Продолжаем работать с АЦП (ADC) контроллера STM32F1 с использованием библиотеки LL. Также работать мы пока будем с регулярными каналами с использованием периферии DMA, только в данном уроке мы попробуем уже поработать не с однократным преобразованием, которое нужно каждый раз в каждой итерации заново запускать, а применим автоматический механизм запуска при помощи режима Continuous.
С данным режимом мы уже знакомы из урока 187, поэтому написать нам код будет не так сложно. Также мы уже не будем исследовать изменения в инициализации ADC, так как мы уже знаем, что там и где изменится.
Схема урока осталась без изменений с прошлого урока
Проект также был сделан из проекта прошлого урока с именем LL_ADC_REG_DMA и получил новое имя LL_ADC_REG_CONT_DMA.
Откроем наш проект в Cube MX и в свойствах ADC1 включим кольцевой (автоматический) режим преобразования сигнала Continuous
Также для того, чтобы наши преобразования не происходили слишком часть, количество циклов преобразования значения последнего канала добавим до максимума
Сгенерируем проект и откроем его в Keil, настроим автоперезагрузку после прошивки, отключим оптимизацию, подключим к дереву проекта файлы lcd.c и i2c_user.c, откроем main.c и удалим в выводе на дисплей лишнее слово
LCD_String(«Regular Once DMA»);
Обозначим наш режим в третьей строке дисплея
1 2 |
LCD_SetPos(0,2); LCD_String("Continuous"); |
Затем вызовем функцию старта ADC в функции main() до бесконечного цикла
1 2 |
LCD_String("Continuous"); LL_ADC_REG_StartConversionSWStart(ADC1); |
А из бесконечного цикла запуск удалим, так как он будет происходить автоматически
/* USER CODE BEGIN 3 */
LL_ADC_REG_StartConversionSWStart(ADC1);
В принципе, вот он весь и код, только давайте подумаем, что будем делать с нашим флагом, ведь у нас же автозапуск ADC.
Здесь самая главная задача — исключить одновременное обращение к элементам массива ADC_Data, так как он у нас используется периферией DMA на запись, и в тот же самый момент мы рискуем обратиться к нему на считывание в момент преобразования данных значений в вольты. При автоматическом запуске АЦП у нас наш флаг к следующей итерации бесконечного цикла будет уже точно установлен и смысл нашего цикла ожидания его установки теряется полностью. Поэтому нужно будет флаг обнулять не после ожидания его установки, а до этого самого ожидания, поэтому перенесём сброс флага выше
fl_adc = 0;
while (!fl_adc) {}
fl_adc = 0;
Далее ещё один будет вопрос, причём очень важный вопрос. Нужно посчитать время преобразования, это будет время от одного прерывания DMA до другого. Для чего это нужно?
Когда мы дождёмся установки флага и будем преобразовывать сырые значения каналов АЦП в вольты, то на это уйдёт также некое время. Нам нужно выяснить то, что это время будет меньше, чем время преобразования аналогового сигнала в цифровой у АЦП, чтобы весь процесс преобразования в вольты закончился до начала новой конверсии АЦП и не произошло того самого одновременного обращения к элементам массива.
Посчитать это несложно. Первые 3 канала у нас настроены на 7,5 циклов между выборками, надо будет к каждому ещё добавить по 12, циклов и мы получим общее время преобразования этих трёх каналов в циклах, это будет 60 циклов. Время преобразования четвёртого цикла 239,5+12,5=252. Значит общее время преобразования всех каналов 312 циклов. АЦП наш тактируется частотой 12 мегагерц, поэтому делим 12 мегагерц на 312, получаем примерно 38,5 килогерц частоту. Теперь нам несложно вычислить период одного преобразования АЦП в микросекундах, разделив единицу на 38,5 килогерц, получим примерно 26 микросекунд.
От момента входа в обработчик прерывания от DMA до момента окончания преобразования сырого значения в вольты и в строку проходит около 20 микросекунд, что несложно подсчитать с помощью точек останова, поэтому всё мы успеваем. Если бы не успевали, то можно это исправить добавлением количества циклов между выборками в других каналах.
Соберём код, прошьём контроллер и посмотрим результат.
Всё работает
Итак, сегодня мы научились работать с ADC с каналами Regular с применением периферии DMA, используя при этом режим автоматического запуска ADC — Continuous.
Всем спасибо за внимание!
Предыдущий урок Программирование МК STM32 Следующий урок
Отладочную плату STM32F103C8T6 можно приобрести здесь STM32F103C8T6
Программатор недорогой можно купить здесь ST-Link V2
Переходник I2C to LCD можно приобрести здесьI2C to LCD1602 2004
Логический анализатор 16 каналов можно приобрести здесь
Смотреть ВИДЕОУРОК (нажмите на картинку)
Добавить комментарий