Урок 21
HAL. ADC. Regular Channel. Trigger
Проект создаём из ADC_REGULAR, называем его ADC_REGULAR_TRIGGER.
Запускаем Cube. Добавим 2 таймер, включив в нем внутреннее тактирование. Включим также PD12 на выход. Затем зайдём в Clock Configuration и посмотрим частоту на этот таймер (стр 67 Ref Manual). Она 21000, поэтому заходим в закладку Configuration и включаем там делитель 20999 и период 3000, а в последней строке Update Event, таким образом мы настроили таймер на период 3 секунды, также необходимо включить у таймера прерывания. Заходим в АЦП, выключим там прерывания. А в 1 закладке включим триггер
Генерируем проект, открываем его, настроим программатор, подключим файл lcd.c и соберем код.
Убавим задержки, очистим дисплей, стартуем таймер и АЦП в главной функции.
LCD_String(str);
HAL_Delay(500);
LCD_Clear();
LCD_SetPos(4, 0);
LCD_SendChar('s');
LCD_SetPos(8, 1);
LCD_SendChar('t');
LCD_SetPos(12, 2);
LCD_SendChar('m');
LCD_SetPos(16, 3);
LCD_SendChar('3');
LCD_SendChar('2');
HAL_Delay(500);
LCD_Clear();
HAL_TIM_Base_Start_IT(&htim2);
HAL_ADC_Start(&hadc1);
Добавим функцию для обработки прерывания таймеру по флагу совпадения (стр 842 мануала библиотеки HAL) и будем там менять состояние светодиода
/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim2)
{
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);
}
/* USER CODE END 4 */
Теперь возьмём данные из АЦП и покажем их на дисплее. Ничего для этого особенного делать не нужно. Нужно только закомментировать там ненужный код и убавить немного задержку.
while (1)
{
// HAL_ADC_Start(&hadc1);//запустим аналогово-цифровое преобразование
// HAL_ADC_PollForConversion(&hadc1,100);//дождёмся окончания преобразований
u=((float)HAL_ADC_GetValue(&hadc1))*3/4096;//занесём результат преобразований в переменную
// HAL_ADC_Stop(&hadc1);//остановим преобразования
sprintf(str,»%.2fv»,u);//преобразуем результат в строку
LCD_SetPos(0,3);//покажем результат на ЖКИ-дисплее
LCD_String(str);
HAL_Delay(100);//задержка перед следующим циклом
/* USER CODE END WHILE */
Компилируем. Прошиваем. Смотрим результаты.
Предыдущий урок Программирование МК STM32 Следующий урок
Отладочную плату и дисплей можно приобрести здесь:
Смотреть ВИДЕОУРОК
Здравствуйте. А Вы не пробовали с помощью триггера запускать АЦП в режиме DMA? Интересует, где именно необходимо задавать массив для сохранения значений через ПДП. В стандартном исполнении мы задаем массив при старте ПДП HAL_ADC_Start_DMA(), но т.к. у нас он запускается по триггеру, непонятно где указывать этот массив. Спасибо.
Я думаю, это вопрос не только ко мне. Здесь посетителей уже немало, я подсчитывал. Я лично, к сожалению не пробовал. Думаю, кто-то пробовал. И он непременно напишет.
К сожалению, так и не удалось найти ответ на свой вопрос. А Вы не подскажите, как работает режим ПДП Circular, т.е. работа ПДП идет непрерывная или только как поступил какой-то запрос?
Мне интересно, что будет больше нагружать процессор, если я по таймеру каждые 100мс буду через прерывание запускать АЦП с ПДП или по триггеру без прерываний буду запускать АЦП, но при этом ПДП будет в режме Circular?
Жаль.
Если бы я точно знал ответ на вопрос, то ответил бы. давно не ковырялся с АЦП.
Приветствую. Я пробовал через DMA. В основной программе после запуска таймера запускаем АЦП через DMA следующей командой:
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)buffer, 5);
А сам массив uint16_t buffer[5] объявляем в начале основной программы main. В результате DMA считает 5 выборок данных из регистра DR ADC1 в наш массив после каждого преобразования.
В режиме ПДП Circular ПДП переносит данные из периферии в память непрерывно, но по запросу. Соответственно запросы к DMA от АЦП тоже должны идти непрерывно, поэтому hadc1.Init.DMAContinuousRequests = ENABLE;
Зачем нужен особый обработчик прерывания таймера? Почему нельзя использовать штатный TIM2_IRQHandler(void) в файле it.c?
Данный обработчик, который в файле, отреагирует сразу на все типы прерываний таймера, а библиотечный — только на одно, то, которое нам нужно.
Также нужно, чтобы HCLK совпадала с частотой АЦП
Здраствуйте, а вы пробывали запускать АЦП в режиме injected по таймеру, просто сейчас пробую поставил все режимы, однако, не идет и все.