Я использую 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()
функция, но она принимает только небольшое подмножество флагов.
Существует восемь различных источников прерываний, которые можно выборочно активировать, и десять различных флагов. Есть ли где-нибудь краткое описание того, как управлять всеми этими флагами?
Как правило, вам нужно обрабатывать только флаги прерывания, которые вы специально включили с помощью 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».
Надеюсь, это сработает для вас и сэкономит намного больше времени на эту проблему. =)
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++;
}
}
```
битмак
Джеймилберн