TXE-Bit löscht UART ARM M0 nicht

Ich versuche, UART an einem STM32F0-Teil zum Laufen zu bringen, und kann die Interrupts nicht herausfinden. Laut Referenzhandbuch

Bit 7 TXE: Transmit data register empty
This bit is set by hardware when the content of the USARTx_TDR register has been 
transferred into the shift register. It is cleared by a write to the USARTx_TDR register.
An interrupt is generated if the TXEIE bit =1 in the USARTx_CR1 register.

Allerdings kann ich das TXE-Flag nie klar sehen. Folgendes habe ich in meinem IRQ-Handler:

  if(USART_GetITStatus(EVAL_COM1, USART_IT_TXE) != RESET)
  {   
    /* Write one byte to the transmit data register */
    if (TxBuffer[TxCount] != '\0')
    {
      USART_SendData(EVAL_COM1, TxBuffer[TxCount++]);
    }
    //else{
    //  USART_ITConfig(EVAL_COM1, USART_IT_TXE, DISABLE);
    //}
  }

Wenn ich die else-Anweisung nicht auskommentiere, wird der Sende-Interrupt endlos ausgelöst, auch wenn ich aufhöre, Bytes an das TDR zu senden. Gibt es eine Möglichkeit, die Interrupts zu stoppen, ohne sie zu deaktivieren? Oder muss ich jedes Mal neu aktivieren, wenn ich etwas senden möchte?

Versuchen Sie Folgendes hinzuzufügen: USART_ClearITPendingBit(EVAL_COM1,USART_IT_TXE); ... Ich würde den Interrupt trotzdem deaktivieren, wenn Sie keine Daten zu senden haben.
Ich muss alle paar Sekunden eine Nachricht als Antwort auf eine empfangene Nachricht senden. Ist es richtig, meine Antwort zu senden und dann den Interrupt zu deaktivieren? Wenn ja, ist das in Ordnung, ich dachte nur nicht, dass der Interrupt deaktiviert werden muss.
Ich deaktiviere immer den Interrupt, wenn mein Sendepuffer leer ist. Um ehrlich zu sein, bin ich mir nicht sicher, ob es erforderlich ist, wenn Sie das USART_IT_TXE-Bit gemäß meinem obigen Vorschlag löschen.

Antworten (2)

Wenn USARTx_TDRdas Register leer ist, USART_ISR_TXEwird das Flag auf 1 gesetzt. Wenn USARTx_CR1_TXEIE( TXEInterrupt Enable Flag) aktiviert ist, TXE=1wird der Interrupt angehalten.

Daher ist das Codebeispiel mit dem Deaktivieren des Interrupts nach abgeschlossener Übertragung eine gute Lösung.

Wenn Sie die Übertragung regelmäßig starten, schreiben Sie einfach das erste Byte (es wird gelöscht TXE) und aktivieren Sie den Interrupt.

Oder wenn möglich DMA verwenden - etwas mehr Code, aber nachdem Sie strlenes berechnet und konfiguriert haben, ist es eher Feuer und Vergessen ;)

Anstatt TXE als Flag zu betrachten, das gelöscht werden muss, sollte man es als Hinweis darauf betrachten, dass der UART bereit ist, Daten zur Übertragung anzunehmen. Die Tatsache, dass Sie keine Daten für Übertragungsdaten haben, bedeutet nicht, dass sie nicht bereit sind.

Einige Mikrocontroller wie der 8051 haben ein Flag, das gesetzt wird, wenn der UART das Setzen eines Bytes beendet hat, aber auch manuell gelöscht werden kann. Solche Konstruktionen neigen dazu, selbst bei einfach gepufferten UARTs Probleme zu verursachen, und sind für UARTs, die doppelt gepuffert sein können, völlig ungeeignet.

Der richtige Ansatz besteht einfach darin, den Transmit-Data-Empty-Interrupt immer dann zu aktivieren, wenn Sie etwas Interessantes zu sagen haben, und ihn zu deaktivieren, wenn Sie dies nicht tun. In manchen Fällen kann es hilfreich sein, einen Interrupt im Sende-Leerlauf zu aktivieren, wenn Sie etwas übertragen, und den Interrupt-Handler dafür auf die abgeschlossene Übertragung reagieren zu lassen und den Interrupt zu deaktivieren. Obwohl es ungewöhnlich erscheinen mag, dass ein Interrupt-Handler den Interrupt deaktiviert, ohne die Ursache zu "beheben", ist dies in Fällen, in denen eine andere Aktion im System dazu führt, dass der Interrupt wieder aktiviert wird, durchaus angemessen.