STM32. Работа с АЦП через DMA
В этой статье, на примере получения данных от модуля АЦП, мы продемонстрируем вам базовые возможности технологии DMA – Direct Memory Access (прямой доступ к памяти) .
В общем случае, процессор, действуя по инструкциям из основной памяти, общается по шине данных с периферийными устройствами микроконтроллерной системы. Получение данных с АЦП при этом, происходит в следующей последовательности:
- Конфигурация АЦП
- Ожидание результата преобразования
- Считывание результата преобразования
- Запись результата преобразования в память
- Использование результата преобразования
На первый взгляд, это простой вариант, но есть более элегантные способы получения данных от АЦП и других периферийных модулей.
Технология DMA позволяет организовать прямой трансфер данных от интересующего модуля, сразу в память контроллера, без использования ресурсов процессора.
Мы не будем погружаться в технические тонкости. Сейчас нас интересует результат. А точнее то, как этого добиться с использованием конфигуратора CubeMX и HAL-драйвера.
Подготовка аппаратного обеспечения
В этом примере мы будем использовать микроконтроллер STM32L052K8T6. Отладочную плату с этим микроконтроллером можно приобрести в нашем магазине, но также можно использовать многие другие контроллеры, в том числе, в составе отладочных плат.
Нас будет интересовать получение данных с двух каналов АЦП сразу, передача данных через UART и прошивка контроллера через SWD-интерфейс. Мы подключили два переменных резистора к выводам PA4, PA5 (для изменения напряжения на выводах от нуля до напряжения питания), USB-to-COM-преобразователь и программатор STLink.
Подготовка CubeMX
На первой вкладке, Pinout, включаем 4ый и 5ый канал АЦП. Также сразу запускаем USART1 в асинхронном режиме и включаем SWD-интерфейс (SYS -> Debug Serial Wire). Все должно быть как на картинке ниже:
Вкладку Clock Configuration оставляем без изменений:
Далее переходим на вкладку Configuration. Здесь нам потребуется настроить все включенные модули и DMA. Отдельно останавливать на работе с UART мы не будем, так как разбирали этот вопрос в предыдущей статье.
В параметрах АЦП устанавливаем настройки как на картинке. Важно выбрать источник тактирования (Clock Prescaler), установить режим непрерывного преобразования (Continuous Conversion Mode) и разрешить запросы от DMA (DMA Continuous Requests).
Далее откройте меню конфигурации DMA и добавьте поток (кнопка Add).
В списке появится новый пункт. Нажмите на выпадающий пункт меню Select и выберите источником модуль АЦП (ADC). Тут же установите циклический режим запросов (Circular), инкремент адреса памяти и для слова. Все должно быть так, как показано на рисунке ниже:
Обратите внимание на пункт на стройки прерываний NVIC. Cube автоматически включил прерывания от DMA:
На этом подготовка проекта завершена. Можно сгенерировать код и открыть проект в Keil.
Написание кода в Keil
Фактически, CubeMX за нас уже проделал всю работу. Все что нам осталось, это запустить АЦП в режиме DMA и указать область памяти, в которую будет складываться результат преобразования. Для просмотра результата, мы будем отправлять данные в сыром виде в UART два раза в секунду.
Структура adc содержит два поля данных. Для этих целей можно было использовать массив, или обычную переменную, но мы предпочли именно такой способ выделения памяти.
Далее, вызывается встроенная функция драйвера HAL_ADC_Start_DMA();. Для работы она требует:
- &hadc — указатель на структуру данных, описывающую настройки модуля АЦП. Cube сгенерировал ее автоматически
- (uint32_t)&adc — указатель на область памяти для хранения результата преобразования с приведением типов данных в 32х-битный формат
- 2 — количество данных для трансфера
Все. Далее осталось завести буфер, формировать сообщения для отправки, отправлять их и смотреть в реальном времени, как изменяются данные на разных каналах. Сам процесс вывода данных мы уже рассматривали в предыдущей статье.
Заключение
В итоге мы добились того, что в программе у нас есть набор переменных, которые содержат актуальные значения преобразований. Обратите внимание, что мы почти не нагружаем ни сам процессор, ни систему прерываний. Возможно это самый простой способ получения данных с нескольких каналов АЦП.
Также, библиотека для работы с модулем АЦП позволяет работать в режиме однократного преобразования, в режиме прерываний, а некоторые контроллеры поддерживают работу с, так называемыми "инжектированными каналами". Но об этом мы поговорим уже в следующих статьях цикла.
Ссылки на остальные статьи цикла можно найти здесь.
Мы будем очень рады, если вы поддержите наш ресурс и посетите магазин наших товаров shop.customelectronics.ru.