В данном занятии мы поработаем с механизмом обработки прерываний от шины USART.
С прерываниями данными мы уже с вами знакомы из урока 14, только использовали мы при этом библиотеку HAL. Теперь нам предстоит работа с библиотекой LL, что не является сильно простой задачей, но так как в уроке 161 мы полностью познакомились с аппаратной частью шины USART, со всеми битами всех её регистров, то мы с нашей задачей обязательно справимся.
Схема наша также не изменилась, поэтому можем смело приступить к практической части урока.
Проект занятия был сделан из проекта прошлого урока с именем LL_USART_RX и имя ему было присвоено LL_USART_INT.
Откроем проект в Cube MX и включим прерывания на шине USART1
Сгенерируем проект, откроем его в Keil, подключим библиотеку для драйвера индикатора max7219.c, настроим программатор на автоперезагрузку и уберём оптимизацию.
Зайдём в тело функции MX_USART1_UART_Init и увидим, что у там выставился уровень приоритета глобальных прерываний USART1, а также включились данные глобальные прерывания
1 2 3 |
/* USART1 interrupt Init */ NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0)); NVIC_EnableIRQ(USART1_IRQn); |
Добавим две глобальные переменные
1 2 3 |
char rx_str[30], tx_str[30], tmp_str[10]; uint8_t fl=0; uint8_t dt1; |
Добавим функцию для обработки прерываний, в которой установим пользовательский флаг и заберём данные из регистра DT
1 2 3 4 5 6 |
/* USER CODE BEGIN 4 */ void USART1_RX_Callback(void) { dt1 = LL_USART_ReceiveData8(USART1); fl=1; } |
Как мы помним, что для того, чтобы сбросить флаг прерывания по заполнению буфера приёма, мы должны считать регистр DR. Поэтому мы здесь его и читаем, заодно сохраняя данные для последующего использования.
Перейдём в файл stm32f1xx_it.c и добавим прототип на нашу пользовательскую функцию обработки прерывания
1 2 |
/* USER CODE BEGIN PFP */ void USART1_RX_Callback(void); |
В обработчике прерываний USART1_IRQHandler обработаем установки всех нужных флагов
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
/* USER CODE BEGIN USART1_IRQn 0 */ if(LL_USART_IsActiveFlag_RXNE(USART1) && LL_USART_IsEnabledIT_RXNE(USART1)) { USART1_RX_Callback(); } else { if(LL_USART_IsActiveFlag_ORE(USART1)) { (void) USART1->DR; } else if(LL_USART_IsActiveFlag_FE(USART1)) { (void) USART1->DR; } else if(LL_USART_IsActiveFlag_NE(USART1)) { (void) USART1->DR; } } |
При обнаружении установленных флагов различных ошибок мы читаем регистр DR, что является условием их сброса. В случае использования (void) данные считаются в регистр АЛУ и никуда дальше не пойдут, что обеспечит меньше машинных циклов для обработки прерывания
Если бы мы писали данную программу на ассемблере, то, скорее всего, достаточно было бы одной инструкции.
А при обнаружении установленного флага RXNE мы отправляемся в пользовательский обработчик.
Вернёмся в файл main.c и в функции main() включим прерывания по заполнению буфера, а также при обнаружении тех или иных ошибок в работе шины
1 2 3 |
Number_7219(87654321); LL_USART_EnableIT_RXNE(USART1); LL_USART_EnableIT_ERROR(USART1); |
Также нам надо будет немного переделать функцию приёма и передачи USART_RX_TX_Str.
Удалим оттуда код чтения буфера приёма, причём в обоих местах
while (!LL_USART_IsActiveFlag_RXNE(USART1)) {}
rx_dt[ind] = (uint8_t)(USART1->DR & 0x00FF);
И заменим вот на это (также в обоих местах)
1 2 3 4 |
uint16_t ind = 0; while (!fl) {} fl=0; rx_dt[ind] = dt1; |
1 2 3 4 |
ind++; while (!fl) {} fl=0; rx_dt[ind] = dt1; |
Мы дождались установки флага, провалились вниз, сбросили его и сохранили считанные данные в наш буфер.
Больше в коде ничего не меняется.
Соберём код, прошьём контроллер, включим обмен в терминальной программе и запустим наш скрипт, который мы писали в прошлом уроке.
А вот и результат работы кода
Всё прекрасно работает!
Итак, на данном уроке мы научились пользоваться механизмом обработки прерываний от шины USART. Какие достоинства прерываний существуют для работы программы, думаю, объяснять не нужно.
Всем спасибо за внимание!
Предыдущий урок Программирование МК STM32 Следующий урок
Отладочную плату STM32F103C8T6 можно приобрести здесь STM32F103C8T6
Программатор недорогой можно купить здесь ST-Link V2
Переходник USB to TTL можно приобрести здесь ftdi ft232rl
Индикатор светодиодный семиразрядный с драйвером MAX7219
Логический анализатор 16 каналов можно приобрести здесь
Смотреть ВИДЕОУРОК (нажмите на картинку)
Добавить комментарий