Löschen von USART (UART) Interrupt-Flags in einem STM32?

Ich verwende einen STM32F105, um mit einem Linx-GPS-Chip über einen UART zu kommunizieren.

Wenn ich keine Interrupts verwende (wenn ich nur das RX-Flag abfrage), funktioniert es einwandfrei. Aber ich erhalte unerwartete Ergebnisse, wenn ich versuche, Interrupts zu verwenden.

Wenn ich zum Beispiel nur den RXNE-Interrupt ("RX not empty") mit aktiviere USART_ITConfig(USARTx, USART_IT_RXNE), dann sollte der Code nur für dieses eine bestimmte Ereignis zum ISR vektorisieren. Aber der Interrupt wird auch für eine Overrun-Bedingung ausgelöst.

Was das Löschen der Flags angeht, scheint die Methode vom Flag abzuhängen. Um das Overrun-Flag ( USART_IT_ORE) zu löschen, erklärt das Benutzerhandbuch, dass ich zuerst das USARTx_SRRegister lesen und dann das USARTx_DRRegister lesen sollte. Das funktioniert; die Flagge wird gelöscht.

Es gibt auch eine USART_ClearITPendingBit()Funktion, die jedoch nur eine kleine Teilmenge von Flags akzeptiert.

Es gibt acht verschiedene Unterbrechungsquellen, die selektiv aktiviert werden können, und zehn verschiedene Flags. Gibt es irgendwo eine Zusammenfassung, wie man all diese Flags verwaltet?

Antworten (3)

Im Allgemeinen müssen Sie nur die Interrupt-Flags behandeln, die Sie mit gezielt aktiviert haben USART_ITConfig().

Wenn Sie jedoch den RXNE-Interrupt ( USART_ITConfig(USARTx, USART_IT_RXNE)) aktivieren, wird dadurch auch der Overrun-Interrupt aktiviert! Sie müssen also mit beiden umgehen.

intmap

Die USART-Flags können verwirrend sein. Es gibt separate Statusflags und Interrupt-Flags und sie haben ähnliche Namen. Zum Beispiel: USART_IT_RXNEund USART_FLAG_RXNE.

Darüber hinaus gibt es verschiedene Methoden, um diese Flags zu löschen. Beispielsweise funktioniert die USART_ClearITPendingBit()Funktion nur für vier (von zehn) möglichen Flags.

Hier ist eine Zusammenfassung der Interrupt-Flags und wie man sie verwendet. Diese sind spezifisch für den STM32F105, aber repräsentativ:


USART_IT_TXE - "Sendedatenregister leer"

  • Beim Anruf wird es automatisch gelöschtUSART_SendData()

USART_IT_RXNE - "Empfangsdatenregister nicht leer"

  • Beim Anruf wird es automatisch gelöschtUSART_ReceiveData(USARTx)

  • Es kann manuell durch Anruf gelöscht werdenUSART_ClearITPendingBit(USARTx, USART_IT_RXNE)


USART_IT_TC - "Übertragung abgeschlossen"

  • Es wird automatisch gelöscht durch:

    • USART_GetITStatus(USARTx, USART_IT_TC)gefolgt von
    • USART_SendData()
  • Es kann auch manuell durch Anruf gelöscht werdenUSART_ClearITPendingBit(USARTx, USART_IT_TC)


USART_IT_CTS - "CTS-Änderung"

  • Durch Anruf gelöschtUSART_ClearITPendingBit(USARTx, USART_IT_CTS)

USART_IT_LBD - "LIN-Unterbrechung erkannt"

  • Durch Anruf gelöschtUSART_ClearITPendingBit(USARTx, USART_IT_LBD)

USART_IT_PE - "Paritätsfehler"

  • Gelöscht von:
    • USART_GetITStatus(USARTx, USART_IT_PE)gefolgt von
    • USART_ReceiveData(USARTx)

USART_IT_NE - "Rauschfehler"

  • Gelöscht von:
    • USART_GetITStatus(USARTx, USART_IT_NE)gefolgt von
    • USART_ReceiveData(USARTx)

USART_IT_ORE - "Überlauffehler"

  • Gelöscht von:
    • USART_GetITStatus(USARTx, USART_IT_ORE)gefolgt von
    • USART_ReceiveData(USARTx)()

USART_IT_IDLE - "Leere Leitung erkannt"

  • Gelöscht von:
    • USART_GetITStatus(USARTx, USART_IT_IDLE)gefolgt von
    • USART_ReceiveData(USARTx)()
Ja, ich habe meine eigene Frage beantwortet :) Wenn ich früher eine solche Liste gefunden hätte, hätte ich viel Zeit gespart. Ich hoffe es hilft jemandem!
Diese Antwort ist Gold; sehr klare Referenz, wie man jeden dieser Interrupts löscht.

Ich möchte nur einige meiner Erfahrungen zu diesem Problem hinzufügen. Ich folge den Anweisungen:

USART_IT_ORE - "Überlauffehler"

Gelöscht durch: USART_GetITStatus(USARTx, USART_IT_ORE) gefolgt von USART_ReceiveData(USARTx)()

Scheint nicht zu funktionieren, und der folgende Befehl funktioniert stattdessen für mich:

USART_GetFlagStatus(USARTx, USART_IT_ORE) gefolgt von USART_ReceiveData(USARTx)

Wenn Sie sich die Funktionen ansehen:

USART_GetFlagStatus() und USART_ReceiveData()

Sie werden genau das finden, was Bitsmack zuvor geschrieben hat ... "Zuerst das USARTx_SR-Register lesen, dann das USARTx_DR-Register lesen."

Hoffentlich funktioniert es für Sie und spart viel mehr Zeit bei diesem Problem. =)

Vielen Dank für Ihre Informationen! Ich erkenne USART_GetFlat() nicht. Kannst du mir sagen woher es kommt?
Es tut mir leid, dass ich den Befehl falsch eingegeben habe, es sollte USART_GetFlagStatus() gefolgt von USART_ReceiveData() sein, der ursprüngliche Beitrag wurde korrigiert. Danke Bitsmack.
Ausgezeichnet, vielen Dank! Es sieht so aus, als hätten sich die Funktionsnamen geändert. Verwenden Sie eine Standard Peripheral Library oder einen der STMCube HALs? Für welche Familie von Mikrocontrollern?
Danke für die gute Antwort. ABER: Ich empfange ein Zeichen auf STM32L476, es werden keine weiteren Bytes empfangen (kein Signal auf Oszi), sondern bekomme permanent einen FE (Framing Error) Interrupt. Kann diesen Interrupt nicht einmal löschen. Irgendwelche Ideen, was ist der Grund?
@peets - Es gibt eine Möglichkeit, das Flag "Framing Error" (FE) zu löschen. Sie müssen aufrufen, LL_USART_ClearFlag_ORE(USARTx_INSTANCE); was in das ICR-Register schreibt WRITE_REG(USARTx->ICR, USART_ICR_ORECF);. Das sollte das Flag Framing Error (FE) löschen. Wenn Sie Error Interrupt Enable (EIE) eingestellt haben, können Sie außerdem Fehlerbehandlungscode eingeben, der für immer bleibt. Wenn Sie Framing-Fehler erhalten, überprüfen Sie die Baudrate und Zeilenumbrüche (UART-Leitung bleibt für einen bestimmten Zeitraum niedrig).

Lesen statusund dataRegister löscht Überlauffehler.

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++;
  }

}
```