Forum: Mikrocontroller und Digitale Elektronik Programm hängt sich auf bei INT1 Taster


von Christian P. (peterfrosta)


Angehängte Dateien:

Lesenswert?

Hallo liebe Gemeinde,

folgendes Problem habe ich:

Habe auf meinem Board mit nem Atmega8 einen Taster an INT1 hängen.
Dieser ist hardwaremäßig entprellt (analago zu dem Beispiel zur
ENTPRELLUNG von mikrocontroller.net).

Das Hauptprogramm seht ihr im Anhang.

Das Programm legt sich nach der Initiallisierung des Notwendigen
schlafen und wird durch den Taster (Int1 dann auf GND) geweckt.
Danach wird lediglich der INT1 deaktiviert und das "clientmenu"
aufgerufen.
In clientmenu(); passiert prinzipiell nichts weiter als dass die Dauer
des Tastendrucks (welcher den INT1 auslöste) "gemessen" wird. Und dann
in Abhängikeit der Dauer zwischen 3 auszuführenden Funktionen gewählt
wird (kleiner 100 = 1s, 100-400 = 1-4s, größer 400 ),  Dazu dient
folgende Funktion:

unsigned int taster_time(void)
{
  unsigned int i = 0;
  led_on();

//warte solange taste gedrückt ist
  while(  !(TASTERPIN & (1<<TASTER)) )
  {
    _delay_ms(10);
    i++;
  }

  _delay_ms(30);

  return i;
}

Ich weiß das man so etwas mit Timer sinvoll lösen können soll aber so
war es erstmal einfacher.

Das Problem ist nun, dass bei zu schnell aufeinander folgenden
Tastendrücken das Programmen sich aufhängt. Ich also die Batterie raus
und rein tun muss. Zu schnell bedeutet hier, dass 3 Drücke pro Sekunde
meist kein Problem sind aber wenn man es richtig drauf anlegt, hängst
es.

Die Entprellung sieht auf dem Oszilloskop recht gut aus, auch bei den
"Zerstörer"-Tastendrücker. Daher frag ich mich, wo die Ursache dafür
liegt?

Als kleine Debug-Hilfe schaltet die taster_time(); eine LED ein , das
Auschalten der LED (led_off();) habe ich dann immer weiter nach hinten
geschoben. Damit wollte ich feststellen wo das Programmen hängen bleibt.
Das led_off(); in der Interrupt-Routine hinter clientmenu(); wurde immer
ausgeführt. Also auch wenn das Prog hingen blieb, ging die LED aus.
Die nächst möglichste stelle sollte dann ja die Stelle sein, wo das
Programm nach der Interrupt-Routine weiterläuft. So habe ich das
led_off(); dorthin verschoben. nun blieb die LED an, wenn das Programm
sich aufhing.

Also ergeben sich mir 2 Fragen, warum hängt sich das Programm bei zu
schnellen Tastendrücker auf?

Und warum schaltet die LED in der ISR aus, direkt danach aber nicht?
(Siehe Code im Anhang).

Vielen dank für jene die themenbezogen helfen wollen!
mfg

von Stefan (Gast)


Lesenswert?

Mich irritiert mich das:
<code>
while(  !(TASTERPIN & (1<<TASTER)) )
</code>

Um einen Taster an Port A4 abzufragen, würde ich sowas schreiben:
<code>
while ( !(PINA & (1<<4)) )
</code>

Leider ahst Du auch nicht den QUelltext gepostet, wo die beiden 
Konstanten für den Taster deklariert sind. Den Namen nach vermute ich 
allerdings, dass Du TASTERPIN und TASTER vertauscht hast und dass sich 
das Programm deswegen an dieser Stelle aufhängt.

von Christian P. (peterfrosta)


Lesenswert?

Ja sorry...
die defines dazu habe ich versäumt zu posten...
Hier:

/////////////////////////////////////////////////////
//////    LED Funktionsbekanntgabe  + Taster  /////////
/////////////////////////////////////////////////////

//LED udn AUSGANG
#define LEDDDR    DDRB
#define  LEDPORT  PORTB

#define LED1    PB1

//TASTERPORT
#define TASTERDDR  DDRD
#define TASTERPORT  PORTD
#define TASTERPIN  PIND

#define TASTER     PD3


/////////////////////////////////////////////////////
// LED Ports initialisieren            ///************/ //plus Taster1
/////////////////////////////////////////////////////

void init_port()
{
  LEDDDR |= ( (1<<LED1) );      // PIND 3 als Ausgang
  LEDPORT &= ~( (1<<LED1) );      //ausgange auf low


  TASTERDDR &= ~(1<<TASTER);      //Taster als Eingang
  //TASTERPORT &= ~(1<<TASTER);      //TASTER ohne Pullup
  TASTERPORT |= (1<<TASTER);      //TASTER mit Pullup  // für 
Lvl-Interrup, Taster zieht eingang nun auf GND nicht auf 3/5 Volt
}

von Kater brummt-sehr gut! (Gast)


Lesenswert?

Also, jetzt rein vom Gefühl her: ein zeitliches Delay von zig ms 
innerhalb einer Interruptroutine macht man einfach nicht. Was passiert 
denn, wenn die Taste 1 min gedrückt ist, mit den weniger priorisierten 
Ints oder dem Hauptprogramm, das vielleicht zyklisch einen Port pollt 
etc.? Bevor ich mir den Riss gebe, warum dieses Konsrukt nicht 
funktioniert, baue ich es doch besser mit Timer oder setze schnell ein 
Bit oder eine Semaphore etc in der INT Routine und kehre schnell zurück, 
Im Hauptprogramm schreibe ich dann eine Stoppuhr, insbesondere bei einem 
kleinen uc wie dem M8.
Nur mal so als Vorschlag...

von Christian P. (peterfrosta)


Lesenswert?

ah du meinst.. den ISR nur zum aufwachen benutzen und den rest im 
hauptprogramm erledigen... das ist ein guter Ansatz bzw ein Versuch 
wert!

was passiert wenn er 100 Sekunden fgedrückt wird war mir "relativ" egal. 
Da das ein - ich sag mal - Lichtschalter ist, der in der regel nur 
schläft und meist nur was anschalten soll. die beiden optioen länger zu 
drücken sind für eine art Einstellung gedacht.
Im schlimmstenfall hatte ich mir vorgestellt, passiert bei so langem 
drücken einfach ein Überlauf der Zählervaiable (unsigned int ca 6500 
Sekunden). Dass eine solche Dauer oder auch meine sonstigen Taster-Dauer 
in der ISR grundsätzlich problematisch sind, habe ich garnicht bedacht.

von Stefan (Gast)


Lesenswert?

Die Abfrage der Taste ist jedenfalls nicht falsch, jetzt wo ich die 
Definitionen sehe.

von Christian P. (peterfrosta)


Lesenswert?

also habe das clientmenu raus aus der isr genommen und unter das sleep 
gedöns in der main gepackt... ändert leider nichts an den abstürzen
:-(

von Christian P. (peterfrosta)


Lesenswert?

keine weiteren Ideen??
;)

von STK500-Besitzer (Gast)


Lesenswert?

Christian Peskov schrieb:
> keine weiteren Ideen??

Wie wäre es mit vollständigem Quellcode? Oder habe ich da was übersehen?

von Sebastian W. (sebastian_w29)


Lesenswert?

Wie hat du die Fuses programmiert? Slow or fast rising power? Interner 
Oszillator oder externer Quartz? Welche Versorgungsspannung?

Bei slow rising power braucht der Atmega ja 65ms+ um aus dem power down 
sleep mode aufzuwachen. Bei dir scheint er sich aufzuhängen wenn in 
dieser Zeit ein zweiter INT1 interrupt reinkommt.

Programmier doch spasseshalber mal fast rising power, um zu sehen, ob 
sich dann am Verhalten was ändert.

LG, Sebastian

von Christian P. (peterfrosta)


Lesenswert?

das klingt ganz schön plausibel für eine mögliche Abhilfe... wen dieses 
Karnevalgedöns mich in ruhe lässt, werde ich testen, ob die änderung der 
aufweckzeit besserung bewirkt. danke.

an stk500 besitzer:
nein du hast nichts übersehen.. aber statt die weiteren 5 includes zu 
posten habe ich  es umschrieben. und es wird (wie du siehst) nur die 
clientmenu per INT aufgerufen. Und da werden nunmal nur die drei 
beschriebenen Fälle unteschieden. im innern dieser funktion und der 
entsprechnenden Includes vermute ich die ursache NICHT.

mfg

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.