STM Урок 186. LL. STM32F1. ADC. Regular Once. Interrupt
Продолжаем работать с АЦП (ADC) контроллера STM32F1 с использованием библиотеки LL. Также работать мы пока будем с однократным преобразованием и с регулярным каналом, только отследить окончание процесса преобразования мы попробуем при помощи механизма прерываний от АЦП.
Думаю, что сделать это будет не сложно, в чём нам поможет библиотека LL.
Схему мы используем ту же самую, что и в прошлом уроке
Проект наш также сделан из проекта прошлого урока с именем LL_ADC_REG_ONCE и получил новое имя LL_ADC_REG_ONCE_INT.
Откроем наш проект в Cube MX и включим для ADC1 глобальные прерывания
Сгенерируем проект для Keil, откроем его, настроим автоперезагрузку после прошивки, отключим оптимизацию, подключим к дереву проекта файлы lcd.c и i2c_user.c, откроем main.c и посмотрим, что у нас изменилось в инициализации АЦП в результате разрешения глобальных прерываний. Для этого зайдём в тело функции MX_ADC1_Init и посмотрим изменения.
Мы видим вот такие строки, говорящие нам о том, что глобальные прерывания от ADC1 и ADC2 разрешены и им назначен самый высокий приоритет
|
1 2 3 |
/* ADC1 interrupt Init */ NVIC_SetPriority(ADC1_2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); NVIC_EnableIRQ(ADC1_2_IRQn); |
Больше в инициализации ничего не добавилось и не изменилось, поэтому вывод такой: локальные прерывания нам придётся настраивать самим и управлять их обработкой тоже самим.
Сначала добавим глобальную переменную для пользовательского флага, чтобы нам основную часть реакции на событие не организовывать в его обработчике
|
1 2 |
/* USER CODE BEGIN PV */ __IO uint8_t fl_adc; |
В main() перед включением ADC разрешим локальные прерывания по событию окончания преобразования
|
1 2 |
LCD_ini(); LL_ADC_EnableIT_EOS(ADC1); |
Если после этого мы попытаемся собрать код и прошить контроллер, то у нас в бесконечном цикле не выполнится ни одна итерация, так как мы обязаны флаг окончания преобразования ещё и сбросить.
Добавим свой обработчик прерывания, в котором установим наш пользовательский флаг
|
1 2 3 4 5 |
/* USER CODE BEGIN 4 */ void ADC_ConvCpltCallback(void) { fl_adc = 1; } |
В файле stm32f1xx_it.c добавим на данный обработчик прототип
|
1 2 |
/* USER CODE BEGIN PFP */ void ADC_ConvCpltCallback(void); |
А уже в обработчике, добавленным LL, ADC1_2_IRQHandler мы сбрасываем флаг EOS и вызываем наш пользовательский обработчик
|
1 2 3 4 5 6 |
/* USER CODE BEGIN ADC1_2_IRQn 0 */ if(LL_ADC_IsActiveFlag_EOS(ADC1) != 0) { LL_ADC_ClearFlag_EOS(ADC1); ADC_ConvCpltCallback(); } |
И, тем не менее, даже после этого у нас по-прежнему не будет выполняться ни одна итерация в бесконечном цикле, так как мы ждём там установки данного флага, а там мы её никогда не дождёмся.
Вернёмся в функцию main() файла main.c и добавим ещё одну строку на дисплей
|
1 2 3 |
LCD_String("Regular Once"); LCD_SetPos(0,2); LCD_String("Intrrupt"); |
Удалим вот эти строки в бесконечном цикле
while (!LL_ADC_IsActiveFlag_EOS(ADC1)) {}
LL_ADC_ClearFlag_EOS(ADC1);
а вместо них отследим установку нашего пользовательского флага, после чего его сбросим
|
1 2 3 |
LL_ADC_REG_StartConversionSWStart(ADC1); while (!fl_adc) {} fl_adc = 0; |
Вот теперь, если мы соберём код и прошьём наш микроконтроллер, у нас всё будет работать, как и прежде

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





можно без ll
Только я разницы не почувствовал преобразование одиночное и безпрерывное в cmsis