Forum: Compiler & IDEs for Schleife durch Tastendruck neu starten


von xASP (Gast)


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

von Karl H. (kbuchegg)


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


1
void SwitchQuery()
2
{
3
4
// Umschaltung Port C, Bit 0..3 auf Eingang
5
6
7
8
  CLR_BIT(PORTD, ENABLE);              // Enable-Signal auf 0
9
  DDRC = DDRC & 0xF0;                // Port C auf Eingabe schalten
10
  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

von xASP (Gast)


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

von Karl H. (kbuchegg)


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
1
 //
2
 // onTime > 0    ... Timer ist eingeschaltet und gibt die Zeit
3
 //                   in 100 ms Schritten an, die noch zu warten ist
4
 // onTime == 0   ... die eingestellte Zeit ist abgelaufen
5
 // onTime == -1  ... Timer ist ausgeschaltet
6
 //
7
 int onTime;
8
9
 onTime = -1;
10
11
 while(1)
12
 {
13
   SwitchQuery();            // Tastenabfrage
14
15
    if( Taste_Licht_an ) {
16
      CLR_BIT(PORTB, PB2);   // Licht ein
17
      onTime = -1;           // und den Timer, falls einer läuft abschalten
18
    }
19
20
    if( Taste_Licht_aus ) {
21
      SET_BIT(PORTB, PB2);   // Licht aus
22
      onTime = -1;           // und den Timer, falls einer läuft abschalten
23
    }
24
25
    if( Taste_Licht_zeitverzögert_an ) {
26
      CLR_BIT(PORTB, PB2);   // Licht ein
27
      onTime = 30;           // 3 Sekunden bei 100ms Durchlaufzeit
28
    }
29
30
    if( onTime == 0 ) {      // Der Timer ist abgelaufen
31
      SET_BIT(PORTB, PB2);   // Licht aus
32
      onTime = -1;
33
    }
34
35
    // wenn ein Timer eingeschaltet ist
36
    // dann runterzählen
37
    if( onTime > 0 )
38
      onTime--;
39
40
    delayms( 100 );
41
  }

von Peter D. (peda)


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

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.