Deine Schleifenschachtelung stimmt nicht.
Aber: Ich würd das ehrlich gesagt gar nicht so machen.
An der UART wird der Empfangsinterrupt freigegeben und in der ISR
erfolgt die Auswertung des empfangenen Zeichens bezüglich XON oder XOFF.
Dazu kommt noch eine globale Variable, die den Sender in die
Gegenrichtung freigibt.
1 | volatile uint8_t stoppedPerHandshake;
|
2 |
|
3 | ISR( USART_RXC_vect )
|
4 | {
|
5 | char c = UDR;
|
6 |
|
7 | if( c == XON )
|
8 | stoppedPerHandshake = FALSE;
|
9 |
|
10 | else if( c == XOFF )
|
11 | stoppedPerHandshake = TRUE;
|
12 | }
|
13 |
|
14 | int uart_putc(unsigned char c)
|
15 | {
|
16 | while (!(UCSRA & (1<<UDRE)) || stoppedPerHandshake ) /* warten bis Senden moeglich */
|
17 | {
|
18 | }
|
19 |
|
20 | UDR = c; /* sende Zeichen */
|
21 | return 0;
|
22 | }
|
Da alle anderen Ausgabefunktionen letzten Endes IMMER in der uart_putc
landen, berücksichtigen sie daher auch automatisch das XON/XOFF
Protokoll. Der Gegenpart auf der anderen Seite kann damit zu jedem
beliebigen Zeitpunkt mittels XOFF den Sender kruzfristig zum Schweigen
bringen, egal ob der gerade eine Zeile ausgibt oder nicht.
Und durch den Interrupt Betrieb ist dann auch sicher gestellt, dass ein
XON/XOFF auf keinen Fall verloren geht, solange die Interrupts aktiviert
sind. Selbst dann wenn das Hauptprogramm momentan ganz was anderes
macht, als eine Zeile zu senden.
Die Schwierigkeit beim XON/XOFF besteht nicht so sehr darin, den Sender
zum Schweigen zu bringen. Die Schwierigkeit besteht mehr darin, dass der
Empfnger dies rechtzeitig tut und damit rechnen muss, dass da noch ein
paar Zeichen nach dem XOFF trotzdem eintrudeln. D.h. der wird sein XOFF
nicht erst dann senden, wenn seine Empfangsbuffer auf Knirsch
vollgeschrieben sind, sondern schon etwas früher.