mikrocontroller.net

Forum: Compiler & IDEs Programm unterbrechen mit Taster


Autor: Simon R. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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()
....

  while( 1 ) {

     ....
  }

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

int main()
{
  int zustand;

  DDRB=0x21;  /*Ein- und Ausgänge*/
  DDRD=0x3F;
  DDRC=0x04;

  lcd_init();
  lcd_home();

  zustand = 0;

  while(1) {
    if( PINC & (1<<taster) )
      zustand = 1 - zustand;

    if( zustand == 0 )
      schleife_normal();
    else
      schleife_pause(zustand);
  }
}

void schleife_pause()
{
  return;   // mach nichts
}

void schleife_normal(void)
{
  zaehler++;
  lcd_data(zaehler);  /*Schreibe auf Display*/
}

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.

Autor: Simon R. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
   mache endlos {

     //
     // Ereignisse auswerten
     // uns Zustände anpassen
     //
     if( Taster1 gedrückt )
       schalte Zähler1 um

     if( Taster2 gedrückt )
       schalte Zähler2 um

     //
     // Zustände auswerten und die notwendigen Aktionen
     // je nach Zustand ausführen
     //
     if( Zähler1 ist im Zustand läuft )
       erhöhe Zähler1
       LCD aktualisieren

     if( Zähler2 ist im Zustand läuft )
       erhöhe Zähler2
       LCD aktualisieren
   }

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.