Forum: Mikrocontroller und Digitale Elektronik serieller Interrupt Mega32


von Tobias (Gast)


Lesenswert?

Hallo
ich habe folgende Frage an euch: Ich habe einen Mikrocontroller (Mega32) 
der Hardware ansteuert (Aktoren, Sensoren etc.). Dieser bekommt vom PC 
über die serielle Schnittstelle Parameter zugeschickt. Der 
Mikrocontroller (in Assembler programmiert) löst bei Empfang eines 
Zeichens einen Interrupt aus. In dieser ISR werden Interrupts 
deaktiviert, der Parameter entgegen genommen, kurz verarbeitet und 
gespeichert, danach Interrupts wieder aktiviert und die ISR beendet um 
mit dem Hauptprogramm weiter zu machen.

So jetzt kommt die eigentliche Frage: Wenn jetzt in der Zeit der 
Abarbeitung der ISR weitere Parameter gekommen sind und im Puffer der 
serielle Schnittstelle hinterlegt wurden, löst der Mikrocontroller dann 
nach der ISR gleich einen weiteren Interrupt (weil er sieht das im 
Puffer Daten sind) aus oder muss ich in der ISR solange lesen bis der 
Puffer leer ist (weil das alleinige vorhanden sein von Daten im Puffer 
keinen Interrupt auslöst)?
Gibt es eine Möglichkeit zu verhindern, dass die ISR unterbrochen wird 
und trotzdem neue Interrupts angenommen werden können?
Vielen Dank im Vorraus

von Johannes M. (johnny-m)


Lesenswert?

Das RXC-Flag bleibt gesetzt, bis der Puffer komplett ausgelesen ist. 
Wenn also in einer ISR das UDR gelesen wird und in der Zwischenzeit ein 
neues Zeichen eintrifft, dann wird die ISR nach dem Rücksprung ins 
Hauptprogramm erneut aufgerufen.

Das Deaktivieren der Interrupt-Bearbeitung in der ISR geschieht übrigens 
automatisch durch die Hardware. Da braucht im Programm nichts geändert 
zu werden.

von Timmo H. (masterfx)


Lesenswert?

Ich würde dir empfehlen nen Fifo zu basteln. In der ISR werden einfach 
alle empfangenen Daten in den Fifo geschrieben. Bei jedem Zeichen wird 
eine globale Zählervariable inkrementiert. Außerhalb der ISR machst du 
quasi eine While-Schleife, die guckt ob noch Daten im Fifo sind. Solange 
dies der Fall ist werden die Parameter nacheinander abgearbeitet (und 
für jedes verarbeitete Zeichen auf dem Fifo die Zählervariable 
dekrementiert). Wenn du es so machst wird s wohl kaum passieren dass dir 
Daten verloren gehen.

von Joan P. (joan)


Lesenswert?

Ich dachte dafür ist das globale Interrupt Enable Bit vs. den einzelnen 
Interrupt Enable Bits da?

Wenn die einzlenen gesetzt sind, werden die Flags in den Flag-Registern 
gesetzt und nur wenn auch das globale I-Bit gesetzt ist, kommt es zur 
Ausführung des Int-Vektors.. deswegen ja auch SEI und CLI, am Ein- und 
Ausgang einer ISR..

Wenn ein Interrupt kommt -> CLI, dann werden alle weiteren Interrupts 
ihre Flags setzen, aber die aktuelle ISR nicht unterbrochen. Am Ende der 
ISR ein -> SEI und zurück.. dann können die in der Zwischenzeit 
eingetrudelten Interrupts anhand ihrer Flags und ihrer Priorität (siehe 
Interrupt Vektor Tabelle) abgearbeitet werden.

So mein Bild des Geschehens.. allerdings nutze ich nur C (dort wird 
standardmässig SEI und CLI erzeugt), deshalb könnte obiges auch falsch 
sein. Steht nix in dem AVR-Tutorial?
Aus den Datenblättern hab ichs bisher immer so verstanden..

Grüsse

von Johannes M. (johnny-m)


Lesenswert?

Joan P. wrote:
> Ich dachte dafür ist das globale Interrupt Enable Bit vs. den einzelnen
> Interrupt Enable Bits da?
Wofür?

> Wenn die einzlenen gesetzt sind, werden die Flags in den Flag-Registern
> gesetzt und nur wenn auch das globale I-Bit gesetzt ist, kommt es zur
> Ausführung des Int-Vektors.. deswegen ja auch SEI und CLI, am Ein- und
> Ausgang einer ISR..
Falsch. Die Flags werden immer gesetzt, wenn das dazugehörige 
Hardware-Ereignis auftritt (*). Durch die lokale und globale Freigabe 
wird lediglich die Interrupt-/Bearbeitung/ freigegeben. Wenn ein Flag 
gesetzt ist und die Interrupt-Bearbeitung wird freigegeben, dann wird 
sofort der dazugehörige Handler ausgeführt.

> Wenn ein Interrupt kommt -> CLI, dann werden alle weiteren Interrupts
> ihre Flags setzen, aber die aktuelle ISR nicht unterbrochen. Am Ende der
> ISR ein -> SEI und zurück.. dann können die in der Zwischenzeit
> eingetrudelten Interrupts anhand ihrer Flags und ihrer Priorität (siehe
> Interrupt Vektor Tabelle) abgearbeitet werden.
Noch mal: Das cli und sei macht die µC-Hardware automatisch!

> So mein Bild des Geschehens.. allerdings nutze ich nur C (dort wird
> standardmässig SEI und CLI erzeugt), deshalb könnte obiges auch falsch
> sein. Steht nix in dem AVR-Tutorial?
Nein, das hat nichts mit C zu tun! Auch wenn Du in Assembler 
programmierst, ist ein Interrupt-Handler ohne weitere Maßnahmen nicht 
unterbrechbar, weil die Hardware das I-Bit im SREG beim Einsprung in 
den Vektor löscht und bei einem entsprechenden Rücksprung wieder setzt!

(*) Wenn z.B. ein Timer überläuft, dann wird immer das betreffende 
Timer-Overflow-Flag gesetzt (sofern es noch nicht gesetzt war), auch 
wenn das dazugehörige "Timer Overflow Interrupt Enable"-Bit und/oder das 
I-Bit im SREG nicht gesetzt ist. Ansonsten wäre v.a. Polling von Flags 
nicht möglich, wenn andere Interrupts freigegeben sind.

von Karl H. (kbuchegg)


Lesenswert?

Joan P. wrote:
> Ich dachte dafür ist das globale Interrupt Enable Bit vs. den einzelnen
> Interrupt Enable Bits da?
>
> Wenn die einzlenen gesetzt sind, werden die Flags in den Flag-Registern
> gesetzt und nur wenn auch das globale I-Bit gesetzt ist, kommt es zur
> Ausführung des Int-Vektors.. deswegen ja auch SEI und CLI, am Ein- und
> Ausgang einer ISR..
>
> Wenn ein Interrupt kommt -> CLI, dann werden alle weiteren Interrupts
> ihre Flags setzen, aber die aktuelle ISR nicht unterbrochen. Am Ende der
> ISR ein -> SEI und zurück.. dann können die in der Zwischenzeit
> eingetrudelten Interrupts anhand ihrer Flags und ihrer Priorität (siehe
> Interrupt Vektor Tabelle) abgearbeitet werden.

Noch mal.
Genau das macht die Hardware schon ganz von alleine.
Am besten ist es wenn man sich da komplett raus hält, sonst
kann es dir nämlich passieren, dass noch bevor eine ISR fertig
ist, die nächste ISR schon angesprungen wird, weil du die
Interrupts global ein klein wenig zu früh freigibst.

Sobald eine ISR aufgerufen wird, wird von der Hardware völlig
von alleine das globale Interrupt Flag gelöscht und sobald der
zugehörige RETI (Return from Interrupt) kommt, schaltet die Hardware
ganz von alleine die Interrupts wieder frei.

von Tobias (Gast)


Lesenswert?

Vielen Dank für die Antwort man lernt immer etwas dazu. Dachte immer man 
muss die sei und cli selber setzten aber so kann man sich täuschen werde 
dass bei Gelegenheit mal ausprobieren. Danke

von Joan P. (joan)


Lesenswert?

Danke für die Aufklärung!!^^ :-)

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.