www.mikrocontroller.net

Forum: Compiler & IDEs for Schleife durch Tastendruck neu starten


Autor: xASP (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo nochmal...

Hänge wieder einmal an einer Aufgabe und weiß nicht genau wie ich sie 
realisieren kann.

Und zwar soll ich eine LED 30sec zum leuchten bringen wenn ein taster 
gedrückt wurde! Wird dieser in der Zeit nochmal gedrückt sollte der 
Timer neu beginnen.

Soll ich das  mit Interrupts realisieren?

Ich hab es mit einer for-Schleife probiert und das 30sec leuchten schon 
hinbekommen. Jetzt wollte ich sie mit break abbrechen, aber das 
funktioniert irengdwie nicht. mache ich was falsch oder ist der ansatz 
schon schief?



int main(void)

{

  initDisplay();
  SET_BIT(DDRB, DDB2);
  SET_BIT(PORTB, PB2);          // Licht zu Beginn AUS!

  while(1)

  {
    SwitchQuery();            // Tastenabfrage

    if(Taste_4)

    {
      Taste_4 = 0;
      CLR_BIT(PORTB, PB2);      // Licht dauerhaft an!
    }

    if(Taste_x)

    {
      Taste_x = 0;
      CLR_BIT(PORTB, PB2);
                           SwitchQuery();

      for (i=0; i<ON_TIME; i++)     // 30sec Licht an!
      {
                            if (Taste_x)
                            {
                                  break;
                            }
      _delay_ms(100);
      }

      SET_BIT(PORTB, PB2);      // Licht an!

    }
  }
}


void SwitchQuery()
{

// Umschaltung Port C, Bit 0..3 auf Eingang



  CLR_BIT(PORTD, ENABLE);              // Enable-Signal auf 0
  DDRC = DDRC & 0xF0;                // Port C auf Eingabe schalten
  PORTC = 0x0F;                  // Pullup-Rs eingeschaltet

  _delay_us(10);                  // Wartezeit Umstellung 
Hardware-Signal


// Einlesen der 3 Tastensignale

  sw1 = (PINC & (1 << PC0));            // aktuelle Werte der Tasten 1-4 
lesen
  sw2 = (PINC & (1 << PC1));
  sw3 = (PINC & (1 << PC2));
  sw4 = (PINC & (1 << PC3));


// Auswertung der 3 Tasten

  if (((sw1==0)|(sw2==0)|(sw3==0    // falls Taster 1-3 und NICHT Taster 
4 gedrückt ist
  {
    Taste_x = 1;                // Taste_x setzen (Licht an)
  }

  if (sw4==0)       // falls Taster 1-3 UND Taster 4 gedrückt ist
  {
    Taste_4 = 1;                // Taste_4 setzen (Licht aus)
  }

  DDRC = DDRC | 0x0F;                // PortC wieder auf Ausgang


}


Wär cool wenn ihr mir da helfen könntet!

gruß xASP

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

Bewertung
0 lesenswert
nicht lesenswert
Und wie soll Taste_x innerhalb der for-Schleife jemals einen neuen Wert 
bekommen können?

> mache ich was falsch oder ist der ansatz
> schon schief?

Deinen Ansatz könnte man zwar noch retten, aber im Grunde ist er 'schon 
schief'

Du musst weg von: Ich warte jetzt 30 Sekunden und dann sehen wir weiter.
Du musst hin zu Ereignisorientiertem Programmieren

Dazu hast du eine Hauptschleife


  while( 1 ) {
     ....
    _delay_ms( 100 );
  }

die für einen Druchlauf 100 Millisekunden benötigt (mehr oder weniger). 
Das ist deine Zeiteinheit. Innerhalb dieser Schleife gehst du daher alle 
möglichen 'Ereignisse' durch und siehst nach, ob sie eingetroffen sind.
Du bist wie ein Nachtwächter, der alle 1/2 Stunde seine Runde dreht und 
dabei nacheinander alle Fenster kontrolliert.
So ein Ereignis kann sein: Ein Taster wird gedrückt oder aber auch ein 
Zähler wird bei jeder Runde durch die while Schleife um 1 erhöht (oder 
erniedrigt) und hat zb den Zählerstand 10 erreicht, was daher 
logischerweise 1 Sekunde passiert nachdem der Zähler angefangen hat, bei 
0 wegzuzählen


void SwitchQuery()
{

// Umschaltung Port C, Bit 0..3 auf Eingang



  CLR_BIT(PORTD, ENABLE);              // Enable-Signal auf 0
  DDRC = DDRC & 0xF0;                // Port C auf Eingabe schalten
  PORTC = 0x0F;                  // Pullup-Rs eingeschaltet


lass das DDR Register und die Pullup in Ruhe.
Diese Dinge stellt man am Anfang einmal ein und dann lässt man sie in 
Ruhe

Autor: xASP (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke schonmal... habe das jetzt bissl umgeändert und funktioniert teils 
schon nach meinen wünschen. und zwar hab ich es jetzt so gemacht, dass 
ich das ganze in eine while(1) schleife gepackt habe und die pro 
durchgang i um 1 erhöht (++i). Am Ende lass ich noch eine delay von 
100ms abarbeiten.

wenn jetzt taster 4 gedrückt wird, bleibt das licht dauerhaft an, was 
auch klappt.

wenn taste x gedrückt wird, geht das licht auch an, aber durch die if 
bedingung, dass wenn i=50 erreicht, i=0 gesetzt wird, das licht ausgeht 
und die schleife abgbricht.

also wenn die ganze while schleife 50 durchläufe gemacht hat, und 
jeweils 100ms gewartet hat, sollte am schluss ja eine leuchtzeit von 5 
sec rauskommen...

es ist aber meist so um die 3 sec, manchmal weniger manchmal mehr, aber 
nie 5 sec, wieso?

SwitchQuery hab ich jetzt noch drinnen lassen, da an den Ports der 
Taster auch das DisplaySignal hängt und dieses im späteren Verlauf auch 
noch Sachen anzeigen soll.


so nun zu meiner neuen Funktion:



int main(void)

{

  initDisplay();
  SET_BIT(DDRB, DDB2);
  SET_BIT(PORTB, PB2);          // Licht zu Beginn AUS!

  while(1)

  {
    while(1)

    {

    SwitchQuery();            // Tastenabfrage

    if((Taste_4==1)&&(Taste_4n==0))

    {
      CLR_BIT(PORTB, PB2);
      _delay_ms(500);
      Taste_4 = 0;
      Taste_4n = 1;    // Licht dauerhaft an!
    }

    if ((Taste_4==1)&&(Taste_4n==1))

    {
      SET_BIT(PORTB, PB2);
      _delay_ms(500);
      Taste_4n = 0;      // Licht dauerhaft aus!
    }

    int i;
    i=0;

    while(1)

    {
      SwitchQuery();

      if((Taste_x==1)&&(Taste_xn==0))

      {
        CLR_BIT(PORTB, PB2);  // Licht an
        Taste_x = 0;
        //Taste_xn = 1;

      }

      if(i==50)

      {
        i=0;
        SET_BIT(PORTB, PB2);      // Licht aus!
        break;
      }

      if(Taste_4==1)

      {
        CLR_BIT(PORTB, PB2);      // Licht dauerhaft an, falls Taste 4!
        break;
      }

      ++i;
      _delay_ms(100);

      }
    }
  }
}


Was denkt ihr, was mach ich falsch?

Gruß xASP

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

Bewertung
0 lesenswert
nicht lesenswert
xASP schrieb:

> Was denkt ihr, was mach ich falsch?

Du bastelst und versuchst den Code den du schon hast zu retten solange 
es nur geht. Anstelle von: alles neu machen
 //
 // onTime > 0    ... Timer ist eingeschaltet und gibt die Zeit
 //                   in 100 ms Schritten an, die noch zu warten ist
 // onTime == 0   ... die eingestellte Zeit ist abgelaufen
 // onTime == -1  ... Timer ist ausgeschaltet
 //
 int onTime;

 onTime = -1;

 while(1)
 {
   SwitchQuery();            // Tastenabfrage

    if( Taste_Licht_an ) {
      CLR_BIT(PORTB, PB2);   // Licht ein
      onTime = -1;           // und den Timer, falls einer läuft abschalten
    }

    if( Taste_Licht_aus ) {
      SET_BIT(PORTB, PB2);   // Licht aus
      onTime = -1;           // und den Timer, falls einer läuft abschalten
    }

    if( Taste_Licht_zeitverzögert_an ) {
      CLR_BIT(PORTB, PB2);   // Licht ein
      onTime = 30;           // 3 Sekunden bei 100ms Durchlaufzeit
    }

    if( onTime == 0 ) {      // Der Timer ist abgelaufen
      SET_BIT(PORTB, PB2);   // Licht aus
      onTime = -1;
    }

    // wenn ein Timer eingeschaltet ist
    // dann runterzählen
    if( onTime > 0 )
      onTime--;

    delayms( 100 );
  }

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die meisten Probleme bestehen aus mehreren Aufgaben (Tasks) und dann 
kommt man mit Single-Task-Denken unweigerlich in eine Sackgasse.

Du hast mindestens schon 3 Tasks: 30s-Timer, Tastenentprellung, 
Tastenauswertung, die sich nicht gegenseitig behindern dürfen.

Man muß also der CPU die Möglichkeit geben, mehrere Tasks gleichzeitig 
auszuführen.

Beitrag "Wartezeiten effektiv (Scheduler)"


Peter

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.