DMA цифро-аналоговое преобразование с микроконтроллером SAM4S: таймер / счетчик
Часть первая в этой серии из трех статей посвящена использованию таймера / счетчика SAM4S для точного управления частотой дискретизации ЦАП.
Вспомогательная информация
- Введение в разработку проекта с помощью Atmel SAM4S Xplained Pro
- Введение в цифро-аналоговое преобразование
Требуемое оборудование / программное обеспечение
- Комплект оценки SAM4S Xplained Pro
- Студия Atmel
Реальный ЦАП
Если вы прочитали мою недавнюю статью, в которой я анализирую производительность цифрового аналого-цифрового преобразователя с широтно-импульсной модуляцией, вы знаете, что PWM ЦАП далеко не впечатляют. Тем не менее, PWM DAC живет, отчасти потому, что (как упоминалось в другой статье по той же теме) многие микроконтроллеры не включают специализированное аппаратное обеспечение ЦАП. Этот относительно распространенный «недостаток ЦАП» — наряду с моим общим нежеланием усложнять дизайн с внешними компонентами, которые были бы совершенно ненужны, если бы производители ИС были настолько добры, чтобы сделать микроконтроллеры именно так, как я их хочу, — объясняет мое большое удовлетворение, когда я найти себя с помощью микроконтроллера, который действительно имеет реальный ЦАП. Это удовлетворение достигает новых высот с помощью устройств серии SAM4S, которые обеспечивают не один, а два аналоговых выхода с цифровым управлением.
Целью этого проекта является генерация синусоидальной волны с использованием модуля ЦАП SAM4S. Эта задача сама по себе достаточно нетривиальна благодаря несколько лабиринтной взаимосвязи между данными SAM4S, Atmel Software Framework (ASF), документацией ASF и фактическим оборудованием микроконтроллера. Несмотря на эту нетривиальность, мы сделаем еще один шаг, подав данные на ЦАП через прямой доступ к памяти (DMA) вместо инструкций ЦП. Мы поговорим больше о DMA в части 3.
Хотя мне нравится смотреть на синусоидальные волны на моем осциллографе, этот проект на самом деле не является самоцелью. Скорее всего, это 1) транспортное средство для изучения важных возможностей SAM4S, а именно точное время / счет, DMA и интегрированное цифро-аналоговое преобразование; и 2) фундамент для других проектов, для которых требуется синхронное цифро-аналоговое преобразование с эффективным ЦП, такое как синтез аудиосигналов или генерация сигналов основной полосы частот для программного обеспечения, определенного радио.
Свободно-беглый или триггерный
Можно использовать ЦАП, просто записав значение в регистр данных преобразования ЦАП. Это называется свободным режимом работы. Аналоговое выходное напряжение обновляется, как только вы записываете данные (на самом деле, 25 часов ЦАП, когда вы записываете данные, больше о деталях аппаратного обеспечения ЦАП в Части 2). Это хорошо для некоторых приложений, но для точного синтеза периодических сигналов (например, синусоиды) нам необходимо убедиться, что все обновления выходного напряжения разделены одинаковыми интервалами. С этой целью мы будем использовать триггерный режим, в котором запись в регистр данных преобразования фактически не изменяет выходное напряжение до тех пор, пока аппаратура ЦАП не будет инициирована отдельным синхронизирующим сигналом. Спецификация SAM4S (стр. 1124) относится к этому триггеру как «внешняя», что несколько вводит в заблуждение. По моему опыту «внешний» обычно означает «внешний для чипа», тогда как в этом случае это означает «внешний для модуля ЦАП». Вот параметры триггерного сигнала:
Мы будем использовать сигнал TIO от таймера / счетчика 1, потому что мы можем удобно зондировать этот сигнал через клемму 1 в ряду сквозных отверстий с надписью «ИНТЕРФЕЙС PIOD»:
Как указано на фотографии, эта клемма 1 подключена к выходу A15, а таблица SAM4S (стр. 52) сообщает нам, что мы можем управлять сигналом TIOA1 на PA15, подключив этот вывод к периферийному B:
«A» после TIO указывает, что это первый из двух выходных сигналов (TIOA и TIOB), которые может генерировать каждый канал таймера / счетчика; «1» после «TIOA» относится к каналу 1 модуля таймера / счетчика, который включает в себя три идентичных независимых канала.
Форма волны против захвата
Канал таймера / счетчика можно настроить для режима осциллограммы или режима съемки. В режиме захвата TIOA и TIOB являются входами; сигнал, подключенный к TIOA или TIOB, может использоваться для указания аппарату таймера / счетчика для хранения текущего значения счетчика в отдельном регистре. Эта функциональность полезна для измерения ширины импульса или задержки между двумя импульсами. Мы, однако, хотим генерировать синхронизирующий сигнал, а не измерять один, поэтому нам нужен режим осциллограммы. Это имя отражает способность таймера / счетчика генерировать множество цифровых сигналов с помощью трех регистров сравнения и разных режимов подсчета. Однако наша задача довольно проста: нам просто нужна квадратная волна с частотой, равной нашей желаемой частоте выборки ЦАП. Таким образом, мы можем использовать режим только для подсчета голосов, и нам нужен только один регистр сравнения.
Первое, что нужно сделать, это выбрать часы, которые будут вести регистр счетчика. Вот варианты:
Мы сконфигурируем микроконтроллер для частоты основного тактового генератора (MCK) 96 МГц; причина этого будет объяснена в Части 2. Требуемая частота выборки ЦАП составляет 1 МГц, а MCK / 8 (т. е. 12 МГц) является хорошим выбором для генерации триггера DAC с частотой 1 МГц, поскольку требуемое значение делителя является целым числом.
Теперь, когда мы знаем частоту источника синхронизации для счетчика, нам нужно выбрать правильное значение для «Register C», сокращенно RC. Этот довольно критически названный регистр может использоваться для сброса счетчика, когда он достигает значения, содержащегося в RC, следующим образом:
Итак, если мы установим биты WAVESEL в регистр «Режим канала TC» в двоичный 10, а затем загрузим правильное значение сравнения в RC, у нас будет счетчик, который сбрасывается и начинает отсчет с 0, когда значение счетчика равно RC. Остается только сказать таймер / счетчик канала, чтобы изменить логический уровень TIOA каждый раз, когда это совпадение происходит. Мы делаем это с помощью поля ACPC в регистре режима канала:
Мы будем использовать опцию переключения. Следующая диаграмма передает связь между значением сравнения RC и формой волны, генерируемой на TIOA.
Прошивка
Теперь пришло время перевести весь этот таймер / встречный бизнес в код, и для этого мы поворачиваем (как обычно) к ASF. Во-первых, давайте добавим все модули ASF, которые нам понадобятся для всего проекта:
Модули, подчеркнутые зеленым цветом, это те, которые вам нужно добавить (остальные автоматически включаются Atmel Studio).
Затем мы имеем два определения препроцессора:
Первый прикрепляет имя к выводу A15, а второй позволяет нам ссылаться на канал таймера / счетчика 1 с TC0_CHANNEL1 вместо более менее информативного числа 1.
Затем нам нужно включить периферийные часы для таймера / счетчика. Здесь есть подробная информация, которую я считаю довольно запутанной, поэтому обратите внимание на следующее обсуждение — это может помочь вам избежать неприятных разочарований. Путаница связана с вопросом о том, какой периферийный идентификатор используется с функцией pmc_enable_periph_clk (). На мой взгляд, очевидным ответом является ID_TC0, потому что мы работаем с каналом 1 в модуле таймера / счетчика 0 . Эта реальность отражается в функции инициализации канала таймера / счетчика, tc_init () — первым аргументом является TC0 или TC1 (ссылаясь на модуль таймера / счетчика 0 или модуль 1), а второй аргумент — номер канала. Естественно, что периферийный идентификатор должен соответствовать самому периферийному модулю, а не одному из каналов внутри модуля. Но, как вы, наверное, догадались, такого не происходит. Как оказалось, периферийные часы включены или отключены для отдельных каналов таймера. Чтобы усугубить путаницу, данные SAM4S (стр. 50) относятся к этим каналам следующим образом:
Таким образом, с периферийными идентификаторами у нас есть канал таймера / счетчика с 0 по 5, тогда как в другом месте у нас есть модуль таймера / счетчика канал от 0 до 2 и модуль 1 таймера / счетчика 1 канал от 0 до 2 . Так или иначе, просто помните, что вам нужно включить периферийные часы для каждого используемого вами канала таймера / счетчика, с периферийными идентификационными каналами 0-2, соответствующими каналам 0-2 модуля 0, и периферийными идентификационными каналами 3-5, соответствующими модуль 1 канал 0-2.
После включения периферийных часов через pmc_enable_periph_clk (ID_TC1) мы настраиваем канал таймера / счетчика:
С помощью функции tc_init () вы сначала указываете модуль таймера / счетчика и канал внутри модуля, затем вы используете логический оператор OR вместе с определениями препроцессора ASF (см. «Tc.h»), чтобы указать правильные значения для того, поля должны быть изменены в регистре режима канала. Как указано в комментариях в приведенном выше отрывке кода, мы настраиваем канал для
- MCK / 8 источник синхронизации,
- режим формы волны,
- только с автоматическим сбросом, когда значение счетчика равно RC, и
- TIOA переключается, когда значение счетчика равно RC.
Из приведенной выше диаграммы мы знаем, что значение в RC должно составлять 6 для создания тактовой частоты 1 МГц:
Теперь все, что нам нужно сделать, это включить таймер / счетчик канала с вызовом tc_start ():
Результаты и выводы
Вы можете использовать следующую ссылку для загрузки исходных файлов и файлов проекта для этого этапа проекта:
Файлы источника и проекта
Вот захват области результирующей формы волны:
Теперь, когда у нас есть сигнал с частотой дискретизации так, как мы этого хотим, мы готовы запустить ЦАП. В следующей статье мы рассмотрим периферийное устройство контроллера SAC4S (DACC), электрические характеристики самого ЦАП и модуль DACC ASF.
Следующая статья в серии: Понимание и использование цифрового преобразователя SAM4S