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_SR
Register lesen und dann das USARTx_DR
Register 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?
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.
Die USART-Flags können verwirrend sein. Es gibt separate Statusflags und Interrupt-Flags und sie haben ähnliche Namen. Zum Beispiel: USART_IT_RXNE
und 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"
USART_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 vonUSART_SendData()
Es kann auch manuell durch Anruf gelöscht werdenUSART_ClearITPendingBit(USARTx, USART_IT_TC)
USART_IT_CTS - "CTS-Änderung"
USART_ClearITPendingBit(USARTx, USART_IT_CTS)
USART_IT_LBD - "LIN-Unterbrechung erkannt"
USART_ClearITPendingBit(USARTx, USART_IT_LBD)
USART_IT_PE - "Paritätsfehler"
USART_GetITStatus(USARTx, USART_IT_PE)
gefolgt vonUSART_ReceiveData(USARTx)
USART_IT_NE - "Rauschfehler"
USART_GetITStatus(USARTx, USART_IT_NE)
gefolgt vonUSART_ReceiveData(USARTx)
USART_IT_ORE - "Überlauffehler"
USART_GetITStatus(USARTx, USART_IT_ORE)
gefolgt vonUSART_ReceiveData(USARTx)()
USART_IT_IDLE - "Leere Leitung erkannt"
USART_GetITStatus(USARTx, USART_IT_IDLE)
gefolgt vonUSART_ReceiveData(USARTx)()
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. =)
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 status
und data
Register 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++;
}
}
```
bitsmack
jjmilburn