while / Interrupt - Problem

Gast #284305
Lesenswert?

Hallo!

Ich habe eine UART-Senderoutine, die abwarten soll, ob der vorherige
Befehl korrekt empfangen wurde.
Es gibt also im UART-Receive-Interrupt eine Überprüfung, ob ein "OK"
zurückempfangen wurde. Ist dies der Fall, so wird eine Variable auf 1
gesetzt. Außerdem wird ein Timer gestartet, der bei einem Overflow
ebenfalls die Variable auf 1 setzt, um den Programmablauf nicht
aufzuhalten.

In meiner Senderoutine warte ich zunächst darauf, dass die Variable 1
wird.
Ich habe
while (pc_answer == 0);   und
for (; pc_answer == 0;);

pc_answer ist natürlich als volatile deklariert.

Das Programm bleibt aber in der while- bzw. for-Schleife hängen und
wird nicht durch den Interrupt unterbrochen, so dass die Variable auf 1
gesetzt werden kann.

Was ist falsch? Oder gibt es schönere Lösungen, die auf eine korrekte
Antwort warten, bevor der nächste Befehl gesendet wird?

Gruß
Markus
Gast #284306
Lesenswert?

Hi, Markus,

"Ich habe eine UART-Senderoutine, die abwarten soll, ob der vorherige
Befehl korrekt empfangen wurde.
Es gibt also im UART-Receive-Interrupt eine Überprüfung, ob ein "OK"
zurückempfangen wurde. "

In Interrupt-Routinen darf nicht gewartet werden.
Die sind nur wie der Postbote - die liefern die Post ab, und schon sind
sie wieder weg.
Das Warten muß in das Hauptprogramm verlegt werden.

Ciao
Wolfgang
Gast #284307
Lesenswert?

Hi!

Oh, habe mich da vielleicht etwas umständlich ausgedrückt:

Ich warte in der Senderoutine, welche eine "normale" C-Funktion ist.
Diese Funktion hat als erste Zeile eben ein
while (!flag); oder eben die for-Variante.

Diese Endlosschleife soll eigentlich durch einen Timer-Overflow (oder
der Empfangsroutine) unterbrochen werden, der das flag setzt und damit
nach dem Rücksprung die Endlosschleife unterbrochen wird.

Gruß
Markus
Gast #284309
Lesenswert?

volatile int pc_answer;

Sende-Funktion:
void send_PC(int E, int L, int W)
  while (!pc_answer);          //um diese Zeile geht es
  pc_answer=0;

  while (!(UCSR0A & (1<<UDRE0)));
  UDR0 = 'E';

        usw.

Die Timer-Overflow-Routine:
SIGNAL (SIG_OVERFLOW3)
{
  lcd_clrscr();
  lcd_command(LCD_DISP_ON);
  lcd_puts("PC CommError!");
  pc_answer=1;
  TCCR3B=(0<<CS32)|(0<<CS31)|(0<<CS30);  // Timer stoppen
  TCNT3H=TCNT3L=0;
};

Wenn ich die while-Schleife rausnehme, erscheint der Display-Text, d.h.
die Interrupt-Routine wird angesprungen, sonst nicht.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren