Forum: Mikrocontroller und Digitale Elektronik ext. Interrupt


von Magic M. (magicjon)


Angehängte Dateien:

Lesenswert?

Hi Leute,

ich habe ein kleines Problem mit den externen Interrupts.

Hardware:
uC: ATmega8@1MHz

Quellcode: im Anhang

Es geht dabei um folgendes:
An den Eingängen INT0 und INT1 des Atmegas liegt momentan dasselbe 
Signal. Dabei handelt es sich um ein Rechtecksignal mit einer 
Periodenlänge von ca. 4s mit einem Verhältnis von 50/50.

Der Atmega soll nun, sobald das Signal anliegt, zunächst auf eine 
steigende Flanke reagieren. Sobald ein Interrupt ausgelöst wird, startet 
Timer0 (ext. Interrupt0=INT0) und Timer2 (ext. Interrupt1=INT1). Beide 
Timer laufen mit einer Frequenz von ca. 977Hz (1MHz/1024). Ebenfalls 
wird in der ISR die Reaktion auf steigende und fallende Flanke der ext. 
Interrupts umgestellt.
Beide Timer lösen bei einem Overflow ebenfalls eine ISR aus. In ihr 
sollten die Ports PC0 und PC2, bedingt durch ihren derzeitigen Zustand, 
ein- bzw. ausgeschaltet werden.
Jetzt zu meinem Problem:
Eigentlich sollten die beiden Ports PC0 und PC2 nach meinem Verständnis 
beide zur etwa gleichen Zeit ein und ausgeschaltet werden.
Sprich also: Bei der ersten steigenden Flanke sollten PC0 und PC2 nach 
256/977Hz=0,26s eingeschaltet werden und nach der fallenden Flanke um 
ca. 0,26s verspätet ausgeschaltet werden. Und das ganze halt 
fortlaufend.
Leider passiert genau das nicht. Sie schalten nämlich beide im Wechsel. 
Sprich, bei der ersten steigenden Flanke schaltet PC0 verspätet ein und 
schaltet auch erst wieder nach der nächsten steigenden Flanke+0,26s aus. 
In diesem Moment schaltet dann PC2 ein und das ganze dann im Wechsel.

Kann mir da jemand weiter helfen, warum das so ist bzw. wie ich dieses 
Problem behebe? (Hoffe, ich konnte mich deutlich ausdrücken bzw. das 
Programm erklärt fragen)

Danke

von Magic M. (magicjon)


Lesenswert?

ok, wie ich gerade selber feststellen musste, klappt irgendwie das 
umschalten im Register MCUCR in der ISR nicht. Sprich also, die 
erkennung von "nur steigende flanke" auf "steigende und fallende flanke" 
in der ISR geht so nicht.

Stellt sich nur die frage, warum nich? jemand eine idee?

von Sascha W. (sascha-w)


Lesenswert?

ja - weil dum mit
>MCUCR = ((0<<ISC01) | (1<<ISC00))
die die anderen Bits löschst, und damit auf LOW-LEVEL Trigger 
umschaltest!

Sascha

von Peter (Gast)


Lesenswert?

Magic Magicjon schrieb:
> Stellt sich nur die frage, warum nich? jemand eine idee?

nö, glaube ich auch nicht weil es dem atmel ziemlich egal ist ob er in 
einer ISR ist oder nicht,
Man kann es nicht mal sicher rausfinden ob man in einer ISR ist oder 
nicht. Es wird also vermutlich nicht daran liegen.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Beim Umschalten kann evtl ein IRQ-Flag gesett werden, so daß direkt nach 
der ISR eine "Schein-IRQ" getriggert wird. Also entsprechende Flags nach 
Umsetzen von MCUCR löschen.

Bits in MCUCR (und anderen SFRs) löscht man nicht durch
  ... |= (0 << XXX)

von Magic M. (magicjon)


Lesenswert?

Sascha Weber schrieb:
> ja - weil dum mit
>>MCUCR = ((0<<ISC01) | (1<<ISC00))
> die die anderen Bits löschst, und damit auf LOW-LEVEL Trigger
> umschaltest!
>
> Sascha

ja, genau das habe ich gerade auch gemerkt ^^

so sollte es ja gehen oder ?


Für INT0:
MCUCR &= ((0<<ISC01) | (1<<ISC00) | (1<<ISC11) | (1<<ISC10));

Für INT1:
MCUCR &= ((1<<ISC01) | (1<<ISC00) | (0<<ISC11) | (1<<ISC10));

von Magic M. (magicjon)


Lesenswert?

Johann L. schrieb:
> Beim Umschalten kann evtl ein IRQ-Flag gesett werden, so daß direkt nach
> der ISR eine "Schein-IRQ" getriggert wird. Also entsprechende Flags nach
> Umsetzen von MCUCR löschen.
>
> Bits in MCUCR (und anderen SFRs) löscht man nicht durch
>   ... |= (0 << XXX)

nur war da kein Oder vor dem Gleichhaltszeichen

von Sascha W. (sascha-w)


Lesenswert?

nein -
du musst mit AND nur die zu löschenden Bits ausmaskieren, und mit OR die 
anderen wieder setzen.

Sascha

von Magic M. (magicjon)


Lesenswert?

Sascha Weber schrieb:
> nein -
> du musst mit AND nur die zu löschenden Bits ausmaskieren, und mit OR die
> anderen wieder setzen.
>
> Sascha

ok, also meinst du der schreibt das SFR, welches zuvor so aussah
MCUCR = ((1<<ISC01) | (1<<ISC00) | (1<<ISC11) | (1<<ISC10));

mit
MCUCR &= ((0<<ISC01) | (1<<ISC00) | (1<<ISC11) | (1<<ISC10));

um so das dort nachher folgendes drin steht ?
MCUCR = ((0<<ISC01) | (1<<ISC00) | (1<<ISC11) | (1<<ISC10));

von Magic M. (magicjon)


Lesenswert?

problem hat sich erstmal erledigt:-)

danke für eure hilfe

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.