Forum: Mikrocontroller und Digitale Elektronik Troubleshoot einfache Entprell-Routine


von Thomas (Gast)


Lesenswert?

Hallo,

bin noch relativ neu im Bereich uC Programmieren und C-Programmieren. 
Ich habe nun mit AVR Studio und einem Atmega 328P versucht folgende 
einfache Funktion zu realisieren:

Wird der Taster kurz gedrückt, wird die LED eingeschaltet, wird der 
Taster lang gedrückt geht diese wieder aus.
Leider tut sich schlicht und ergreifend, gar nichts.

Vielleicht kann mir hier jemand meine Programm/Programmierfehler 
aufzeigen und Tipps für das Weitermachen geben.

Vielen Dank im Vorraus.

mfg Thomas
1
#include <asf.h>
2
#include <avr/io.h>
3
#include <stdbool.h>
4
5
#define F_CPU 16000000
6
7
bool lastState=0;
8
bool newState=0;
9
bool ledOn=0;
10
11
bool kurz=0;
12
bool lang=0;
13
14
uint8_t toggle=0;
15
16
uint8_t shortPress=5; //50ms debounce Zeit
17
uint16_t longPress=50; //500ms Wartezeit
18
uint16_t i=0;
19
20
ISR (TIMER0_COMPA_vect){    //ISR Routine - Wird ca alle 10ms aufgerufen
21
  newState=PIND3;        //Taster Zustand abrufen
22
  if(newState==lastState){  //Wenn sich der Zustand seit dem letzten Aufruf nicht geändert hat Zählvariable erhöhen
23
    i++;          
24
  }
25
  if(i==shortPress){      //Wenn Taster 5 Durchläufe, also 50ms gedrückt wird, wird die Toggle Variable gesetzt
26
  toggle=1;  
27
  }
28
  if(i==longPress){      //Wenn Taster 50 Durchläufe, also 0,5s gedrückt wird, wird die Toggle Variable zurückgesetzt
29
  toggle=0;
30
  }
31
  lastState=newState;
32
} 
33
  
34
int main (void)
35
{
36
  DDRB |= (1<<PB5);    //LED-Pin als Output
37
  DDRD &= ~(1<<PD3);    //Taster-Pin als Input
38
  
39
  TCCR0A |= (1<<WGM01);        //Timer in CTC Mode
40
  TCCR0B |= (1<<CS02) | (1<<CS00);  // F_CPU/1024 
41
  OCR0A = 156;            //Compare Wert einstellen
42
  TIMSK0 |= (1<<OCIE0A);        //Compare Match Interrupt aktivieren
43
  sei();                //Interrupts aktivieren
44
45
  for(;;){
46
    if(toggle==1){
47
      PORTB |= (1<<PINB3);    //Toggle Variable auf den LED-Pin übertragen
48
    }
49
    else{PORTB &= ~(1<<PINB3);
50
      }
51
  }
52
  return 0;
53
}

von Jim M. (turboj)


Lesenswert?

Die "toggle" Variable ändert sich im Interrupt, daher deklariert man die 
besser so:
1
volatile uint8_t toggle=0;

Ansonsten optimiert der Compiler den Zugriff darauf gnadenlos weg.

von Flohzirkus (Gast)


Lesenswert?

Auch die anderen in der ISR verwendeten Variablen sollten volatile 
deklariert sein.

Außerdem: Deine Zählervariable zählt nicht nur die Zeit, in der der 
Taster gedrückt ist, sondern auch die Zeit, in der er nicht gedrückt 
ist.
Sie wird nie zurückgesetzt - zählt also munter weiter bis zum Überlauf.

So sollte die LED dann eigentlich einmal zu Beginn und dann alle elf 
Minuten wieder für 450 ms leuchten.
Durch einen Tastendruck kannst du das um ein paar Millisekunden 
verzögern.

Schönen Sonntag noch :-)

von Thomas (Gast)


Lesenswert?

Hallo, vielen Dank schonmal,

habe gestern dann auch noch gemerkt, dass erstens die Zählvariable nie 
gedrückt wird und zweitens die Variable auch erhöht wird wenn der Taster 
nicht gedrückt ist und sich der Zustand lediglich nicht ändert.
Habe auf dieser Seite aber nun eine ganz gute Anleitung gefunden.

mfg Thomas

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.