Forum: Compiler & IDEs Programm unterbrechen mit Taster


von Simon R. (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Simon R. (Gast)


Lesenswert?

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!

von Karl H. (kbuchegg)


Lesenswert?

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
Noch kein Account? Hier anmelden.