Продолжаем работать с АЦП (ADC) контроллера STM32F1 с использованием библиотеки LL. Также работать мы продолжим с инжектированной группой каналов и отслеживать окончание процесса преобразования мы также будем при помощи механизма прерываний от АЦП, только в данном уроке мы попробуем уже поработать не с однократным преобразованием, которое нужно каждый раз в каждой итерации заново запускать, а применим автоматический механизм запуска.
С данным режимом мы работали неоднократно, поэтому нам разобраться с данной темой и применить её в использовании режима SCAN будет несложно.
Схема наша также осталась прежней
Проект мы сделаем из проекта прошлого урока с именем LL_ADC_INJ_ONCE_SCAN_INT и назовём его LL_ADC_INJ_CONT_SCAN_INT.
Откроем наш проект в Cube MX и в свойствах ADC1 включим кольцевой (автоматический) режим преобразования сигнала, а также для того, чтобы преобразования запускались не слишком часто, установим наибольший интервал между выборками
Сгенерируем проект и откроем его в Keil, настроим автоперезагрузку после прошивки, отключим оптимизацию, подключим к дереву проекта файлы lcd.c и i2c_user.c, откроем main.c и удалим объявление глобального флага
__IO uint8_t fl_adc;
Вместо него добавим массив для сырых значений каналов ADC
1 2 |
/* USER CODE BEGIN PV */ __IO uint16_t ADC_Data[4]; |
А в функции main() мы такой же, но локальный, массив удалим
__IO uint32_t wait_loop_index = 0;
__IO uint16_t ADC_Data[4];
Из тела функции, играющей роль обработчика прерываний по флагу окончания преобразования ADC_ConvCpltCallback удалим установку пользовательского флага
fl_adc = 1;
Вместо этого мы здесь считаем значения из регистров каналов ADC1
1 2 3 4 5 6 |
void ADC_ConvCpltCallback(void) { ADC_Data[0] = LL_ADC_INJ_ReadConversionData12(ADC1, LL_ADC_INJ_RANK_1); ADC_Data[1] = LL_ADC_INJ_ReadConversionData12(ADC1, LL_ADC_INJ_RANK_2); ADC_Data[2] = LL_ADC_INJ_ReadConversionData12(ADC1, LL_ADC_INJ_RANK_3); ADC_Data[3] = LL_ADC_INJ_ReadConversionData12(ADC1, LL_ADC_INJ_RANK_4); |
В функции main() включим режим Continuous
1 2 3 |
LL_ADC_DeInit(ADC1); //Set ADC continuous conversion mode on ADC group regular LL_ADC_REG_SetContinuousMode(ADC1, LL_ADC_REG_CONV_CONTINUOUS); |
Почему мы включаем данный режим для регулярной группы, я расскажу чуть позже, я это рассказывал только в видеоверсии подобного урока по однократному преобразованию.
А здесь исправим количество циклов между выборками
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_4, LL_ADC_SAMPLINGTIME_239CYCLES_5);
Вызовем функцию, которая включит автоматический запуск инжектированной группы после регулярной. Данная функция установит бит JAUTO в регистре CR1. Хотя у нас регулярная группа не задействована, но без этого работать не будет, так как мы режим Continuous используем именно для регулярной группы, так как она пустая, то после процесса такого пустого преобразования регулярной группы засчёт данной настройки сразу же и запустится процесс конвертирования значений каналов инжектированной группы
1 2 3 |
LL_ADC_SetSequencersScanMode(ADC1, LL_ADC_SEQ_SCAN_ENABLE); //Set ADC group injected conversion trigger LL_ADC_INJ_SetTrigAuto(ADC1, LL_ADC_INJ_TRIG_FROM_GRP_REGULAR); |
Исправим надпись на дисплее здесь
LCD_String("Jnjected Continuous");
Стартуем наш АЦП до бесконечного цикла и тут можно подождать немного, так как мы процесс окончания преобразования теперь не отслеживаем и в первой итерации рискуем поэтому получить какое-то случайное значение, которое ещё не записалось в нашу переменную
1 2 3 |
LCD_String("Scan Interrupt"); LL_ADC_INJ_StartConversionSWStart(ADC1); LL_mDelay(100); |
А вот это всё теперь удаляем из бесконечного цикла
LL_ADC_INJ_StartConversionSWStart(ADC1);
while (!fl_adc) {}
fl_adc = 0;
ADC_Data[0] = LL_ADC_INJ_ReadConversionData12(ADC1, LL_ADC_INJ_RANK_1);
ADC_Data[1] = LL_ADC_INJ_ReadConversionData12(ADC1, LL_ADC_INJ_RANK_2);
ADC_Data[2] = LL_ADC_INJ_ReadConversionData12(ADC1, LL_ADC_INJ_RANK_3);
ADC_Data[3] = LL_ADC_INJ_ReadConversionData12(ADC1, LL_ADC_INJ_RANK_4);
Собираем код, прошиваем контроллер и смотрим как у нас всё работает
Всё работает отлично!
Итак, на данном занятии мы освоили механизм автоматического запуска преобразований инжектированной группы каналов АЦП, применяя при этом также режим сканирования последовательности каналов, что позволило нам ещё более разгрузить основной код.
Всем спасибо за внимание!
Предыдущий урок Программирование МК STM32 Следующий урок
Отладочную плату STM32F103C8T6 можно приобрести здесь STM32F103C8T6
Программатор недорогой можно купить здесь ST-Link V2
Переходник I2C to LCD можно приобрести здесьI2C to LCD1602 2004
Логический анализатор 16 каналов можно приобрести здесь
Смотреть ВИДЕОУРОК (нажмите на картинку)
Добавить комментарий