¿Borrar banderas de interrupción USART (UART) en un STM32?

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_SRregistro y luego leer el USARTx_DRregistro. 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?

Respuestas (3)

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.

mapaintt

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_RXNEy 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"

  • Se borra automáticamente al llamarUSART_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 por
    • USART_SendData()
  • También se puede borrar manualmente llamandoUSART_ClearITPendingBit(USARTx, USART_IT_TC)


USART_IT_CTS - "Cambio de CTS"

  • Borrado llamandoUSART_ClearITPendingBit(USARTx, USART_IT_CTS)

USART_IT_LBD - "Interrupción de LIN detectada"

  • Borrado llamandoUSART_ClearITPendingBit(USARTx, USART_IT_LBD)

USART_IT_PE - "Error de paridad"

  • Limpiado por:
    • USART_GetITStatus(USARTx, USART_IT_PE)seguido por
    • USART_ReceiveData(USARTx)

USART_IT_NE - "Error de ruido"

  • Limpiado por:
    • USART_GetITStatus(USARTx, USART_IT_NE)seguido por
    • USART_ReceiveData(USARTx)

USART_IT_ORE - "Error de desbordamiento"

  • Limpiado por:
    • USART_GetITStatus(USARTx, USART_IT_ORE)seguido por
    • USART_ReceiveData(USARTx)()

USART_IT_IDLE - "Línea inactiva detectada"

  • Limpiado por:
    • USART_GetITStatus(USARTx, USART_IT_IDLE)seguido por
    • USART_ReceiveData(USARTx)()
Sí, respondí mi propia pregunta :) Si hubiera encontrado una lista como esta antes, me habría ahorrado una buena cantidad de tiempo. ¡Espero que esto ayude a alguien!
Esta respuesta es oro; referencia muy clara de cómo borrar cada una de estas interrupciones.

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. =)

¡Gracias por tu información! No reconozco USART_GetFlat(). ¿Puedes decirme de dónde viene?
Lamento haber escrito mal el comando, debería ser USART_GetFlagStatus() seguido de USART_ReceiveData(), la publicación original fue corregida. Gracias Bitsmack.
¡Excelente gracias! Parece que los nombres de las funciones han cambiado. ¿Está utilizando una biblioteca de periféricos estándar o una de las HAL de STMCube? ¿Para qué familia de microcontroladores?
Gracias por la buena respuesta. PERO: recibo un carácter en STM32L476, no se reciben más bytes (no hay señal en oszi), pero recibo una interrupción permanente FE (error de trama). Ni siquiera se puede borrar esta interrupción. ¿Alguna idea de cuál es la razón?
@peets: hay una manera de borrar el indicador de error de trama (FE). Tienes que llamar al 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 statusy datalos 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++;
  }

}
```