Hallo liebe Leute!
Ich habe hier ein einfaches Programm, welches nach dem Einschalten des
Controllers erstmal nur ein Ampellicht geben soll.
Sobald INT0 aktiv wird (Taster gedrückt wird), so soll die
Interrrupt-Routine (ISR) ausgeführt werden. Das ist dann einfach ein
Blinklicht der Ampel auf allen 3 LEDs.
Sobald ich den Taster erneut drücken möchte, soll wieder die normale
Ampelsteuerung (Rot-Rotgelb-Grün--Gelb-Rot) funkionieren, usw.
Wie realisiere ich das??
Hier der Code:
1
#include<avr/io.h>
2
#include<util/delay.h>
3
#include<avr/interrupt.h>
4
5
6
7
ISR(INT0_vect)// Interrupt-Vektor-Service-Routine -> was passiert, wenn Interrupt ausgelöst wird?
8
{
9
while(1)
10
{
11
PORTB=0x38;
12
_delay_ms(10);
13
PORTB=0;
14
_delay_ms(10);
15
}
16
17
}
18
19
20
intmain(void)
21
{
22
23
DDRB=0x38;
24
25
26
MCUCR|=(1<<ISC01);
27
MCUCR&=~(1<<ISC00);
28
GIMSK|=(1<<INT0);// fallende Flanke an INT0 erzeugt Interrupt
Die Interrupt-Routine wird nie mehr verlassen. Da beim Eintritt in die
Routine das I-Flag gelöscht wird, werden bis zum Verlassen keine
weiteren Interrupts behandelt.
Ergo: Aufgehangen.
Endlosschleifen und Delays in Interruptroutinen sind überdies eh nich so
prickelnd.
Da mechanische Taster prellen, ist das mit dem Interrupt keine gute
Idee. Hier im Forum gibt es diverse Routinen zum Entprellen per
Software, die du dafür nutzen kannst. Die Ergebnisse fragst du dann
einfach in der Hauptschleife ab.
Gruß, DetlevT
das mit der Ampelphasenlänge ist mir bewusst, da ich das Programm nur
simuliere und momentan die "virtuelle Taktfrequenz" zu niedrig wäre um
nicht stundenlang auf einen "Signalwechsel" warten zu müssen. Deshalb
hab ich die "delay-Zeit" auf nur 30 ms gesetzt.
Vom Entprellen der Taster natürlich abgesehen, mir gehts nur darum, wie
ich aus der Interrupt-Funktion wieder herauskomme.
Gruß
INT-0-8-15 schrieb:> mir gehts nur darum, wie> ich aus der Interrupt-Funktion wieder herauskomme.
indem du dort den Pin vom Taster abfragst? statt while(1)
Dein Grundgedanke scheint, der Beschreibung entsprechend, gewesen zu
sein, das das Programm nach dem Tastendruck in einer Sondersituation
(alle Lichter blinken) ist.
So hast Du aber die Beschreibung der Funktion zu direkt in ein Programm
umgesetzt.
Zwar soll ein Interrupt die Behandlung von asynchronen Ereignissen
ermöglichen, aber das heisst nicht, das er auch unmittelbar zur Trennung
von Betriebsarten dient, d.h. das in main das "normale" Programm abläuft
und im Interrupt das "besondere" Programm.
Die zwei verschiedenen Abläufe werden beide in main beschrieben.
Lediglich die Umschaltung zwischen den beiden Abläufen erfolgt im
Interrupt. Das bedeutet im allgemeinen das setzen einer (volatile)
Variable im Interrupt, die dann in main abgefragt wird. Passenderweise
an einer Stelle bei der sinnvolle Übergänge zwischen den Betriebsweisen
möglich sind.
Was hier über Tastenentprellung gesagt wurde ist dennoch zusätzlich zu
beachten.
Viel Erfolg
> indem du dort den Pin vom Taster abfragst? statt while(1)
Dann würde der aber doch nur ein einziges Mal das Blinken blinken
lassen, oder?
1
ISR(INT0_vect)// Interrupt-Vektor-Service-Routine -> was passiert, wenn Interrupt ausgelöst wird?
2
{
3
if(PINB==wert)
4
{
5
PORTB=0x38;
6
_delay_ms(10);
7
PORTB=0;
8
_delay_ms(10);
9
}
10
11
}
Wäre das nicht doppelgemoppelt? Weil dass der PIN gedrückt wurde, ist ja
sicher, sonst wäre er erst garnicht in die ISR-Routine gekommen,
richtig?
Gruß
INT-0-8-15 schrieb:> Wäre das nicht doppelgemoppelt? Weil dass der PIN gedrückt wurde, ist ja> sicher, sonst wäre er erst garnicht in die ISR-Routine gekommen,> richtig?
Schon.
Aber deine Frage war ja: wie komme ich aus der ISR wieder raus, wenn der
Taster losgelassen wird. Und diese Lösung würde realsieren: Solange die
Taste gedrückt ist, bleibt das Programm in dieser Schleife hängen.
Vielleicht ist dir auch gar nicht bewusst, dass diese Abfrage das hier
realsiert:
* solange eine Taste gedrückt ist
und nicht
* wenn eine Taste gedrückt wurde, mache einmal
Aber sei gewarnt: Es ist trotzdem die falsche Lösung.
Die richtige Lösung besteht darin, wie weiter oben schon angesprochen,
dass deine Hauptschleife 2 Modi hat, die per Variable ausgewählt werden.
In der ISR wird dann einfach nur der andere Modus ausgewählt, in dem die
Variable entsprechend gestellt wird.
Auf solche nicht absehbar langen Schleifen in einer ISR solltest du dich
erst gar nicht einlassen.