Forum: Mikrocontroller und Digitale Elektronik delay() verlassen wenn taste gedrückt


von Andreas K. (zumpe)


Lesenswert?

Hallo,
ich arbeite mich gerade wieder in PIC Programmierung ein und versuche 
verschiedene kleine Testprogramme zu programmieren um die Chips und C 
richtig zu verstehen. Nun habe ich ein Frage zur "best practice". ;)
Ich habe das Vellemann Testboard und habe mit das Beispielprogramm dazu 
angesehen (ASM) welches einfach beim drücken von Tasten verschiedene 
Muster auf den LEDs erzeugt. In der notwenigen Delay Routine, damit man 
die LEDs leuchten  sieht, wird immer wieder der Tastenzustand abgefragt 
und bei gedrückter Taste die Delay Schleife verlassen und in einem Menue 
Teil die richtige Routine neu aufgerufen. Soweit so gut, das versteh ich 
auch soweit alles.
Nun bin ich am zeifeln wie man das in C am besten löst. Habe bisher mit 
Standard delay(ms) Funktionen gearbeitet. Die laufen also stur bis zum 
Emde durch und eine Reaktion auf eine neu gedrückte Taste kann erst dann 
wieder erfolgen. Ich könnte ja auch eine "spezielle" delay() Routine 
schreiben die beim auftreten einer gedrückten Taste mit break; 
abgebrochen wird. Also ähnlich dem Assembler Code. Ist das der richtige 
Ansatz? Oder gibts da mit C eine elegantere Methode?

Danke und viele Grüße
Andreas

von (prx) A. K. (prx)


Lesenswert?

Langes Delay auf wiederholte kurze Delays runterbrechen und 
zwischendurch mal nach der Taste suchen.

von Karl H. (kbuchegg)


Lesenswert?

Andreas Krüger schrieb:
> Hallo,
> ich arbeite mich gerade wieder in PIC Programmierung ein und versuche
> verschiedene kleine Testprogramme zu programmieren um die Chips und C
> richtig zu verstehen. Nun habe ich ein Frage zur "best practice". ;)
> Ich habe das Vellemann Testboard und habe mit das Beispielprogramm dazu
> angesehen (ASM) welches einfach beim drücken von Tasten verschiedene
> Muster auf den LEDs erzeugt. In der notwenigen Delay Routine, damit man
> die LEDs leuchten  sieht, wird immer wieder der Tastenzustand abgefragt
> und bei gedrückter Taste die Delay Schleife verlassen und in einem Menue
> Teil die richtige Routine neu aufgerufen. Soweit so gut, das versteh ich
> auch soweit alles.

Dann hast du auch schon verstanden, dass der ganze Delay-Ansatz eine 
Sackgasse ist.


> abgebrochen wird. Also ähnlich dem Assembler Code. Ist das der richtige
> Ansatz? Oder gibts da mit C eine elegantere Methode?

Da gehst weniger um C und/oder Assembler sondern um das ganze Prozedere.
Ein Delay, also eine Warteschleife ist grundsätzlich zwar einfach, aber 
der falsche Ansatz für komplexere Programme.

Für solche Dinge hat man Timer. Zeitsteuerungen laufen in 'richtigen' 
Programmen praktisch immer über einen Timer.

von xfr (Gast)


Lesenswert?

Andreas Krüger schrieb:
> Nun habe ich ein Frage zur "best practice". ;)

Man verwendet delay_ms() überhaupt nicht (höchstens in der 
Initialsierung oder delay_ns() für sehr kurze Delays). Für alles andere 
gibt es Timer.

von Εrnst B. (ernst)


Lesenswert?

"Best practice" wäre wohl: kein delay verwenden. Timer stellt zeitbasis 
zur Verfügung, "delay" als zählen von xxx Timer-Ticks implementieren, 
z.b. innerhalb der State-Machine in der Main-Loop. Wenn nichts zu tun 
ist, kann die Main-Loop in den sleep/idle/power-save modus.

von Peter D. (peda)


Lesenswert?

Vom Prinzip her:
1
  for(;;){
2
    if( timer_abgelaufen() )
3
      naechstes_muster_anzeigen();
4
    if( tastendruck() )
5
      tastendruck_behandeln();
6
  }

Nach genau diesem Prinzip arbeitet dieses Beispiel:

Beitrag "Re: AVR Sleep Mode / Knight Rider"


Peter

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Andreas Krüger schrieb:
> Oder gibts da mit C eine elegantere Methode?
Ja.
Man wartet gar nicht, sondern arbeitet statdessen was anderes. Und 
sieht in einer Schleife (die legendäre Hauptschleife) zwischendurch mal 
nach, ob die Zeit schon vorbei ist. Wenn die Zeit dann um ist, dann wird 
die gewünschte Aktion ausgeführt:
http://www.lothar-miller.de/s9y/categories/22-Zeiten

von Andreas K. (zumpe)


Lesenswert?

Danke für die vielen schnellen Antworten! Ihr seid wirklich klasse!!

Ich denke das schubst mich schon in die richtige Richtung.

Wenn man den uC zwischendurch in den sleep schicken will etwa so:

durchlaufender Timer mit Interrupt
Timer Interrupt auslösen. (aufwachen)
Timertick Variable inkrementieren.
Tastenstatus abfragen (mit Entprellung)
Interrupt Routine beenden

Die Mainschleife läuft durch das aufwachen auch weiter. Hier dann prüfen 
ob Zeit für Musterwechsel abgelaufen oder andere Taste gedrückt. 
Enstprechende Programmteile aufrufen.
Wieder schlafen legen.

Liege ich da richtig?

Viele Grüße
Andreas

von xfr (Gast)


Lesenswert?

Die Tasterentprellung kann man auch nach dem Aufwachen in der 
Hauptschleife machen, die ist ja nicht zeitkritisch. ISRs immer so kurz 
wie möglich halten, es könnte ja schließlich noch andere, wirklich 
zeitkritische Interrupts geben.

Ansonsten ja, das ist übliche Vorgehensweise.

von Peter D. (peda)


Lesenswert?

Sleep sollte man nur da verwenden, wo es auch auf die Stromaufnahme 
ankommt.
Und auch erst ganz zum Schluß implementieren.


Peter

von Falk B. (falk)


Lesenswert?

Siehe Multitasking

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.