CUSTOMELECTRONICS.RU
Информационно-учебный блог о разработке электроники
Эл. почта: info@customelectronics.ru

STM32. Работа с АЦП через DMA

В этой статье, на примере получения данных от модуля АЦП, мы продемонстрируем вам базовые возможности технологии DMA – Direct Memory Access (прямой доступ к памяти) .
В общем случае, процессор, действуя по инструкциям из основной памяти, общается по шине данных с периферийными устройствами микроконтроллерной системы. Получение данных с АЦП при этом, происходит в следующей последовательности:

  1. Конфигурация АЦП
  2. Ожидание результата преобразования
  3. Считывание результата преобразования
  4. Запись результата преобразования в память
  5. Использование результата преобразования

На первый взгляд, это простой вариант, но есть более элегантные способы получения данных от АЦП и других периферийных модулей.
Технология DMA позволяет организовать прямой трансфер данных от интересующего модуля, сразу в память контроллера, без использования ресурсов процессора.
Мы не будем погружаться в технические тонкости. Сейчас нас интересует результат. А точнее то, как этого добиться с использованием конфигуратора CubeMX и HAL-драйвера.

Подготовка аппаратного обеспечения

В этом примере мы будем использовать микроконтроллер STM32L052K8T6. Отладочную плату с этим микроконтроллером можно приобрести в нашем магазине, но также можно использовать многие другие контроллеры, в том числе, в составе отладочных плат.
Нас будет интересовать получение данных с двух каналов АЦП сразу, передача данных через UART и прошивка контроллера через SWD-интерфейс. Мы подключили два переменных резистора к выводам PA4, PA5 (для изменения напряжения на выводах от нуля до напряжения питания), USB-to-COM-преобразователь и программатор STLink.

Подготовка CubeMX

На первой вкладке, Pinout, включаем 4ый и 5ый канал АЦП. Также сразу запускаем USART1 в асинхронном режиме и включаем SWD-интерфейс (SYS -> Debug Serial Wire). Все должно быть как на картинке ниже:
01 - Cube Pinout
Вкладку Clock Configuration оставляем без изменений:
02 - Cube Clock Conf
Далее переходим на вкладку Configuration. Здесь нам потребуется настроить все включенные модули и DMA. Отдельно останавливать на работе с UART мы не будем, так как разбирали этот вопрос в предыдущей статье.
В параметрах АЦП устанавливаем настройки как на картинке. Важно выбрать источник тактирования (Clock Prescaler), установить режим непрерывного преобразования (Continuous Conversion Mode) и разрешить запросы от DMA (DMA Continuous Requests).
03 - Cube ADC Conf
Далее откройте меню конфигурации DMA и добавьте поток (кнопка Add).
В списке появится новый пункт. Нажмите на выпадающий пункт меню Select и выберите источником модуль АЦП (ADC). Тут же установите циклический режим запросов (Circular), инкремент адреса памяти и для слова. Все должно быть так, как показано на рисунке ниже:
04 - Cube DMA Conf
Обратите внимание на пункт на стройки прерываний NVIC. Cube автоматически включил прерывания от DMA:
05 - Cube NVIC Conf
На этом подготовка проекта завершена. Можно сгенерировать код и открыть проект в Keil.

Написание кода в Keil

Фактически, CubeMX за нас уже проделал всю работу. Все что нам осталось, это запустить АЦП в режиме DMA и указать область памяти, в которую будет складываться результат преобразования. Для просмотра результата, мы будем отправлять данные в сыром виде в UART два раза в секунду.
06 - Keil Program
Структура adc содержит два поля данных. Для этих целей можно было использовать массив, или обычную переменную, но мы предпочли именно такой способ выделения памяти.
Далее, вызывается встроенная функция драйвера HAL_ADC_Start_DMA();. Для работы она требует:

  • &hadc — указатель на структуру данных, описывающую настройки модуля АЦП. Cube сгенерировал ее автоматически
  • (uint32_t)&adc — указатель на область памяти для хранения результата преобразования с приведением типов данных в 32х-битный формат
  • 2 — количество данных для трансфера

Все. Далее осталось завести буфер, формировать сообщения для отправки, отправлять их и смотреть в реальном времени, как изменяются данные на разных каналах. Сам процесс вывода данных мы уже рассматривали в предыдущей статье.

Заключение

В итоге мы добились того, что в программе у нас есть набор переменных, которые содержат актуальные значения преобразований. Обратите внимание, что мы почти не нагружаем ни сам процессор, ни систему прерываний. Возможно это самый простой способ получения данных с нескольких каналов АЦП.
Также, библиотека для работы с модулем АЦП позволяет работать в режиме однократного преобразования, в режиме прерываний, а некоторые контроллеры поддерживают работу с, так называемыми "инжектированными каналами". Но об этом мы поговорим уже в следующих статьях цикла.

Ссылки на остальные статьи цикла можно найти здесь.
Мы будем очень рады, если вы поддержите наш ресурс и посетите магазин наших товаров shop.customelectronics.ru.

Метки: , , , , , Просмотров: 3329