Forum: Compiler & IDEs XMega UART, DataregisterEmpty


von Hans J. (hjm)


Lesenswert?

Hallo,

ich habe da ein Problem.

Ich nutze einen ATXmega 128A1 und sende damit im Interrupt via UARTC1.

Wenn ich den TXC-Interrupt wähle funktiniert es einwandfrei.

Ich möchte jedoch den DRE (DataRegisterEmpty) Interrupt nutzen, um
die Kommunikation Schlupffrei zu machen.

Jedoch funktioniert dies nur ein einziges mal nach einem Reset
und danach werden keine Daten mehr gesendet.

Gibt es da irgend welche Probleme bei den XMega's?

Grüße
Hans-Josef

von Mike R. (thesealion)


Lesenswert?

Gib doch mal ein wenig mehr von deinem Code preis.

von Hans J. (hjm)


Lesenswert?

Hallo,

hier mal etwas Code.
Zuerst die Version mit TXC-IRQ, welche einwandfrei funktioniert:
1
#define COM_C1 USARTC1        // USART1 von PORTC wird als Interface Bus1
2
3
4
mstr_send;         // Receive OFF, Sender ON, Datenrichtung=Senden
5
uart_send_cnt = 6; // Anzahl zu sendender zeichen
6
uart_cnt      = 0; // Zeichenzähler
7
8
USART_PutChar(&COM_PB, uart_buffer[uart_cnt++]);  // Sende 1.char
9
USART_TxdInterruptLevel_Set(&COM_C1, USART_TXCINTLVL_HI_gc);  // Trans-IRO scharf machen
10
...
11
12
...
13
ISR (USARTC1_TXC_vect)  // Send IRQ
14
{
15
  if (uart_cnt < uart_send_cnt)                        // Alles gesendet?
16
    USART_PutChar(&COM_C1, uart_buffer[uart_cnt++]);  // TX Buffer fuellen
17
18
  else{
19
    PORTC.OUTCLR = PIN5_bm;      // RS485 Datenrichtung Empfang
20
    USART_Tx_Disable(&COM_C1);   // TX_disable
21
  }
22
}


Jetzt mit DRE-IRQ, welches nur einmal funktioniert. Dabei sollte immer 
wenn das Datenregister leer ist was eingetragen werden und am Schluß 
wird dann der TXC-IRQ scharf gemacht, was die RS485-Datenrichtung 
umschaltet und den Sender abschaltet.
1
#define COM_C1 USARTC1        // USART1 von PORTC wird als Interface Bus1
2
3
4
mstr_send;         // Receive OFF, Sender ON, Datenrichtung=Senden
5
uart_send_cnt = 6; // Anzahl zu sendender zeichen
6
uart_cnt      = 0; // Zeichenzähler
7
8
USART_DreInterruptLevel_Set(&COM_C1, USART_DREINTLVL_HI_gc);  // Trans-IRO scharf machen
9
10
ISR (USARTC1_DRE_vect)  // Send IRQ
11
{
12
  if (uart_cnt < uart_send_cnt)                        // Alles gesendet?
13
    USART_PutChar(&COM_C1, uart_buffer[uart_cnt++]);  // TX Buffer fuellen
14
15
  else{
16
    USART_DreInterruptLevel_Set(&COM_C1, USART_DREINTLVL_OFF_gc);  // DRE-IRQ sperren
17
    USART_TxdInterruptLevel_Set(&COM_C1, USART_TXCINTLVL_HI_gc);  // Trans-IRO scharf machen
18
  }
19
}
20
21
ISR (USARTC1_TXC_vect)  // Ende des senden
22
{
23
  PORTC.OUTCLR = PIN5_bm;      // RS485 Datenrichtung Empfang
24
  USART_Tx_Disable(&COM_C1);   // TX_disable
25
}

Also wie gesagt die erste Lösung arbeitet (bis auf die kleinen) 
Verzögerungnen durch andere IRQ-Bearbeitung.
Die DRE-Lösung tut es nur bei erstenmal nach einem Reset, danach sendet 
der µC nichts mehr????

Ich habe spaßeshalber mal ein Senden im Pollbetrieb gemacht, mit dem 
gleichen Ergbnis.


Grüße
Hans-Josef

von Michael U. (amiga)


Lesenswert?

Hallo,

Nach Reset ist das DRE-Bit gesetzt, die Routine wird also nach Freigabe 
der IRQ sofort aufgerufen.

Du schaltest dann den DRE-IRQ in der ISR aus.
Irgendwann sicher auch wieder ein?

DRE ist nach Schreiben der Daten in der ISR gelöscht, das wird auch nie 
wieder gesetzt, es sei denn, Du schreibst das erste Byte zum erneuten 
Senden
außerhalb der ISR in den UART, dann wird es gesetzt, wenn die Daten raus 
sind.

Gruß aus Berlin
Michael

von Hans J. (hjm)


Lesenswert?

Hallo,

so ich habe den Fehler gefunden.

Wenn man den Transmitter abschaltet wenn noch Zeichen im Schieberegister 
sind dann funktioniert der Tansmitter danach garnicht mehr.

Hat jemand eine Ahnung, wie man den Transmitter wieder zurücksetzen 
kann?


@amiga,
Der DRE-IRQ wird immer ausgeführt, da das Flag nur gelöscht wird wenn 
man Daten schreibt. Löschen kann man das nicht.
Wenn man den DRE-IRQ nicht sperrt dann kommt der immer.
So steht's auch im Manual beschrieben.

Grüße
Hans-Josef

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.