Guten Tag,
ich habe hier gerade ein kleines Problem, bei dem mich hoffentlich
jemand in die richtige Richtung schubsen kann:
Das Programm (siehe unten) soll später mal dazu dienen, an einem AVR
Mega8 einen Wert per Drehgeber einstellen zu können.
Dafür soll der Benutzer am PC-terminal eintippen:
"Start" --> Drehgeber auslesen und das unendlich am PC-terminal ausgeben
"Stop" --> Ausgabe stop
"Weiter" --> Vom Letzer gespeicherte Wert wieder anfangen zu Zählen
"Reset" --> Vom null wieder anfangen zu zählen
- Wert auf PC-terminal ausgeben klappt Dazu habe ich den Code von Peter
F.
benutzt (Danke!).
- Drehgeber auslesen: Klappt. Dazu habe ich den Code von Peter D.
benutzt (Danke!).
soweit funktioniert alles korrekt.
Jetzt das verbliebene Problem:
tippe ich "Start" ein, wird unendlich der ausgelesener Wert eingegeben.
(Klar möchte ich es). Leider ist mir nicht mehr möglich etwas
einzutippen.
Wie kann ich den Code schreiben um der Benutzer die möglichkeit geben,
etwas anderen Befehlen einzutippen. ("Stop", "Weiter", "Reset")
Danke im Voraus!
innerhalb der Schleife es für received keine Möglichkeit mehr gibt,
einen anderen Wert zu erhalten.
Du musst deine komplette Systematik umstellen. So etwas wie eine
Schleife die auf etwas wartet, darf es nicht mehr geben. Damit darfst du
auch zb deine uart_gets Funktion nicht mehr weiter benutzen, solange die
darauf wartet, dass eine Zeile komplett empfangen wurde.
Du musst die Logik in die Hauptschleife bringen:
Sieh dir nacheinander Dinge an, die man tun könnte, ob die
Voraussetzungen dafür gegeben sind und mache sie, wenn die
Voraussetzungen dafür gegeben sind. Bei einigen derartigen Aktionen wird
es dann so sein, dass sie die Voraussetzungen für andere Aktionen
schaffen oder vernichten
1
while(1)
2
3
if(Zeichenwurdeempfangen){
4
if(Zeichenistein'\n'){
5
// Zeile ist komplett, merk dir das
6
Zeile_komplett=TRUE;
7
}
8
}
9
10
if(Zeile_komplett){
11
Zeile_komplett=FALSE;
12
if(Zeileist"Start")
13
Merkendassausgegebenwerdensoll
14
elseif(Zeileist"Stop")
15
DenMerkerfürdieAusgabezurücksetzen
16
elseif(Zeileist"Weiter")
17
...
18
}
19
20
if(MerkerfürAusagbeistgesetzt)
21
mache1Ausgabe
22
23
}
Ich hoffe man kann erkennen, wie das funktioniert. Du darfst nirgends
warten. Stattdessen dreht die Haupt-while-Schleife ständig ihre Runden,
sieht sich die einzelnen Sachen an und entscheidet anhand von Merkern
(einfache Variablen die entweder 0 oder 1 sein können) ob eine Aktion
gemacht werden soll oder nicht.
Du musst weg von einem sequentiellen Programmierstil (zuerst mach das,
dann mach das, dann warte auf dieses und zum Schluss machst du noch
jenes) hin zu einem ereignisorientierten Programmierstil: Ein Ereignis
tritt auf, bearbeite es; in der Hauptschleife werden ständig alle
möglichen Ereignisse überprüft ob sie vorliegen.
heike schrieb:
> enter = uart_getc();
Was macht uart_getc()?
Wartet die auf ein Zeichen, oder kommt die gleich zurück wenn kein
Zeichen vorhanden ist?
Wenn ich mich recht erinnere benutzt du die UART Lib vom Peter Fleury.
Sieh dir in seiner Demo an, wie man den Returnwert von uart_getc richtig
auswertet.
Ich les mir den Code noch weiter durch
NEIN!
Ich sagte doch: keine Warteschleifen.
Du holst ein Zeichen wenn eines da ist und hängst es an dein received
Buffer an, das wars. Das nächste Zeichen wird bearbeitet, wenn die
globale for(;;) Schleife das nächste mal zur Abfrage kommt "Ist ein
Zeichen da?"
1
if(enter!=0)// von der UART kommt wieder was
2
{
3
if(enter=='\r')// bei einem Newline ist die Zeile komplett
4
{
5
*s='\0';
6
Zeile_komplett=TRUE;
7
s=received;// s gleich wieder an den Anfang von received
8
// stellen, damit die nächsten Tastendrücke
9
// den nächsten String von vorne aufbauen
10
}
11
else// ansonsten hänge das Zeichen hinten drann
12
{
13
*s=enter;
14
s++;
15
}
16
}
Du denkst noch sequentiell:
Ich will eine Zeile komplett einlesen, also warte ich bis ich ein \r
erhalte.
Der springende Punkt ist das Wörtchen 'warte'. Das musst du los werden.
Deine Denkweise muss sein:
Ich habe ein und nur ein Zeichen erhalten, was mache ich damit?
Hänge ich es hinten an das bisher empfangene drann oder ist mit diesem
einen Zeichen eine Zeile vollständig und kann weiterbearbeitet werden.
(Das Ereignis ist: Ein Zeichen wurde empfangen
und der Rest ist die Reaktion auf dieses Ereignis)
heike schrieb:
> if( Zeile_komplett == TRUE )> {> if(strcmp(received, "start") == 0)> {> ltoa( enc_delta, s, 10 );> Merker =1;> }> else if(strcmp(received, "stop") == 0)> {> Merker =0;> }> else if(strcmp(received, "weiter") == 0)> {> Merker =1;> }> else if(strcmp(received, "reset") == 0)> {> enc_delta = 0x00;> enc_last = 0x00;> ltoa( enc_delta, s, 10 );> Merker =1;> }> }> if( Merker ==1 )> {> uart_puts("\r\n");> uart_puts( s );> uart_puts("/");> }>> Zeile_komplett = FALSE;> }
Nope. Das Rücksetzen von Zeile_komplett hat hier nichts verloren.
Das gehört logischerweise in den Zweig, in dem du das Ereignis
Zeile_komplett == TRUE behandelst.
1
if(Zeile_komplett==TRUE)
2
{
3
Zeile_komplett=FALSE;
4
if(strcmp(received,"start")==0)
5
{
6
ltoa(enc_delta,s,10);
7
8
...
9
10
}
Hier gibt es auch noch ein anderes Problem. Wenn die Auswertung länger
dauert und du schnell tippen kannst, dann kannst du klarerweise Zeichen
in received 'einschmuggeln' ehe sie ausgewertet wurden.
Aber mach erst mal den Rest.