STM Урок 195. LL. STM32F1. ADC. Injected Once. Запуск по таймеру
Продолжаем работать с АЦП (ADC) контроллера STM32F1 с использованием библиотеки LL. Также работать мы продолжим с инжектированным каналом. Запускать мы будем также наш АЦП на данном уроке автоматически, хотя вернёмся мы в режим однократного преобразования. Как же такое возможно и для чего это нужно?
В режиме кольцевого запуска (continuous) АЦП не может запускаться реже чем через 252 цикла (12,5 + 239,5). Порой бывает нужно запускать АЦП автоматически гораздо реже. Для этого существует у контроллера STM32F1 а АЦП запуск от таймера. Причём запустить наш АЦП мы можем, используя различные события таймера, такие как захват, сравнение и переполнение счётчика.
От таймера мы наш АЦП уже запускали в уроке 188, только работали мы тогда с регулярным каналом. Сегодня же попробуем от таймера запустить инжектированный канал.
Схема наша не изменилась
Проект был сделан из проекта урока 192 с именем LL_ADC_INJ_ONCE и назван LL_ADC_INJ_ONCE_TIM.
Откроем проект в Cobe MX и включим глобальные прерывания в ADC1

Включим таймер 4

Настроим его на период в 1 милисекунду и выберем событие обновления
В свойствах ADC1 выберем срабатывание от нашего таймера

Также не забываем выбрать библиотеку здесь
Сгенерируем проект и откроем его в Keil, настроим автоперезагрузку после прошивки, отключим оптимизацию, подключим к дереву проекта файлы lcd.c и i2c_user.c, откроем main.c и добавим глобальную переменную для хранения сырого значения АЦП
|
1 2 |
/* USER CODE BEGIN PV */ __IO uint16_t ADC_Data; |
В функции main() объявление подобной переменной удалим
__IO uint16_t ADC_Data;
Здесь изменим триггер на таймерный
LL_ADC_INJ_SetTriggerSource(ADC1, LL_ADC_INJ_TRIG_EXT_TIM4_TRGO);
Включим локальные прерывания по событию окончания преобразования
|
1 2 |
LCD_ini(); LL_ADC_EnableIT_JEOS(ADC1); |
Включим бит JEXTTRIG в регистре CR2 при помощи специальной функции
|
1 2 |
LL_ADC_EnableIT_JEOS(ADC1); LL_ADC_INJ_StartConversionExtTrig(ADC1,LL_ADC_INJ_TRIG_EXT_RISING); |
Выведем ещё одну строку на дисплей
|
1 2 3 |
LCD_String("Jnjected Once"); LCD_SetPos(0,2); LCD_String("Timer Ext Trigger"); |
Запустим таймер и немного подождём
|
1 2 3 |
LCD_String("Timer Ext Trigger"); LL_TIM_EnableCounter(TIM4); LL_mDelay(100); |
Добавим функцию, которую будем вызвать из обработчика прерываний от АЦП, в которой считаем значение из регистра АЦП в переменную
|
1 2 3 4 5 |
/* USER CODE BEGIN 4 */ void ADC_ConvCpltCallback(void) { ADC_Data = LL_ADC_INJ_ReadConversionData12(ADC1, LL_ADC_INJ_RANK_1); } |
В файле stm32f1xx_it.c добавим для данной функции прототип
|
1 2 |
/* USER CODE BEGIN PFP */ void ADC_ConvCpltCallback(void); |
Вызовем данную функцию и сбросим флаг в функции-обработчике ADC1_2_IRQHandler
|
1 2 3 4 5 6 |
/* USER CODE BEGIN ADC1_2_IRQn 0 */ if(LL_ADC_IsActiveFlag_JEOS(ADC1) != 0) { LL_ADC_ClearFlag_JEOS(ADC1); ADC_ConvCpltCallback(); } |
В функции main() файла main.c в бесконечном цикле вот это вот всё можем вполне удалить
LL_ADC_INJ_StartConversionSWStart(ADC1);
while (!LL_ADC_IsActiveFlag_JEOS(ADC1)) {}
LL_ADC_ClearFlag_JEOS(ADC1);
ADC_Data = LL_ADC_INJ_ReadConversionData12(ADC1, LL_ADC_INJ_RANK_1);
Соберём код, прошьём контроллер и посмотрим, как работает наш код


Всё работает.
Таким образом, на данном занятии мы научились запускать АЦП контроллера STM32F1 от таймера с использованием инжектированного канала, что позволило нам теперь более гибко и более в широких пределах настраивать период автоматического запуска преобразования.
Всем спасибо за внимание!
Отладочную плату STM32F103C8T6 можно приобрести здесь STM32F103C8T6
Программатор недорогой можно купить здесь ST-Link V2
Переходник I2C to LCD можно приобрести здесьI2C to LCD1602 2004
Логический анализатор 16 каналов можно приобрести здесь
Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)
Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)






Добрый вечер, хотел написать на ваш форум, но не получается зарегистрироваться. Поэтому, сорри, напишу здесь. Во-первых, спасибо большое за работу, которую вы делаете, с удовольствием смотрю ваши ролики даже если тема знакома, очень нравится ваш стиль изложения, спокойный такой. Теперь от комплиментов к делу. ))) Недавно приобрел новые платки в формате BluePill но с stm32f411ceu6, вы наверняка их знаете. Там на обратной стороне платы есть место для SPI Flash типа W32QXX. Ну я и впаял туда 4х-мегабайтную W25Q32. Теперь жеж надо использовать? Попробовал я хранить на ней картинки для отрисовки GUI на ili9341. Все хорошо, залил картинки, читаю, рисую. Но медленно. И подумалось мне, а почему бы не попробовать заделать DMA RX стрим, считывающий с SPI флешки сразу в SPI->DR экранчика. Конечно, предварительно предупредив его, что щас будем писать данные в фреймбаффер. Сказано-сделано. В кубе RX стрим без инкрементирования MEM, и HAL_SPI_Receive_DMA вместо указателя на буфер пишем (uint8_t *)&SPI2->DR. Самое прикольное, что работает. Правда, флешка не умеет читать (или это я дурак) выравненные по HALFWORD, а ili9341 хочет именно это. Поэтому картинка у меня малость испорчена, но если записать на флешку картинку, где после каждого байта rgb565 вставить байт с нулем, тем самым удваивая размер картинки, то все работает офигенно и, что самое главное, моментально.
Вы наверное спросите, нафига я вам все это тут пишу. А вот зачем. Удваивание картинки, конечно, выход, но хреновый. Жаль память. Поэтому я уже неделю бьюсь над проблемой как же подружить DMA экранчика и флешки, а именно их неодинаковые пожелания по выравниванию. Мне не хватает таких глубоких познаний как у вас, поэтому подумал, мож вы чем поможете? Вы, кстати, не поднимали еще проблему DMA из периферии в периферию, насколько я помню. А ведь тема интересная, особенно вышеописанный пример. Как вы считаете?
Пока не загонялся этим. А разве нет Quad SPI у 411-го? почему Вы обычный SPI используете?
Нема QSPI. 5 обычных SPI и 5 I2S, которые на них сидят. Если бы был QSPI, я бы вообще его проадресовал напрямую из ld и рисовал бы как из RAM.
Ну да бог с ним. Вы все-таки сделайте урок по Perif-to-Perif DMA, интересная ведь тема, и не стандартная.
У меня есть такой пример ацп управляет шим каналом через дма только на серии stm32f1 cmsis если хотите свяжитесь по ємайлу rusevdimir@gmail.com
на cmsis