На этом уроке мы рассмотрим использование цифро-аналогового преобразователя.
Цифро-аналоговый преобразователь (сокращенно - ЦАП) — это устройство для преобразования цифрового кода (чаще всего – двоичного) в аналоговый сигнал (для микроконтроллера это сигнал напряжения), то есть выполняет функцию, обратную аналого-цифровому преобразователю.
Основными характеристиками цифро-аналогового преобразователя являются его
- разрядность N, которая определяет количество различных аналоговых уровней выходного сигнала 2N,
- диапазон выходных напряжений
- максимальная частота дискретизации – это максимальная частота, при которой ЦАП может работать, выдавая на выходе корректный результат.
Микроконтроллер STM32F303VCT6 содержит в своем составе 12-разрядный модуль цифро-аналогового преобразователя с двумя выходными каналами – это линии PA4 и PA5 соответственно. ЦАП может формировать на выходных каналах сигнал треугольной формы, белый шум или сигнал заданный пользователем.
Давайте создадим новый проект для микроконтроллера STM32F303VCT6, и на вкладке Pinout укажем, что будем использовать выходной канал OUT1 для цифро-аналогового преобразователя. Как видим, выход ЦАП мы можем наблюдать на линии PA4.
Перейдем во вкладку Clock Configuration и укажем, что будем использовать умножитель частоты с коэффициентом 16. Тем самым мы получим внутреннюю частоту тактирования 64МГц. При этом предварительный делитель модуля APB1 установим в значение 2, чтобы обеспечить частоту тактирования этого модуля не более 36МГц.
Перейдем во вкладку Configuration и займемся настройкой модуля цифро-аналогового преобразователя. Давайте для начала попробуем воспроизвести треугольный сигнал на выходе ЦАП. Для этого необходимо установить тип триггера.
В качестве триггера можно выбрать любой из сигналов, приведенных в документации.
Я выберу TIM6 Trigger Out Event. И далее мне предлагается выбрать форму генерируемого сигнала. Мы договорились, что будем генерировать сигнал треугольной формы, поэтому во вкладке Wave generation mode выбираем Triangle wave generation. Дальше нам предлагается задать амплитуду генерируемого сигнала, которая представляет собой значение, равное степени двойки без единицы и лежит в диапазоне от 1 до 212 - 1.
Выберем для примера амплитуду, равную 2047, то есть половине от максимума.
Это означает, что при каждом событии установленного триггера выходное напряжение будет увеличиваться на аналоговую величину, соответствующую вот такому значению.
Эта величина является отношением максимального напряжения к количеству различных уровней аналогового сигнала, которое, в свою очередь представляет собой 2 в степени, соответствующей разрядности ЦАП. И когда выходное значение достигнет величины, соответствующей выбранной амплитуде сигнала, это значение начнет уменьшаться на 1 при каждом событии триггера.
Таким образом, 1 период сигнала на выходе ЦАП будет определяться двойной амплитудой сигнала и периодом таймера, выбранного в качестве триггера.
Ну, а частота, соответственно, будет обратной величиной.
Ну, и поскольку мы выбрали таймер TIM6 в качестве триггера, необходимо настроить его параметры. На вкладке Pinout активируем таймер TIM6 и переходим на вкладку Configuration.
Trigger Event Selection ставим в значение Update Event.
Это событие происходит каждый раз в момент переполнения таймера.
Ну, и нужно установить значение периода таймера. Это значение лежит в диапазоне от 0 до 65535. Допустим, мы хотим получить треугольный сигнал с частотой 50 Гц.
Тогда значение регистра периода для таймера TIM6 должно составлять 312.
Сохраним настройки и, наконец-то, перейдем к проекту в IAR.
Всё, что нам нужно добавить в проект – это запуск таймера TIM6 с помощью функции
И запуск цифро-аналогового преобразователя с помощью функции
которая в качестве аргументов принимает ссылку на дескриптор ЦАП и константу, определяющую номер канала ЦАП:
#define DAC_CHANNEL_2 ((uint32_t)0x00000010) /*!< DAC Channel 2 */
2
3
4
HAL_TIM_Base_Start(&htim6);
HAL_DAC_Start(&hdac, DAC_CHANNEL_1);
/* USER CODE END 2 */
Откомпилируем проект и загрузим в отладочную плату. В данном случае работоспособность программы лучше всего проверить с помощью осциллографа. Вот сигнал на линии PA4, которая является выходом канала ЦАП. Как видим, частота действительно соответствует 50Гц, а амплитуда составляем 1,5В, что является половиной питающего напряжения.
Если мы уменьшим амплитуду треугольного сигнала, допустим, в 2 раза, то и частота этого треугольного сигнала тоже уменьшится в 2 раза. И вот результирующий сигнал на выходе ЦАП.
Как видим, частота стала 100 Гц. А амплитуда уменьшилась в 2 раза.
Верну амплитуду к предыдущему варианту - 2047.
И если необходимо увеличить частоту сигнала, сохраняя его амплитуду, то достаточно уменьшить значение периода таймера, который используется в качестве триггера. Например, мы хотим получить частоту не 50 Гц, а 1кГц.
При этом полученное значение регистра периода округлим до 16. Собираем проект. И вот она – частота 1кГц.
Хочу отметить еще один момент. Сейчас сигнал на выходе АЦП меняется в пределах от примерно 50мВ до 1,5В.
Наличие ненулевого начального значения связано с использованием выходного буфера, который позволяет подключать нагрузку непосредственно к выводу микроконтроллера, без использования внешнего операционного усилителя.
Если мы отключим выходной буфер, то это смещение пропадет. Давайте это проверим.
Вот так выглядит сигнал на выводе PA4 без использования выходного буфера.
Мы можем программно установить начальное значение сигнала на выходе ЦАП с помощью функции
Ей в качестве аргументов передаются ссылка на дескриптор ЦАП, константа, обозначающая номер канала, константа, обозначающая вариант выравнивания значения и само начальное значение. В качестве этого значения установим величину, соответствующую половине питания – 2048.
Согласно документации, ЦАП микроконтроллера поддерживает 3 значения константы выравнивания:
- выравнивание 8-битного значения по правому краю DAC_ALIGN_8B_R
- выравнивание 12-битного значения по левому краю DAC_ALIGN_12B_L
- выравнивание 12-битного значения по правому краю DAC_ALIGN_12B_R
Нам подойдет последний вариант, который задается константой DAC_ALIGN_12B_R, описанной в библиотечном файле stm32f3xx_hal_dac.h.
2
3
4
5
HAL_TIM_Base_Start(&htim6);
HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 2048);
HAL_DAC_Start(&hdac, DAC_CHANNEL_1);
/* USER CODE END 2 */
Добавлена строка 3
Загрузим проект в отладочную плату и посмотрим, как изменилась картинка на осциллографе.
Теперь мы видим, что минимальное напряжение на выходе ЦАП сместилось на отметку 1,5В.
Кстати, если мы не будем формировать треугольный сигнал на выходе ЦАП принудительно, то функция HAL_DAC_SetValue() позволит нам получить заданное аналоговое значение.
Кроме того, микроконтроллер позволяет получить на выходе ЦАП сигнал шума с заданной амплитудой. Для этого вид сигнала устанавливаем в значение Noise Wave Generation, и в появившемся поле Noise Amplitude можем указать количество бит, которые будут формировать произвольные значения для шумового сигнала.
Вот такой шумный сигнал получился. Замечу, что пользовательский код проекта при этом не изменился.
Но, к сожалению, все задачи цифро-аналогового преобразователя не ограничиваются генерацией треугольника, шума или постоянного сигнала. Для формирования других видов аналогового сигнала необходимо использовать пользовательские данные, и этот способ мы рассмотрим уже в следующем уроке.