Hallo zusammen, ich habe ein Problem bzgl. Taster. Verwendet wird der ATMega8. Vielleicht kann mir jemand helfen? Es geht um folgendes: Durch das Drücken eines Tasters möchte ich den aktuellen Programmablauf, egal an welcher Stelle das Programm ausgeführt wird, unterbrechen. Durch ein erneutes Drücken des Tasters soll das Programm an der Stelle fortgesetzt werden. Hier mein aktuelles Programm (Ich weiß, dass ein goto nicht verwendet werden sollte, aber für mich ist das doch übersichtlicher als ständig irgendwelche Unterprogramme zu schreiben :-) ): void main(void) { int zustand; DDRB=0x21; /*Ein- und Ausgänge*/ DDRD=0x3F; DDRC=0x04; lcd_init(); lcd_home(); while(1) { if(PINC & (1<<taster)) { zustand=1; } else { zustand=0; } if(zustand==0) { schleife_normal(); } else { schleife_pause(zustand); zustand=0; } void schleife_pause(int variable) { while(variable) { return 1; } } void schleife_normal(void) { reset: PORTB=0x20; /* Setzen --> Grundzustand*/ if(!(PINB & (1<<PB3)) && !(PINB & (1<<PB4)) && (PINB & (1<<PB1)) && (PINB & (1<<PB2))) { PORTB|=(1<<PB0); /*Set aktivieren, Programm starten*/ } else { goto reset; } wechsel: while(((!(PINB & (1<<PB3)) && (PINB & (1<<PB4))) || ((PINB & (1<<PB3)) && !(PINB & (1<<PB4)))) && !(PINB & (1<<PB1)) && !(PINB & (1<<PB2))); if(((!(PINB & (1<<PB3)) || (PINB & (1<<PB4))) && ((PINB & (1<<PB3)) || !(PINB & (1<<PB4))) && (!(PINB & (1<<PB3)) || (PINB & (1<<PB4)))) || (PINB & (1<<PB1)) || (PINB & (1<<PB2))) { lcd_data(zaehler); /*Schreibe auf Display*/ zaehler++; /*Zählregister um 1 erhöhen*/ bfr=zaehler/pulse; /*BFR ausrechnen*/ set_cursor(0,2); lcd_data(bfr); /*schreibe auf Display*/ PORTB=0x20; /*kehre in den grundzustand zurück*/ } else { goto wechsel; } if(PINC & (1<<PC1)) { lcd_clear(); } else goto reset; } Ich freue mich über alle Tipps!!! Simon
Schmeiss die gotos raus :-) Die Funktionen schleife_normal bzw. schleife_pause sollen nur EINE Sache machen. Auch wenn sie schleife_irgendwas heissen, soll sich in der Funktion keine Schleife befinden! Die einzige Schleife, die es gibt, ist die in main()
1 | ....
|
2 | |
3 | while( 1 ) { |
4 | |
5 | ....
|
6 | }
|
Nur dort gibt es eine Schleife und da genau dort die einzige Stelle ist, an der die Taste abgefragt wird ist auch nur dort die einzige Stelle an der du dein Programm verschiedene Dinge machen lassen kannst, je nachdem wie der Taster steht. Du musst dein Programm so umgestalten, dass es immer nur EIN Ding macht und nicht in einer extra Schleife auf irgendetwas wartet
1 | int main() |
2 | {
|
3 | int zustand; |
4 | |
5 | DDRB=0x21; /*Ein- und Ausgänge*/ |
6 | DDRD=0x3F; |
7 | DDRC=0x04; |
8 | |
9 | lcd_init(); |
10 | lcd_home(); |
11 | |
12 | zustand = 0; |
13 | |
14 | while(1) { |
15 | if( PINC & (1<<taster) ) |
16 | zustand = 1 - zustand; |
17 | |
18 | if( zustand == 0 ) |
19 | schleife_normal(); |
20 | else
|
21 | schleife_pause(zustand); |
22 | }
|
23 | }
|
24 | |
25 | void schleife_pause() |
26 | {
|
27 | return; // mach nichts |
28 | }
|
29 | |
30 | void schleife_normal(void) |
31 | {
|
32 | zaehler++; |
33 | lcd_data(zaehler); /*Schreibe auf Display*/ |
34 | }
|
Du musst aufhören in Schleifen zu denken und anfangen in Zuständen und Ereignissen zu denken. Dein Programm hat nur 1 Schleife und je nach Zustand und Ereignis macht es verschiedene Dinge in dieser Schleife. Irgenwelche Ereignisse (zb Tastendrücke) schalten Zustände ein oder aus. Ja nachdem ob ein Zustand aktiviert ist oder nicht, wird ein Programmteil ausgeführt oder eben nicht oder es passiert etwas anderes. Dein Prozessor ist schnell genug, dass er diese Hauptschleife viele Tausend mal in der Sekunde abarbeiten kann. Für einen Benutzer entsteht die Illusion, dass der µC sofort auf seinen Tastendruck reagiert.
Vielen Dank für die schnelle Antwort. Ich bin noch Anfänger auf dem Gebiet...muss mich erst noch dran gewöhnen. ;-) Ich werde es ausprobieren!
Und vor allen Dingen solltest du es dir zumindest in den nächsten Monaten zu eigen machen, dass wenn immer du versucht bist 'goto' zu schreiben, du in die Küche gehst und ein Bier in den Ausguss schüttest (zur Strafe) Du musst anfangen wie ein Schachspieler zu arbeiten, der simultan 40 Partien spielt. Der spielt auch nicht eine Partie durch um sich dann der nächsten zu widmen. Er geht an ein Brett, sieht sich die Sache an, entscheidet was zu tun ist und macht seinen Zug. Dann geht es weiter zum nächsten Brett (zur nächsten Aufgabe, zum nächsten Problem). Reihum, Brett für Brett, Runde für Runde, bis die komplette Aufgabe (40-Partien zu Ende zu spielen) erledigt ist. Genau dieses 'reihum' ist deine Hauptschleife. Jedes Brett ist in deinem Programm eine Aufgabe, die es zu machen gilt. Wenn die Aufgabe lautet: 2 Zähler sollen unabhängig voneinander zählen und jeweils mit einem Taster ein oder ausgeschaltet werden können, dann hast du * 2 Zähler. Jeder Zähler kann im Zustand "läuft oder läuft nicht" sein * 2 Taster. Jeder Taster schaltet seinen Zähler in den jeweils anderen Zustand * 1 Hauptschleife die nacheinander die Ereignisse abfragt und die Zustände auswertet und Aktionen dafür ausführt
1 | mache endlos { |
2 | |
3 | //
|
4 | // Ereignisse auswerten
|
5 | // uns Zustände anpassen
|
6 | //
|
7 | if( Taster1 gedrückt ) |
8 | schalte Zähler1 um |
9 | |
10 | if( Taster2 gedrückt ) |
11 | schalte Zähler2 um |
12 | |
13 | //
|
14 | // Zustände auswerten und die notwendigen Aktionen
|
15 | // je nach Zustand ausführen
|
16 | //
|
17 | if( Zähler1 ist im Zustand läuft ) |
18 | erhöhe Zähler1 |
19 | LCD aktualisieren |
20 | |
21 | if( Zähler2 ist im Zustand läuft ) |
22 | erhöhe Zähler2 |
23 | LCD aktualisieren |
24 | }
|
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.