Forum: Mikrocontroller und Digitale Elektronik Interrupt button


von Peter (Gast)


Lesenswert?

Hallo, ich möchte mit einem Button einen Interrupt auslösen. Bisher habe 
ich immer in der while schleife abgefragt
1
int main(){
2
  while(1){
3
    ...
4
    if(PINB&(1<<PINB4)){
5
      PORTB |= (1<<PB0); // LED an      
6
      _delay_ms(1000);
7
    }
8
    else{
9
      PORTB &= ~(1<<PB0); // LED aus
10
    }
11
    ...
12
  }
13
}

Jetzt ist es ja so, dass die while schleife immer durchläuft und nur 
wenn ich im richtigen zeitpunkt den Taster gedrückt halte, die LED 
angeht.
Kann man das auch so machen, dass eine Routine aufgerufen wird, sobald 
ich den Taster drücke und dort dann drinn steht:
1
      PORTB |= (1<<PB0); // LED an      
2
      _delay_ms(1000);
so könnte ich das dann aus der hauptschleife raus nehmen.

von chris (Gast)


Lesenswert?

Peter schrieb:
> Jetzt ist es ja so, dass die while schleife immer durchläuft und nur
> wenn ich im richtigen zeitpunkt den Taster gedrückt halte, die LED
> angeht.

damit hast du erkannt, dass delay nur Probleme verursacht und fast nie 
sinnvoll ist.

Taster an Interrupts zu hängen ist der nächste Fehler ;)
Und delay in Interrupts ist eine noch viel schlimmere Todsünde.

Lies dir mal diesen Artikel durch:
http://www.mikrocontroller.net/articles/Entprellung

Insbesondere den Abschnitt "Timer-Verfahren (nach Peter Dannegger)"


lg
Chris

von Tho W. (tommyprog)


Lesenswert?

Sers,

natürlich könntest du das ganze außerhalb der main in eine extra 
"methode" funktion oder wie man es sonst noch nennen will, packen.

Vergiss aber nicht, die Funktion auch noch als Prototyp festzulegen, da 
du sonst einen Fehler bekommst.
Hab die Übung ausm lehrbuch (stark ähnlich) übrigens schon hinter mir, 
und kann mir auch vorstellen, was bei dir danach noch kommt.

Mfg,
tommyProg

von Tho W. (tommyprog)


Lesenswert?

chris schrieb:
> Peter schrieb:
>> Jetzt ist es ja so, dass die while schleife immer durchläuft und nur
>> wenn ich im richtigen zeitpunkt den Taster gedrückt halte, die LED
>> angeht.
>
> damit hast du erkannt, dass delay nur Probleme verursacht und fast nie
> sinnvoll ist.

Mag sein, aber lass ihn das noch ausprobieren, und ihn stück für Stück 
machen.
> Taster an Interrupts zu hängen ist der nächste Fehler ;)

Hehe, ich weiß noch wo ich das gemacht hatte.
Du hast nicht recht, es ist kein Fehler, aber man soll es nicht machen, 
weil es technisch katastrophal ist.

In einer Übung ausm Lehrbuch wird das aber so verlangt. Und Lösungen 
gibts nur eigene^^.

> Und delay in Interrupts ist eine noch viel schlimmere Todsünde.
Ja, da hast du recht, warteschleifen, LCD ausgaben usw. sind der 
wahnsinn³ in ISR's

> Lies dir mal diesen Artikel durch:
> http://www.mikrocontroller.net/articles/Entprellung
>
> Insbesondere den Abschnitt "Timer-Verfahren (nach Peter Dannegger)"

Timer- Verfahren würde ich noch nicht durchlesen, weil es da auch 
interrupt verfahren gibt, und wie man einen Timer programmiert scheint 
anfangs schwer (habs gestern erst gemacht). Von daher mach dann eher mit 
interrupts weiter, und wenn du das System dahinter verstanden hast,
dann würde ich mir timer anschauen.

Schau mal in paar Tagen auf youtube interrupt grundlagen an, da müsst 
nen video aus koblenz geben, wo der prof das sehr gut erklärt.

mfg,
tommyProg

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Tho Wes schrieb:

> Timer- Verfahren würde ich noch nicht durchlesen, weil es da auch
> interrupt verfahren gibt, und wie man einen Timer programmiert scheint
> anfangs schwer (habs gestern erst gemacht).

Timer sind die leichteste Übung von allen
FAQ: Timer
Die Hauptschwierigkeit ist das Begreifen wie einfach die Sache 
eigentlich ist, weil alle in einem Timer immer viel mehr sehen, als da 
tatsächlich dahinter steckt.

Dagegen ist eine reine externer Interrupt Software-Lösung für einen 
Taster eine harte Nuss. Lehrbuch hin oder her.
Ausserdem bringt es ihm nichts, solange er mit delay arbeitet. Der 
Prozessor kann  nun mal nur eine Sache zu einem bestimmten Zeitpunkt 
machen. Wenn er im delay hängt, dann hängt er im delay. Egal ob das in 
main() oder in einer ISR ist. Davon kommt man nur weg wenn man Timer 
benutzt. Und so schwer ist das auch wieder nicht. Dafür aber sehr 
wichtig, das man diese Technik beherrscht. Ganz im Gegensatz zu 'Taster 
an externem Interrupt'.

Allenfalls kann man noch über die Beobachtung gehen, dass 1000 mal 1ms 
gewartet in Summe auch 1000ms gewartet sind. Will man also eine LED 1 
Sekunde nach dem Drücken und Loslassen einer Taste verlöschen lassen und 
kann nichts anderes als delay, dann kann man immer noch:
1
int main()
2
{
3
  uint16_t waitTime;
4
5
...
6
7
  waitTime = 0;
8
9
  while(1){
10
    ...
11
    if(PINB&(1<<PINB4)){
12
      waitTime = 1000;
13
      PORTB |= (1<<PB0); // LED an      
14
    }
15
16
    if( waitTime > 0 ) {
17
      waitTime--;
18
      if( waitTime == 0 )
19
        PORTB &= ~(1<<PB0);  // LED aus
20
    }
21
    _delay_ms( 1 );
22
    ...
23
  }
24
}

mit der 1 Millisekunde kann man eventuell leben, für einen Lernenden auf 
dem Weg zum Verständnis eines Timers wäre das für mich eine akzeptable 
Lösung. Aber auf lange Sicht hilft nur: lernen wie man mit einem Timer 
einen Basistakt generiert und davon dann alles weitere ableitet. Das ist 
insofern wichtig, weil damit auch ein Wechsel in der 
Programmierphilosophie einher geht (der in der letzten Lösung schon ein 
wenig angedeutet ist), der extrem wichtig in der µC Programmierung ist. 
Timer sind DIE Arbeitspferde in einem µC Programm. Demenstrechend 
wichtig ist es auch, mit ihnen umgehen zu können und einige 
Softwaretechniken zu können, die auf Timern basieren.

: Bearbeitet durch User
von Peter (Gast)


Lesenswert?

Ich habe da noch mal eine Nachfrage, das mit dem Interrupt habe ich 
hinbekommen, war ja gar nicht so schwierig. Allerdings kann ich nur 
Pin7, also INT0 nehmen.
1
int main(){
2
  MCUCR |= (1<<ISC00) | (1<<ISC01); 
3
  GIMSK |= (1<<INT0); 
4
  while(1){
5
    ...
6
    ...
7
  }
8
} 
9
10
ISR(INT0_vect){
11
  PORTB |= (1<<PB0);
12
  _delay_ms(1000);
13
  PORTB &= ~(1<<PB0);
14
}

das funktioniert ja auch. Aber das mit dem _delay_ms(1000) bekomme ich 
auch noch weg.
Meine Frage geht aber eher richtung der Funktion.

chris schrieb:
> Taster an Interrupts zu hängen ist der nächste Fehler ;)

Wieso?

von spess53 (Gast)


Lesenswert?

Hi

>Wieso?

Weil Taster prellen. Aber

>ISR(INT0_vect){
>  PORTB |= (1<<PB0);
>  _delay_ms(1000);
>  PORTB &= ~(1<<PB0);
>}

Delays in Interrupts, noch dazu in dieser Größenordnung, sind ein 
absoluter NoGo.

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

Peter schrieb:

>> Taster an Interrupts zu hängen ist der nächste Fehler ;)

Weil Taster prellen.
Du drückst einmal und es werden 5 Interrupts ausgelöst. Wie stellst du 
denn fest welche der Interrupts aufgrund eines Prellvorgangs (der dauert 
so in der Größenordnung von 5 bis 10ms) ausgelöst wurden und welcher 
Interrupt real wegen einem Tastendruck durch den Benutzer ausgelöst 
wurde?
Es zeigt sich, dass du durch einen externen Interrupt keinerlei Vorteil 
mehr hast. Ganz im Gegenteil wird der Code komplexer als wenn man gleich 
auf Pollen in einer Timerschleife setzt. Um zu Entprellen muss in 
irgendeiner Form eine zeitliche Steuerung rein. Und zeitliche Steuerung 
bedeutet in einem µC zu 99% praktisch immer der Einsatz eines Timers. 
Wenn ich den Timer aber sowieso zum Entprellen brauche(*), dann kann 
dort auch gleich das Tastenpollen mit gemacht werden. Ein Taster an 
einem externen Interrupt macht nur dann Sinn, wenn man den µC dadurch 
aus dem Stromspar-Tiefschlaf holen muss.


Und keine Sorge.
Auch wenn deine Taster jetzt noch nicht prellen - irgendwann werden sie 
es tun. Das ist so sicher wie das Amen im Gebet.


(*) abgesehen davon hat so gut wie jedes irgendwie ernstzunehmende 
Programm mindestens 1 Timer im Einsatz. D.h. das ist noch nicht mal 
massig Mehraufwand, den auch noch zum Tastenbehandeln einzusetzen.

: Bearbeitet durch User
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.