Forum: Compiler & IDEs Problem mit Interrupt


von Ro B. (robret)


Lesenswert?

Hallo,
ich bin dabei kein Programm für einen Atmega32 auf einem RNControl 
Testboard zu schreiben.
Ich habe eine Funktion Sendchar über das USART Interrupt, daraus 
abgeleitet eine Send_String Funktion, beide funktionieren.

Der 16 Bit Timer ist auch initialisiert, und steuert im Millisekunden 
Takt die Problembehaftete ISR an. In dieser möchte ich im Sektunden Takt 
einen Messwert übertragen(dem einsprechend inkrementiere ich eine 
Laufvariable usw.).Der Messwert ist ein Zählerstand eines Impulszählers. 
Dieser ergibt sich durch ein Signal am PORTB,durch den INT2_vektor 
ebenfalls über eine ISR wird der Messwert erhöht. Beim wenn ich nun in 
der ISR, die durch den Timer ausgelöst wird den Messwert Senden will 
gehen während des Sendens Impulse verloren.
Beispielsweise Sendet er mit bei einem 4kHz Signal nur 3996 als 
Zählerstand. Lasse ich jedoch das senden weg, und lasse mir statt dessen 
den Zählerstand an den LEDs des PORTC ausgeben, so stimmt er. 
Komischerweise Stimmt auch er erste übertragene Wert nach einem Reset.


Kann mir jemand weiterhelfen?

von Mark .. (mork)


Lesenswert?

Ro Bret schrieb:
> wenn ich nun in
> der ISR, die durch den Timer ausgelöst wird den Messwert Senden will
> gehen während des Sendens Impulse verloren.


In einer ISR sind Interrupts im Normalfall ausgeschaltet, weshalb 
während des Sendens keine Impulse gezählt werden können, da dies ja 
ebenfallt über einen Interrupt (INT2) geschiet.

Mögliche Lösungen wären dass man vor dem Senden die Interrupts wieder 
freigibt (unsauber), die Senderoutine so umbaut, dass diese die zu 
sendenden Bytes in ein Buffer schreibt und sofort zurückkehrt (über den 
USART TXC Interrupt werden die Bytes im Buffer dann nacheinander 
gesendet), oder in der Timer-ISR wird lediglich ein Flag gesetzt, 
welches in der Hauptschleife gepollt wird und das Senden dann von dort 
aus (also mit aktivierten Interrupts) geschiet.

MfG Mark

von Ro B. (robret)


Lesenswert?

Vielen Dank erstmal für die Schnelle Antwort,

aber laut Datenblatt haben Externe Interrupts eine höhere Priorität als 
der Sende Interrupt, wieso ist es in diesem Fall scheinbar nicht so? Ich 
bin ja wenn ich mir den MW nur auf den LEDs anzeigen lasse auch in der 
Timer ISR, und der INT2 ISR funktioniert.

Gibt es beim ATMega eigentlich die Möglichkeit reine Software 
"Interrupts" also Threads oder Events zu initialisieren?

von Grrrr (Gast)


Lesenswert?

Leider kein Quellcode. (Siehe Netiquette 
http://www.mikrocontroller.net/articles/Netiquette)

Aber Deine Formulierung:

Ro Bret schrieb:
> wenn ich nun in
> der ISR, die durch den Timer ausgelöst wird den Messwert Senden will

lässt vermuten, das Du in der der ISR des Timers tatsächliche die 
UART-Sendefunktionen aufrufst. Falls Du nicht nur ein Zeichen von 
innerhalb der ISR sendest, blockiert das natürlich unnötig die anderen 
Interrupts.
Ein bewährtes alternatives Entwurfsschema ist, in der Timer-ISR nur 
einfach den Zählerstand in einer Variablen zu speichern und evtl. ein 
Flag zu setzen. Das ist kurz genug, das höchstens ein weiterer INT2 
auftritt (hängt natürlich von der maximalen Frequenz ab, die Du messen 
willst).

Die weitere Möglichkeit wäre, garkeinen Interrupt für das Messen der 
Frequenz zu benutzen, sondern den externen Takteingang für Timer0 resp. 
1 zu verwenden. Dann hält der Sendeinterrupt die Zählung überhaupt nicht 
auf.
Trotzdem sollte auch in diesem Fall (wie auch sonst nicht) das senden 
nicht in einer ISR erfolgen. Die einzige Ausnahme ist das senden eines 
einzelnen Zeichens aus den Interrupts, die ein leeres Senderegister 
anzeigen.

von Grrrr (Gast)


Lesenswert?

Ro Bret schrieb:
> aber laut Datenblatt haben Externe Interrupts eine höhere Priorität als
> der Sende Interrupt, wieso ist es in diesem Fall scheinbar nicht so?

Wie kommst Du darauf, das es in diesem Fall scheinbar nicht so ist?
Unter Interrupt Priorität werden verschiedene Dinge verstanden.
Beim AVR bezieht sich die Priorität lediglich auf die Reihenfolge der 
Ausführung von mehreren gleichzeitig anstehenden Interrupts. Nicht 
jedoch auf die in manchen uCs implementierte Fähigkeit die Priorität von 
laufender ISR gegen die neu auftretender ISR abzuwägen. Insbesondere 
kann beim AVR jede neuer Interrupt einen schon laufenden Interrupt 
unterbrechen (falls das globale Interrupt-Flag das erlaubt) egal ob 
der neue Interrupt eine höhere oder niedrigere "Priorität" als der 
laufende hat.

D.h.:
Die höhere Priorität kommt nicht zum tragen, solange die Interrupts 
gesperrt sind oder gerade eine ISR ausgeführt wird.
Die Interrupts werden bei auftreten eines Interrupts global gesperrt. 
Das bedeutet, das die anderen Interrupts, nicht sofort, sondern erst 
nach verlassen, der gerade laufenden ISR abgearbeitet werden. Dann aber 
kommt, und das ist der einzige relevante Fall, in dem die Priorität beim 
AVR überhaupt relevant ist, falls mehrere verschiedene Interrupts 
aufgetreten sind, diejenige ISR mit der höchsten Priorität zur 
Ausführung.

Lies mal den Artikel: http://www.mikrocontroller.net/articles/Interrupt 
und das Datenblatt.

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.