Я использую модуль UART4 STM32F105. Я использую прерывание RXNE («RX Buffer Not Empty») для захвата данных по мере их поступления. Он работает, как и ожидалось.
Когда прерывание RXNE включено, оно также включает прерывание переполнения (ORE). Это также работает, как и ожидалось.
Флаг состояния ORE отображается как USART_FLAG_ORE
. Соответствующий флаг прерывания USART_IT_ORE
. Если прерывание RXNE разрешено, то при установке бита флага это должно привести к установке бита IT. Скопировано из руководства пользователя :
Я обрабатываю прерывание так:
void usartISR(void)
{
// Did we receive data?
if(USART_GetITStatus(UART4, USART_IT_RXNE) == SET)
{
// Add it to the active buffer
}
// Did the receiver overrun?
else if(USART_GetITStatus(UART4, USART_IT_ORE) == SET)
{
// Clean up and clear the Overrun condition
}
// No other triggers have been enabled
else
{
ErrorHandler(ERR_BAD_INTERRUPT);
}
}
Проблема возникает, если флаг ORE уже установлен, когда я разрешаю прерывание:
{
// The USART_FLAG_ORE bit is already set
// The following command causes an immediate vector to the ISR:
USART_IT_Config(UART4, USART_IT_RXNE, ENABLE);
}
Векторы кода в ISR, но USART_IT_ORE
флаг, похоже, не установлен. ISR весело переходит в конец и вызывает обработчик ошибок. Если я загляну в регистры USART_CR, ни одно из других событий прерывания не будет разрешено. Если я обойду обработчик ошибок, код будет повторно обращаться к ISR, даже если флаги IT не установлены.
Почему ISR запускается без USART_IT_ORE
установки флага? Я упускаю что-то очевидное?
Изучив определения в источнике stm32f10x_usart.h
и Get_ITStatus()
в источнике, становится очевидным, что фактических «флагов прерывания» UART не существует. В регистре состояния есть только флаги состояния. Как вы знаете, когда происходит событие, устанавливается соответствующий бит флага, независимо от того, разрешены прерывания или нет. Если соответствующее прерывание разрешено , то MCU переходит к соответствующему ISR, где событие может быть обработано.
На изображении выше показано, что если прерывание RXNE включено и установлен флаг ORE, прерывание срабатывает, как и должно быть. В своем коде вы пытались получить статус «флага прерывания» с помощью Get_ITStatus()
. Однако единственное, что Get_ITStatus()
нужно сделать, это: проверить, установлен ли соответствующий флаг состояния SET &&, если соответствующее прерывание разрешено.
Теперь мы знаем, что первое условие истинно, так как вы сами УСТАНАВЛИВАЕТЕ флаг и убедились, что он действительно установлен. Второе условие также должно быть истинным — если проверяемое прерывание было RXNEIE (поскольку вы включили его). Но фактически проверяемый бит разрешения прерывания, когда USART_IT_ORE
он передается в Get_ITStatus()
, EIE
равен (разрешение прерывания при ошибке). Поэтому, поскольку вы не включили это прерывание, Get_ITStatus()
всегда будет возвращаться RESET (0) для ошибки переполнения.
Get_ITStatus()
хотя и не совсем неправильно. На приведенной выше диаграмме показано, что при установке ORE, EIE и DMAR будет генерироваться прерывание. Согласно мануалу по указанной вами ссылке:
Этот фрагмент предоставляет дополнительное подтверждение. Таким образом, кажется, что авторы библиотеки закодировали только эту вторую возможность (хотя и неправильно, поскольку DMAR не проверяется). Ваш обходной путь проверяет флаг состояния напрямую, что нормально, если вы не устанавливаете EIE с RXNEIE, поскольку вы не знаете, какой источник сгенерировал ошибку переполнения.
Я нашел обходной путь. Это не дает прямого ответа на вопрос, но, надеюсь, это поможет, пока кто-то не даст лучший ответ :)
Получается, что хотя бит USART_IT_ORE
не устанавливается, USART_FLAG_ORE
бит устанавливается . Если я изменю ISR для проверки бита флага (используя USART_GetFlagStatus(USART_FLAG_ORE)
) вместо бита IT ( USART_GetITStatus(USART_IT_ORE)
), тогда ISR будет работать нормально.
Интересно, что оба USART_FLAG_ORE
и USART_IT_ORE
очищаются с одинаковой последовательностью событий. Они очищаются вместе. Так что мне больше не пришлось менять код...
Get_ITStatus()
и думаю, что знаю, почему так происходит. Вы должны будете проверить все же. Ввод ответа...
СореDakeNoKoto
битмак
USART_FLAG_ORE
установлен, подразумевая, чтоUSART_IT_ORE
должен был быть установлен, ноUSART_GetITStatus()
функция все равно вернула отрицательный результат...битмак
USART_FLAG_ORE
не был очищен ни одним из чтений.СореDakeNoKoto
USART_IT_ORE_RX
вместоUSART_IT_ORE
inGetITStatus()
. Последнее кажется устаревшим определением в одной библиотеке, которую я нашелбитмак
USART_IT_ORE
используется в моей версии SPL (v3.5.0). Я поискал в библиотекеUSART_IT_ORE_RX
и ничего не нашел. Я нашел обходной путь и разместил его в ответ. Не могли бы вы посмотреть на него и посмотреть, говорит ли он вам что-нибудь? Еще раз спасибо.