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 и добавим глобальную переменную для хранения сырого значения АЦП

 

 

В функции main() объявление подобной переменной удалим

 

__IO uint16_t ADC_Data;

 

Здесь изменим триггер на таймерный

 

LL_ADC_INJ_SetTriggerSource(ADC1, LL_ADC_INJ_TRIG_EXT_TIM4_TRGO);

 

Включим локальные прерывания по событию окончания преобразования

 

 

Включим бит JEXTTRIG в регистре CR2 при помощи специальной функции

 

 

Выведем ещё одну строку на дисплей

 

 

 

Запустим таймер и немного подождём

 

 

Добавим функцию, которую будем вызвать из обработчика прерываний от АЦП, в которой считаем значение из регистра АЦП в переменную

 

 

В файле stm32f1xx_it.c добавим для данной функции прототип

 

 

Вызовем данную функцию и сбросим флаг в функции-обработчике ADC1_2_IRQHandler

 

 

В функции 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 от таймера с использованием инжектированного канала, что позволило нам теперь более гибко и более в широких пределах настраивать период автоматического запуска преобразования.

Всем спасибо за внимание!

 

 

Предыдущий урок Программирование МК STM32 Следующий урок

 

Исходный код

 

 

Отладочную плату STM32F103C8T6 можно приобрести здесь STM32F103C8T6

Программатор недорогой можно купить здесь ST-Link V2

Дисплей LCD 16×2

Переходник I2C to LCD можно приобрести здесьI2C to LCD1602 2004

Логический анализатор 16 каналов можно приобрести здесь

 

 

 

Смотреть ВИДЕОУРОК (нажмите на картинку)

 

STM LL. STM32F1. ADC. Injected Once. Запуск по таймеру

5 комментариев на “STM Урок 195. LL. STM32F1. ADC. Injected Once. Запуск по таймеру
  1. Lymes:

    Добрый вечер, хотел написать на ваш форум, но не получается зарегистрироваться. Поэтому, сорри, напишу здесь. Во-первых, спасибо большое за работу, которую вы делаете, с удовольствием смотрю ваши ролики даже если тема знакома, очень нравится ваш стиль изложения, спокойный такой. Теперь от комплиментов к делу. ))) Недавно приобрел новые платки в формате 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 из периферии в периферию, насколько я помню. А ведь тема интересная, особенно вышеописанный пример. Как вы считаете?

  2. Lymes:

    Нема QSPI. 5 обычных SPI и 5 I2S, которые на них сидят. Если бы был QSPI, я бы вообще его проадресовал напрямую из ld и рисовал бы как из RAM.
    Ну да бог с ним. Вы все-таки сделайте урок по Perif-to-Perif DMA, интересная ведь тема, и не стандартная.

  3. ivan rusev:

    У меня есть такой пример ацп управляет шим каналом через дма только на серии stm32f1 cmsis если хотите свяжитесь по ємайлу rusevdimir@gmail.com

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*