Forum: Compiler & IDEs ISR fuer UART in AVR


von Owen S. (senmeis)


Lesenswert?

Hallo,

ich benutze AT90CAN128 von Atmel und habe eine ISR-Funktion und eine 
User-Funktion für UART geschrieben. Baudrate = 19,200 bits/s, Quarz = 8 
MHz.
1
SIGNAL(SIG_UART0_RECV)
2
{
3
  receive_uart_data = UDR0;  // Datenbyte speichern
4
  new_receive_uart_data = 0x01;  // Mitteilung vom neuen Datenbyte
5
}
6
7
void user_application()
8
{
9
  if (new_receive_uart_data == 0x01)  
10
  {
11
  // Datenbyte bearbeiten
12
  new_receive_uart_data = 0x00;
13
  }
14
}
Frage : Kann das passieren, dass UART-Daten verloren gehen, wenn 
UART-Daten zu schnell ankommen ?

Gruss
Senmeis

von Falk B. (falk)


Lesenswert?

@ Owen Senmeis (senmeis)

>SIGNAL(SIG_UART0_RECV)

Das heisst beim aktuellen AVR-GCC ISR(), siehe Doku.

>Frage : Kann das passieren, dass UART-Daten verloren gehen, wenn
>UART-Daten zu schnell ankommen ?

Ja, wenn dein Programm zu viel Zeit zur Verarbeitung braucht, siehe 
Interrupt.

MFG
Falk

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Ja. Es können Verluste an mehreren Stellen auftreten.

1/ Die ISR läuft und es kommt ein neues Zeichen in der UART Hardware an. 
Wenn das nicht gespeichert werden kann, geht es verloren. Eher 
unwahrscheinlich bei Baudrate = 19,200 bits/s, Quarz = 8 MHz, aber je 
nach dem Restcode kann man das provozieren.

2/ user_application() wird zu selten ausgeführt. Der Puffer 
receive_uart_data ist nur ein Byte gross. Wenn zwischen zwei ISR 
Aufrufen kein user_application() Aufruf ist, geht das ältere Byte 
verloren.

3/ Man sieht die Definition von new_receive_uart_data nicht, 
insbesondere ob es volatile typisiert ist. Der Compiler kann in 
user_application() Code produzieren, der nicht berücksichtigt, dass eine 
ISR diese Variable zu einem beliebigen Zeitpunkt ändert.

von Owen S. (senmeis)


Lesenswert?

Hallo,

danke für die Hinweise.

Noch eine Frage zur angegebenen Anleitung "Interrupt". Zitat aus der 
Anleitung:
"D.h. während der UART selbsttätig das Zeichen sendet ist die CPU zum 
Warten verdammt."

Im Gegensatz habe ich immer folgenden Code benutzt, um ein Byte zu 
senden, also keine Interrupts.
1
// einzelnes Senden
2
void USART0_Tr_UINT8(UINT8 num8)
3
{
4
  while(!(UCSR0A&(1<<UDRE0)));
5
  UDR0 = num8;
6
}
Kann das Programm hier blockiert werden? Bisher habe ich noch keine 
Probleme gehabt.

Gruss
Senmeis

von STK500-Besitzer (Gast)


Lesenswert?

>Kann das Programm hier blockiert werden? Bisher habe ich noch keine
>Probleme gehabt.

Nein, eigentlich nur, wenn das Senden nicht gestattet ist (TXEN muß zum 
Senden gesetzt sein).

>Der UART ist ein oft benutztes Modul eines Mikrocontrollers. Anfänger >nutzen ihn 
meist im sogenannten Polling Betrieb (engl. to poll, abfragen).
>"D.h. während der UART selbsttätig das Zeichen sendet ist die CPU zum
>Warten verdammt."

Aus dem Zusammenhang gerissen kann man einen anderen Sinn hinter der 
Aussage vermuten.

>Im Gegensatz habe ich immer folgenden Code benutzt, um ein Byte zu
>senden, also keine Interrupts.

Bei einem gepufferten UART (zwei Bytes werden gespeichert) und geringer 
Datenmengen spricht nichts gegen die Poll-Methode.
Wenn man aber viele Daten (vielleicht auch noch relativ schnell) 
verschicken will, sollte man das "im Hintergrund" per ISR und 
Daten-Puffer lösen. Der Controller führt zwischen zwei Interrupts 
mindestens eine Anweisung aus.

von Falk B. (falk)


Lesenswert?

@ Owen Senmeis (senmeis)

>Kann das Programm hier blockiert werden?

Sicher durch die While-Schleife. Wobei das keine Blockieren im Sinn von 
endlos festfressen ist, sondern halt warten bis der FIFO des UARt 
leer ist.

> Bisher habe ich noch keine Probleme gehabt.

Das hat ja auch keiner behauptet, aber die CPU muss dennoch warten, wenn 
du z.b. einen String mit 10 Zeichen senden willst.

MFG
Falk

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.