Forum: Mikrocontroller und Digitale Elektronik Wechselschaltung mit ATMEGA16 und STK500


von Jenny K (Gast)


Angehängte Dateien:

Lesenswert?

Für die Einarbeitung in der Programmierung des AVR uC mit C habe ich mir 
die AVR GCC Tutorials angeschaut und auch einfache Programme 
nachgebildet.

Nun wollte ich ein Programm schreiben der die elektrische 
Wechselschaltung nachbildet und stoße da auf erhebliche Schwierigkeiten.

Im Grunde will ich folgendem Verhalten nachbilden:

Taste gedrückt ---> LED An (und bleibt an) bis die Taste wieder gedrückt 
wird zum ausschalten.

Bisher stehe vor dem Problem dass der folgende Code nur dazu führt dass 
die LED getoggelt wird (LED nur AN während Taste gedrückt wird):

  if(PINB & (1 << PINB0)){
        PORTA |= (1 << PINB0);
      }
      else
      {
        PORTA &= ~(1 << PINB0);
      }

Das Rausnehmen des else Abschnittes bringt leider keine Abhilfe.
Beigefügt ist der Code dazu.

Ich freue mich, wenn ich Hinweise erhalten kann wie ich dies lösen.

Vielen Dank,

Jenny

von Spess53 (Gast)


Lesenswert?

Hi

Lies dir mal den Artikel durch:

http://www.mikrocontroller.net/articles/AVR-Tutorial:_Tasten

Außerdem solltest du beachten, das beim STK500 eine gedrückte Taste eine 
Null liefert und eine Led bei einer Null am Pin leuchtet.

MfG Spess

von N. G. (newgeneration) Benutzerseite


Lesenswert?

Hi
1
bool t=false;
2
if(taster)
3
{
4
    false= !false;
5
}
6
if(t)
7
{
8
    ledon();
9
}
10
else
11
{
12
    ledoff();
13
}

natürlich must du die funktionen noch einsetzen, aber rein voon der 
Theoride...

hoffe konnte helfen

von Dietrich L. (dietrichl)


Lesenswert?

N. G. schrieb:
> false= !false;

Du meinst wohl:
  t = !t;

> aber rein voon der Theoride...

Das reicht aber noch nicht. Man muss nach Toogeln von "t" noch warten, 
bis der Taster wieder losgelassen wird, bevor "t" wieder getoggelt 
werden darf.
Und entprellen fehlt natürlich auch noch ;-(

Gruß Dietrich

von Jenny K (Gast)


Angehängte Dateien:

Lesenswert?

Danke für die Hilfe.

Das Programm habe ich nun wie folgt auf der Basis des Codes zur 
Entrellung von Peter Dannegger geändert, weil ich gar keine Kenntnis von 
Assembler habe und daher lieber auf C programmieren würde:


int main(void)
{

  bool t=false;

  DDRB  = 0x00;  //PortB als Eingang
  PORTB = 0x01;  //Pull-up Aktiv an PIN B0

  DDRA  = 0xff;  //PortA als Ausgang

  for(;;){

    if(debounce(PINB, PB0))
  {
  t=true;
  }
  if(t){
      PORTA |= (1<<PA0);
  }
  else
  {
    PORTA &= ~(1<<PA0);
  }
    _delay_ms(1000);
  }
}


Leider führt dies dazu, dass die LED nur noch dauernd AN ist und keine 
Reaktion auf Tastendrücke an PB0 zeigt. Was habe ich dabei falsch 
gemacht.

Euere Unterstützung finde ich großartig und gerade für eine Neulinge 
gibt das eine zusätztliche Motivation.

von Jenny K (Gast)


Lesenswert?

Kann mir bitte jemand einen Hinweis geben? Der Code habe ich nochmals 
geändert aber leider ohne Erfolg. Die LED geht bei einem Tastendruck für 
einige Sekunden AN, erlischt aber danach.

Ich wollte es aber so dass es bei einem Tastendruck AN bleibt solange 
bis der Taster wieder betätigt wird.
----------
int main(void)
{

  bool t=false;

  DDRB  = 0x00;  //PortB als Eingang
  PORTB = 0x01;  //Pull-up Aktiv an PIN B0

  DDRA  = 0x01;  //PortA als Ausgang

  for(;;){
   if(PINB & (1 << PINB0)){
  t=true;
  }
  else
  {
  t=false;
  }
  if(t){
    debounce(PINB, PB0);
      PORTA |= (1<<PA0);
  }
  else
  {
    PORTA &= ~(1<<PA0);
  }
    _delay_ms(1000);
  }
}


Danke,
Jenny

von Otto (Gast)


Lesenswert?

Du musst noch eine Variable einfügen, ob die LED zuletzt ein oder aus 
geschaltet wurde, detektieren, ob die Taste losgelassen wurde und zwei 
seperate Abfragen benutzen....

von Jenny K (Gast)


Lesenswert?

Das mit der 2.ten Variable verstehe ich noch nicht ganz. Ich dachte die 
Variable t im Programm würde es sein. Kannst Du es mir bitte genauer 
erklären?

von Otto (Gast)


Lesenswert?

Deine Tastenabfrage ist zur Zeit doppelt - das bringt dich aber nicht 
weiter.

Es müssten 2 separate if-Abfragen verwendet werden:

1. Ein: Taste UND  !Letzte_Taste UND !Taste_betaetigt

2. Aus: Taste UND Letzte_Taste UND ! Taste_betaetigt

von Jenny K (Gast)


Lesenswert?

Der Code habe ich nun wie folgt geändert:

int main(void)
{

  bool t=false;

  DDRB  = 0x00;  //PortB als Eingang
  PORTB = 0x01;  //Pull-up Aktiv an PIN B0

  DDRA  = 0x01;  //PortA als Ausgang

  for(;;){

  /* Ein */
   if(PINB & (1 << PINB0)){

    if(t==false & ~(1 << PINB0)){
        debounce(PINB, PB0);
          PORTA |= (1<<PA0);
    }

  t=true;
  }

     if(PINB & (1 << PINB0)){

    if(t==true & ~(1 << PINB0)){
        debounce(PINB, PB0);
          PORTA &= ~(1<<PA0);
    }

  t=false;
  }

  }
}


Die 2 If-Abfragen sind verschachtelt. Leider ist die LED mit dem Code 
auch nur dauernd AN.

von Otto (Gast)


Lesenswert?

1. Die Abfragen dürfen nicht verschachtelt sein.
2. Du fragst bei "ein" ab, dass die letzte Aktion "aus" war.
3. Du setzt eine Variable,  dass eine Aktion erfolgte.
4. Du speicherst, die Aktion (1=ein, 0=aus).
4. Diese fragst du ebenfalls unter 2 auf FALSE ab.
5. Erst wenn die Entprellroutine "Taste nicht betätigt" liefert, setzt 
du diese zurück.

von Jenny K (Gast)


Lesenswert?

Noch ein Update des Codes:

int main(void)
{

  bool t=false;
  bool f;

  DDRB  = 0x00;  //PortB als Eingang
  PORTB = 0x01;  //Pull-up Aktiv an PIN B0
  DDRA  = 0x01;  //PortA als Ausgang

  for(;;){

  /* 2. Ein t-->"aus" */
     if(PINB & (1 << PINB0) & ~t & ~f){ // 2. Schritt
      f=true;  // 3.+4. Schritt

      if(~debounce(PINB, PB0)){ // 5. Schritt
          PORTA |= (1<<PA0);
      }
      else{
        PORTA &= ~(1<<PA0);
        }
    }
    else
    {
      f=false; // 3.+4. Schritt
    }
  }
}


Ich habe mich an dem Hinweis von Otto gerichtet aber offensichtlich noch 
ein Fehler drin, weil es immer noch nicht klappt.

Danke für Hinweise,

Jenny

von Peter D. (peda)


Lesenswert?

Jenny K schrieb:
> keine
> Reaktion auf Tastendrücke an PB0 zeigt.

Weil Du mit
>     _delay_ms(1000);
die ganze Entprellung zunichte machst.

Riesige Delays sind Schweinereien, die in keinem Programm was verloren 
haben. Es wird zwar oft kolportiert, daß sie Anfängern das Programmieren 
erleichtern sollen, aber das genaue Gegenteil ist der Fall.

Die weiteren Versuche werden ja immer abstruser.
Debounce liefert genau einmal True bei jedem Drücken.
Einfach:
1
  for(;;){
2
    if(debounce(PINB, PB0))
3
      PORTA ^= (1<<PA0);
4
  }

von Jenny K (Gast)


Lesenswert?

Herzlichen Dank! Das war die Lösung.

von Jenny K (Gast)


Angehängte Dateien:

Lesenswert?

Habe nun versucht das Programm soweit zu erweitern, dass die LED an PA2 
angeht, wenn sowohl PB0 als auch PB1 nacheinander betätigt wurden. Dazu 
verwende ich zwei Variablen t und f in denen ich den logischen Zustand 
zwischenspeichere. Leider funktioniert dies nicht.

Was mache ich dabei falsch oder worauf muss ich generell bei der 
Zwischenspeicherung in einer temporären Variable achten?

int main(void)
{

  bool t=false;
  bool f=false;

  DDRB  = 0x00;  //PortB als Eingang
  PORTB = 0xff;  //Pull-up Aktiv an PIN B0

  DDRA  = 0xff;  //PortA als Ausgang
  PINA &= 0x00;
    for(;;){

      if(debounce(PINB, PB0)){
      t=true;
    PORTA ^= (t <<PA0);//Toggle entsprechend PA0 läuft wie erwartet
    }
    else{
    t=false;
    }

    if(debounce(PINB, PB1)){
      f=true;
    PORTA ^= (f <<PA1);  //läuft wie erwartet
    }
    else{
      f=false;
    }

      if(t&f){   //Bedingung wird nicht über die LED an PA2 nachgebildet
      PORTA |= (1 <<PA2);
    }
    else
    {
      PORTA &= ~(1 <<PA2);
    }

  }

}

Danke für die Unterstützung.

Jenny

von Hubert G. (hubertg)


Lesenswert?

Jenny K schrieb:
> if(t&f){   //Bedingung wird nicht über die LED an PA2 nachgebildet

Willst du wirklich t und f verknüpfen oder abfragen t&&f ?

von Peter D. (peda)


Lesenswert?

1
    if(debounce(PINB, PB0)){
2
      t=true;
3
    }
4
    if(debounce(PINB, PB1)){
5
      if(t){
6
        t=false;
7
        PORTA ^= (1 <<PA2);
8
      }
9
    }

Nochmal, debounce() liefert jedes Ereignis genau einmal.
Die ganzen else sind daher Unsinn, sie würden ständig durchlaufen.

von Jenny K (Gast)


Lesenswert?

Heißt es dann dass die debounce() Funktion nicht für Mehrtastenabfragen 
verwendet werden kann?

von Karl H. (kbuchegg)


Lesenswert?

Jenny K schrieb:
> Heißt es dann dass die debounce() Funktion nicht für Mehrtastenabfragen
> verwendet werden kann?

Was ist eine 'Mehrtastenabfrage'?

Wenn du das meinst, was ich denke das du meinst, dann sieh dir halt mal 
das letzte Beispiel von PeDa GENAU an.
Was denkst du, warum da einmal PB0 und das andere mal PB1 als Argument 
zum debounce steht? Du musst schon die Dinge GENAU studieren, die du 
fertig vorgesetzt bekommst!

von Jenny K (Gast)


Lesenswert?

der Hintergrund ist das ich für ein Praktikum eine Art Zustandautomaten 
programmieren soll der abhängig von der gerade gedrückten Tasten 
bestimmte Ausgänge (LED, Relais) an/aus machen soll. Da die Aufgabe für 
mich komplex erscheint, habe ich überlegt erst mit 
einfachen/grundsätzlichen Fragestellungen (Zustandszuweisung in 
Hardware, boolsche Verknüpfung in HW,...) anzufangen.

Mit Mehrtastenabfrage meine ich:

Taster 1 wird betätigt --> debounce() wird aufgerufen und der ON 
(betätigt) Zustand in einer boolschen Variable x (TRUE) gespeichert. 
Falls der Taster 2 danach auch betätigt wird wird die debounce() 
Funktion erneut aufgerufen und eine Variable y (TRUE) speichert 
ebenfalls den Zustand.Erst abhängig von der Abfrage, ob x und y beide 
TRUE sind wird der entsprechende Ausgang PIN aktiviert/deaktiviert.

In der C-Programmierung wie wir es in der Vorlesung machen geht das 
ganze etwas einfacher. Die prinzipielle Funktion in C wobei die Taster 
und LED als boolsche Variablen deklariert sind läuft auch.

Ich finde eure Unterstützung wirklich klasse und Danke dafür.

Jenny

von Karl H. (kbuchegg)


Lesenswert?

Jenny K schrieb:

> Mit Mehrtastenabfrage meine ich:
>
> Taster 1 wird betätigt --> debounce() wird aufgerufen und der ON
> (betätigt) Zustand in einer boolschen Variable x (TRUE) gespeichert.
> Falls der Taster 2 danach auch betätigt wird wird die debounce()
> Funktion erneut aufgerufen und eine Variable y (TRUE) speichert

Du missverstehst das irgendwie.

Grundsätzlich muss dein Programm in einer Art Dauerschleife laufen.
Innerhalb dieser Dauerschleife wird debounce FÜR EINEN BESTIMMTEN PIN 
aufgerufen. Dieser debounce Aufruf teilt dir mit, ob die Taste in der 
Zeit seit dem letzten Aufruf für diese Taste niedergedrückt wurde oder 
nicht. Allerdings überwacht debounce die Taste nicht ständig. Die 
Grundannahme ist, dass bei zb 1000 Aufrufen von debounce in 1 Sekunde 
keinen Menschen finden wird, der es schafft eine Taste kurz genug zu 
drücken, dass dies bei diesen 1000 Aufrufen pro Sekunde unentdeckt 
bleibt. debounce vergleicht einfach den jetzigen Tastenzustand mit dem 
Tastenzustand vom letzten Aufruf und wenn der unterschiedlich ist, dann 
meldet es einen Tastendruck. Unterscheiden sich die beiden nicht, dann 
meldet es keinen Tastendruck. Aber debounce wartet nicht darauf, dass 
der Benutzer eine Taste drückt.

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.