PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Starten|Stoppen (C)



BlackDevil
01.07.2008, 20:35
Servus

Bin noch neu im Geschäft und hab leider kein Minimalbeispiel. Aber ich denke ich kann gut genug beschreiben wo der Schuh drückt.

Nehmen wir mal an ich möchte ein Lauflicht Kreieren. Nun würde ich folgendes tun (Pseudo Code):


if(taster1.gedrückt==1){
while(1){
portc.1=1;
portc.1=0;
if(taster2.gedrückt==1){
stop(); // entspricht Pause
if(taster2.gedrückt==1){ // Taster erneut gedrückt
start();
}
}
}


Ich frage mich wie man Starten bzw Stoppen kann? Ich weis das ich mit einem Ähnliche Code mit continue; an den Anfang der WhileSchleife und mit break; aus der Whileschleife hinaus springen kann ... Aber wie kann ich kurz Inne Halten, Kaffee Trinken und dann das Licht Weiter Laufen lassen? Beziehungsweise wie kann ich die Richtung umdrehen?

Grüße

Felix G
02.07.2008, 01:04
Oha...
also while(1) für etwas anderes zu benutzen als die Hauptschleife eines Programms ist aber ganz ganz böse.


Viele Probleme ähnlich dem von dir beschriebenen lassen sich recht bequem mit einer sog. state-machine lösen

implementieren kann man sowas mit einem großen Switch-Block:
(der seinerseits in einer Funktion sitzt welche zyklisch aufgerufen wird)


switch(zustand)
{
case zustand1:
blablubb
zustand = zustand2;
break;
case zustand2:
blablubb
zustand = zustand3;
t = Zeit;
break;
case zustand3:
if(Zeit - t > Wartezeit)
{
blablubb
zustand = ....
}
case zustand4:
...
...
...
}

natürlich kann man beliebig zwischen den Zuständen hin und her springen, man muss nicht immer so linear vom einen zum nächsten wie hier dargestellt. Wartezeiten lassen sich auch sehr leicht realisieren, denn man muss sich nur den Startzeitpunkt merken und dann bei jedem Aufruf überprüfen ob die Wartezeit schon abgelaufen ist oder nicht.

uwegw
02.07.2008, 10:59
Du nimmst einen Timer und lässt ihn periodisch Interrupts auslösen (zb alle 10ms).
Dann fragst du in der ISR den Taster ab (da kannst du gleich die Entprellung einbauen) und taktest gleichzeitig das Lauflicht. Also je nach gewünschter Geschwindigkeit alle x ISRs das Lauflicht einen Stand weiterschalten (Tabelle usw.).
Wenn jetzt der Taster gedrückt wird, wird eine globale Variable gesetzt, die der Lauflichtfunktion mittelt, was nun zu tun ist. Also zb "stop", "weiter", andersrum", "schneller" etc.
[mit einfachen Warteschleifen ist hier jedenfallls nichts mehr zu machen!]

BlackDevil
02.07.2008, 14:15
SwitchCase ist mir nicht unbekannt - und aufgrund der Frequenz mit der die Hauptschleife immer widerholt wird fällt dann auch kein Flackern auf ... denk ich mir gerade so.

Also:
HAUPTSCHLEIFE=>TasterA gedrückt? TasterA gedrückt gewesen? Variable setzen => Switch(Case) Auswählen => Hauptschleifen Ende (Widerholen)

Mit Interrupts ist klar das man das damit machen kann - ist dann aber wieder nicht Einsteiger Freundlich *g*. Gibts was im Netz zu SSM (SolidStateMachines) zu lesen das ihr gut findet?

uwegw
02.07.2008, 14:34
Warteschleifen sind ebenfalls nicht einsteigerfreundlich. Sie sind in den allermeisten Fällen weder für Einsteiger noch für Profis geeignet. Die Möglichkeit von Warteschleifen in einer Programmiersprache führt dazu, dass Einsteiger diese pauschal für alle zeitabhängigen Aufgaben einsetzen wollen. Das ist schlechter Programmierstil und führt oft in Sackgassen.

Warteschleifen haben den Nachteil, dass man immer nur eine Sache gleichzeitig machen kann, und das reicht eigentlich nie aus (schon bei einer simplen Sache wie deinem Lauflicht). Die einzige Berechtigung für Warteschleifen sind ganz kurze Verzögerungen von einigen Mikro-bis Milisekunden, wie man sie zb für LCDs braucht. In der delay.h der avr-libc sind ja auch nur wenige Milisekunden Wartezeit möglich. Das hat natürlich vor allem technische Gründe, wird aber auch ein Stück weit so gewollt sein. Alles, was über ein paar Milisekunden hinausgeht, sollte besser per Timer gemacht werden.

In meinen Programmen lasse ich immer einen Timer mit einen Zyklus von einigen Milisekunden laufen. In dessen ISR stehen dann alle Aufgaben, die regelmäßig erledigt werden müssen. Also LEDs ansteuern (Blinkfunktion), Taster abfragen,...

BlackDevil
02.07.2008, 15:29
wie sähe dann der Code aus? Wenn ich mal Plumb fragen darf, im Tut hab ich nichts gefundne +leider*

Felix G
02.07.2008, 23:06
Also, du nimmst einen Timer her und stellst ihn so ein, daß er z.B. im 1ms Takt einen Interrupt erzeugt. In der Timer-ISR zählst du dann im einfachsten Fall mal eine Variable um 1 hoch.

Damit hast du schonmal alles was du brauchst um innerhalb deines Programms Zeiten zu messen, denn du brauchst dir ja nur den Startzeitpunkt merken und erhälst die vergangene Zeit dann einfach durch Subtraktion des Startzeitpunkts von der aktuellen Zeit.

Dadurch wiederum ist es sehr leicht Wartezeiten in Funktionen einzubauen, welche zyklisch aufgerufen werden. Das habe ich ja auch schon beispielhaft in der mini Statemachine dargestellt.

BlackDevil
03.07.2008, 11:07
Ich kann mir nur den Timer noch nich so ganz vorstellen - ich werd nachher aber noch mal googlen. Heute muss ich mir noch die nötigen 45% der Physik Klausur in die Rübe Boxen ^^