Очистка флагов прерывания USART (UART) в STM32?

Я использую STM32F105 для связи с GPS-чипом Linx с помощью UART.

Если я не использую прерывания (если я просто опрашиваю флаг RX), то все работает нормально. Но я получаю неожиданные результаты при попытке использовать прерывания.

Например, если я разрешаю только прерывание RXNE («RX not empty») с помощью USART_ITConfig(USARTx, USART_IT_RXNE), тогда код должен направлять только ISR для этого конкретного события. Но прерывание срабатывает и при переполнении.

Что касается очистки флагов, кажется, что метод зависит от флага. Чтобы сбросить флаг переполнения ( USART_IT_ORE), в руководстве пользователя объясняется, что я должен сначала прочитать USARTx_SRрегистр, а затем прочитать USARTx_DRрегистр. Это работает; флаг очищен.

Также есть USART_ClearITPendingBit()функция, но она принимает только небольшое подмножество флагов.

Существует восемь различных источников прерываний, которые можно выборочно активировать, и десять различных флагов. Есть ли где-нибудь краткое описание того, как управлять всеми этими флагами?

Ответы (3)

Как правило, вам нужно обрабатывать только флаги прерывания, которые вы специально включили с помощью USART_ITConfig().

Однако, если вы разрешите прерывание RXNE ( USART_ITConfig(USARTx, USART_IT_RXNE)), это также активирует прерывание Overrun! Таким образом, вы должны справиться с обоими из них.

внутренняя карта

Флаги USART могут сбивать с толку. Существуют отдельные флаги состояния и флаги прерывания, и они имеют схожие имена. Например: USART_IT_RXNEи USART_FLAG_RXNE.

Кроме того, существуют различные способы очистки этих флагов. Например, USART_ClearITPendingBit()функция работает только для четырех (из десяти) возможных флагов.

Вот краткое описание флагов прерывания и способов их использования. Они специфичны для STM32F105, но являются репрезентативными:


USART_IT_TXE — «Регистр передачи данных пуст»

  • Очищается автоматически при звонкеUSART_SendData()

USART_IT_RXNE — «Регистр приема данных не пуст»

  • Очищается автоматически при звонкеUSART_ReceiveData(USARTx)

  • Его можно очистить вручную, вызвавUSART_ClearITPendingBit(USARTx, USART_IT_RXNE)


USART_IT_TC — «Передача завершена»

  • Он очищается автоматически:

    • USART_GetITStatus(USARTx, USART_IT_TC)с последующим
    • USART_SendData()
  • Его также можно очистить вручную, вызвавUSART_ClearITPendingBit(USARTx, USART_IT_TC)


USART_IT_CTS — «Изменение CTS»

  • Очищено по телефонуUSART_ClearITPendingBit(USARTx, USART_IT_CTS)

USART_IT_LBD — «Обнаружен разрыв LIN»

  • Очищено по телефонуUSART_ClearITPendingBit(USARTx, USART_IT_LBD)

USART_IT_PE — «Ошибка четности»

  • Очищено:
    • USART_GetITStatus(USARTx, USART_IT_PE)с последующим
    • USART_ReceiveData(USARTx)

USART_IT_NE — «Ошибка шума»

  • Очищено:
    • USART_GetITStatus(USARTx, USART_IT_NE)с последующим
    • USART_ReceiveData(USARTx)

USART_IT_ORE — «Ошибка переполнения»

  • Очищено:
    • USART_GetITStatus(USARTx, USART_IT_ORE)с последующим
    • USART_ReceiveData(USARTx)()

USART_IT_IDLE — «Обнаружена свободная линия»

  • Очищено:
    • USART_GetITStatus(USARTx, USART_IT_IDLE)с последующим
    • USART_ReceiveData(USARTx)()
Да, я ответил на свой вопрос :) Если бы я нашел такой список раньше, это сэкономило бы мне много времени. Я надеюсь, что это поможет кому-то!
Этот ответ — золото; очень четкая ссылка на то, как очистить каждое из этих прерываний.

Просто хочу добавить немного своего опыта по этой проблеме, я следую инструкциям:

USART_IT_ORE — «Ошибка переполнения»

Очищается: USART_GetITStatus(USARTx, USART_IT_ORE), за которым следует USART_ReceiveData(USARTx)()

Кажется, это не работает, и вместо этого у меня работает следующая команда:

USART_GetFlagStatus(USARTx, USART_IT_ORE), за которым следует USART_ReceiveData(USARTx)

Если вы посмотрите на функции:

USART_GetFlagStatus() и USART_ReceiveData()

Вы найдете то, что именно Bitsmack писал раньше... «Сначала прочитайте регистр USARTx_SR, затем прочитайте регистр USARTx_DR».

Надеюсь, это сработает для вас и сэкономит намного больше времени на эту проблему. =)

Спасибо за Вашу информацию! Я не узнаю USART_GetFlat(). Можете ли вы сказать мне, откуда это?
Мне жаль, что я неправильно набрал команду, это должно быть USART_GetFlagStatus(), за которым следует USART_ReceiveData(), исходный пост был исправлен. Спасибо Битсмак.
Отлично, спасибо! Похоже, имена функций изменились. Вы используете стандартную периферийную библиотеку или один из HAL STMCube? Для какого семейства микроконтроллеров?
Спасибо за хороший ответ. НО: я получаю один символ на STM32L476, дальнейшие байты не принимаются (нет сигнала на oszi), но постоянное получение прерывания FE (ошибка кадра). Не могу даже очистить это прерывание. Есть идеи, в чем причина?
@peets — есть способ снять флаг ошибки кадрирования (FE). Вам нужно вызвать LL_USART_ClearFlag_ORE(USARTx_INSTANCE); , который пишет в регистр ICR WRITE_REG(USARTx->ICR, USART_ICR_ORECF);. Это должно сбросить флаг ошибки кадрирования (FE). Кроме того, если у вас установлен параметр «Включение прерывания от ошибки» (EIE), вы можете ввести код обработки ошибок, который будет действовать вечно. Если вы получаете ошибки кадрирования, проверьте скорость передачи данных и разрывы строк (линия UART остается на низком уровне в течение определенного периода времени).

чтение statusи dataрегистры сбрасывает ошибку переполнения.

uint32_t cnt_rx2_overrun;
void USART2_IRQHandler(void)
{
  uint32_t status = USART2->SR;
  uint8_t ch;
  if (status & USART_SR_RXNE) { // rx data
    ch = USART2->DR;
    // parse data
  }
  else if (status & USART_SR_ORE){ // overrun error
    ch = USART2->DR; // reading clears the ORE flag
    cnt_rx2_overrun++;
  }

}
```