Forum: Mikrocontroller und Digitale Elektronik atxmega und externer interrupt


von klarst (Gast)


Lesenswert?

Hallo,

ich habe ein Problem mit meinem externen interrupt am Atxmega16D4. Ich 
habe folgenden Code:
1
PORTC.INTCTRL |= 0x03;                     
2
PORTC.INT0MASK |= PIN0_bm;                  
3
PORTC.PIN0CTRL |= PORT_ISC_RISING_gc;    
4
5
PMIC.CTRL |= PMIC_HILVLEN_bm; 
6
SREG |= 0x80;    
7
sei();
8
9
ISR(PORTC_INT0_vect)  
10
{                    
11
 //mache irgendwas für zwei µs
12
}

Im Grunde funktioniert das Ganze. Bei einer steigenden Flanke am Pin 
springt der Controller eine Mikrosekunde später in die ISR. Soweit OK.

Das Problem ist jedoch, dass mein Signal am Pin in dieser Mikrosekunde 
an Reaktionszeit bereits ein zweites mal mit steigender Flanke an diesem 
Pin anlag, sodass der Controller direkt nachdem er die ISR verlassen 
hat, sofort erneut in die ISR springt. Wie kann ich das vermeiden?

von Route_66 H. (route_66)


Lesenswert?

Was jetzt?
Soll der Controller auch die zweite Flanke auswerten oder nicht?

Oder anders ausgedrückt:
Was ist das für ein Signal? Wie oft kommt die Flanke? Wieviele Flanken 
sollen ausgewertet und wieviele ignoriert werden?

von Klarst (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe ein Bild erstellt, vielleicht hilft das weiter.

Die zweite Flanke soll nicht ausgewertet werden.
Das Signal am Pin0 wiederholt sich alle 5 Millisekunden und ich möchte 
stets nur auf die erste Flanke reagieren. D.h. ich möchte alle 5 
Millisekunden lediglich nur einen ISR Durchlauf haben, unabhängig davon, 
wie stark das Signal gestört ist.

von Oliver S. (oliverso)


Lesenswert?

Stichwort "entprellen".
Oder aber in der ISR den Interrupt für ein paar ms sperren, über einen 
zweiten Timer.

Oliver

von Markus (Gast)


Lesenswert?

In deinem Fall genügt es vielleicht schon, wenn du am Ende der ISR die 
Interrupt Flags löschst, indem du eine 1 an die Bitposition schreibst:
1
PORTC.INTFLAGS = INT0IF_bm;

Wenn die zweite dich störende Flanke während der ersten ISR auftritt, 
dann würdest du das Flag löschen und aus der ISR zurückkehren. Das Flag 
ist allerdings gelöscht, also wird die ISR nicht nochmal aufgerufen.

Wenn die Interrupts zu schnell nacheinander getriggert werden, aber 
nicht innerhalb der ersten ISR, dann kann Olivers Vorschlag helfen: In 
der Ext. Interrupt ISR startest du einen Timer und deaktivierst du die 
Ext. Int. ISR. (INT0MASK löschen). In der Timer ISR, deaktivierst du den 
Timer und aktivierst die Ext. Int. ISR.

von Volker B. (Firma: L-E-A) (vobs)


Lesenswert?

Klarst schrieb:

> Die zweite Flanke soll nicht ausgewertet werden.
> Das Signal am Pin0 wiederholt sich alle 5 Millisekunden und ich möchte
> stets nur auf die erste Flanke reagieren.

Wenn die Signale stets paarweise auftreten, würde ich einfach ein 
D-Flipflop vorschalten. Beim ersten Einschalten ggf. das Signal pollen 
und den Reset des FFs erst freigeben, wenn der kurze Puls erkannt wurde.

Grüßle
Volker

Nachtrag: Oder arbeite mit zwei Interrupts, also das Signal an zwei Pins 
führen, die jeweils einen Interrupt auslösen. Der Handler des ersten 
sperrt seinen eigenen Interrupt und gibt den zweiten fei. Dieser machts 
dann genau andersherum und sperrt sich, gibt aber den ersten wieder 
frei. Vor der Freigabe die jeweiligen Flags löschen.

Die unterschiedlichen Pulse können recht elegant durch einen Timer im 
Pulse-Width-Capture-Modus unterschieden werden. Die Pulsweite steht dann 
direkt im zugh. Capture-Register.

von klarst (Gast)


Lesenswert?

Markus schrieb:
> In deinem Fall genügt es vielleicht schon, wenn du am Ende der ISR die
> Interrupt Flags löschst, indem du eine 1 an die Bitposition schreibst:
> PORTC.INTFLAGS = INT0IF_bm;

Dies hat scheinbar wunderbar funktioniert.
Danke an alle.

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.