Estoy usando un STM32F105 para comunicarme con un chip GPS Linx usando un UART.
Si no uso interrupciones (si solo sondeo la bandera RX), entonces funciona bien. Pero obtengo resultados inesperados cuando trato de usar interrupciones.
Por ejemplo, si solo habilito la interrupción RXNE ("RX no vacío") usando USART_ITConfig(USARTx, USART_IT_RXNE)
, entonces el código solo debería vectorizarse al ISR para este evento específico. Pero la interrupción también se activa por una condición de desbordamiento.
En cuanto a borrar las banderas, parece que el método depende de la bandera. Para borrar el indicador Overrun ( USART_IT_ORE
), el Manual del usuario explica que primero debo leer el USARTx_SR
registro y luego leer el USARTx_DR
registro. Esto funciona; se borra la bandera.
También hay una USART_ClearITPendingBit()
función, pero solo acepta un pequeño subconjunto de banderas.
Hay ocho fuentes de interrupción diferentes que se pueden habilitar selectivamente y diez banderas diferentes. ¿Hay un resumen en alguna parte de cómo administrar todas estas banderas?
En general, solo necesita manejar los indicadores de interrupción que ha habilitado específicamente con USART_ITConfig()
.
Sin embargo, si habilita la interrupción RXNE ( USART_ITConfig(USARTx, USART_IT_RXNE)
), ¡esto también habilita la interrupción Overrun! Así que debes manejar ambos.
Las banderas de USART pueden ser confusas. Hay banderas de estado y banderas de interrupción separadas y comparten nombres similares. Por ejemplo: USART_IT_RXNE
y USART_FLAG_RXNE
.
Además, existen varios métodos para borrar estos indicadores. Por ejemplo, la USART_ClearITPendingBit()
función solo funciona para cuatro (de las diez) banderas posibles.
Aquí hay un resumen de las banderas de interrupción y cómo usarlas. Estos son específicos para el STM32F105, pero son representativos:
USART_IT_TXE - "Registro de transmisión de datos vacío"
USART_SendData()
USART_IT_RXNE - "El registro de datos de recepción no está vacío"
Se borra automáticamente al llamarUSART_ReceiveData(USARTx)
Se puede borrar manualmente llamandoUSART_ClearITPendingBit(USARTx, USART_IT_RXNE)
USART_IT_TC - "Transmisión completa"
Se borra automáticamente por:
USART_GetITStatus(USARTx, USART_IT_TC)
seguido porUSART_SendData()
También se puede borrar manualmente llamandoUSART_ClearITPendingBit(USARTx, USART_IT_TC)
USART_IT_CTS - "Cambio de CTS"
USART_ClearITPendingBit(USARTx, USART_IT_CTS)
USART_IT_LBD - "Interrupción de LIN detectada"
USART_ClearITPendingBit(USARTx, USART_IT_LBD)
USART_IT_PE - "Error de paridad"
USART_GetITStatus(USARTx, USART_IT_PE)
seguido porUSART_ReceiveData(USARTx)
USART_IT_NE - "Error de ruido"
USART_GetITStatus(USARTx, USART_IT_NE)
seguido porUSART_ReceiveData(USARTx)
USART_IT_ORE - "Error de desbordamiento"
USART_GetITStatus(USARTx, USART_IT_ORE)
seguido porUSART_ReceiveData(USARTx)()
USART_IT_IDLE - "Línea inactiva detectada"
USART_GetITStatus(USARTx, USART_IT_IDLE)
seguido porUSART_ReceiveData(USARTx)()
Solo quiero agregar algo de mi experiencia en este problema, sigo las instrucciones:
USART_IT_ORE - "Error de desbordamiento"
Borrado por: USART_GetITStatus(USARTx, USART_IT_ORE) seguido de USART_ReceiveData(USARTx)()
Parece que no funciona, y el siguiente comando funciona para mí en su lugar:
USART_GetFlagStatus(USARTx, USART_IT_ORE) seguido de USART_ReceiveData(USARTx)
Si miras las funciones:
USART_GetFlagStatus() y USART_ReceiveData()
Encontrará lo que Bitsmack escribió exactamente antes... "Primero lea el registro USARTx_SR, luego lea el registro USARTx_DR".
Esperemos que funcione para usted y ahorre mucho más tiempo en este tema. =)
LL_USART_ClearFlag_ORE(USARTx_INSTANCE);
que escribe en el registro ICR WRITE_REG(USARTx->ICR, USART_ICR_ORECF);
. Eso debería borrar el indicador de error de trama (FE). Además, si tiene activada la interrupción de errores (EIE), puede ingresar un código de manejo de errores que permanece para siempre. Si obtiene errores de encuadre, verifique la velocidad en baudios y los saltos de línea (la línea UART se mantiene baja durante un período de tiempo).la lectura status
y data
los registros borran el error de desbordamiento.
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++;
}
}
```
bitsmack
jjmilburn