Forum: Mikrocontroller und Digitale Elektronik Subroutine wird fälschicherweise ausgeführt


von S. Streibl (Gast)


Angehängte Dateien:

Lesenswert?

Hallo

bei meinem Programm wird die Subroutine SET_dac8532() immer mit
ausgeführt, wenn der Interrupt ausgelöst wird. Kann mir das jemand
erklären ?

Vielen Dank fürs lesen

S. Streibl

von Εrnst B. (ernst)


Lesenswert?

Mal die generierten Asm-Sources angeschaut, ob dort die
Interrupt-routine auch richtig mit einem return abgeschlossen wird?

/Ernst

von johnny.m (Gast)


Lesenswert?

Den Grund dafür an sich sehe ich jetzt auf Anhieb nicht, aber Du führst
in der ISR eine elend lange Funktion mit Wartezeiten aus. Das allein
kann schon zu undefinierbaren Fehlern führen. Wenn der Tip von Ernst
nicht helfen sollte, stell mal die ISR vor alle anderen Funktionen.

Das globale Interrupt disable bei Einsprung in die ISR passiert
übrigens automatisch und das Sichern des SREG macht der Compiler. Das
brauchst Du nicht extra zu programmieren.

Gruß

Johnny

von S. Streibl (Gast)


Lesenswert?

Hallo Ernst,

so wie es aussieht wird die Interruptroutine mit  RJUMP abgeschlossen.

 OUT     0x0D,R1
 SEI                      Global Interrupt Enable
 RJMP    PC-0x0000        Relative jump

Ist RJMP mit RCALL identisch ? Sollte jedenfalls funktionieren, so wie
es AVRStudio anzeigt

@ Johnny :

heisst das, ich kann in der ISR cli() weglassen? Aber doch nicht sei()
?
Die ISR kann ich nicht umstellen, da das alles sehr verschachtelt ist.
Vielleicht sollte ich die gesamte Struktur ändern und die ISR so kurz
wie nur möglich halten.

Gruß

Basti

von S. Streibl (Gast)


Lesenswert?

Nachtrag :

in der Simulation siehts dann so aus als wär die RJMP Zeile die
while(1)-Schleife von main(). Das würde bedeuten, dass die ISR nicht
mit RET oder RCALL beendet wird.
Wie kann ich das im C-Code beheben ?

Grüße

Basti

von S. Streibl (Gast)


Lesenswert?

und noch ein Nachtrag :
in der Simulation wird das Unterprogramm nicht ausgeführt.
Das ist mal wieder sehr praktisch ...
Falls ihr noch Tipps habt, raus damit.

Grüße

Basti

von johnny.m (Gast)


Lesenswert?

Hallo Basti

Ich weiß nicht, wie es bei Dir mit Assembler-Kenntnissen aussieht (nach
dem was oben steht, nicht besonders:-), deshalb versuche ich mal, es
ohne zuviel davon zu beschreiben. Hilfreich zum Verständnis ist, sich
mal nach dem Compilieren die List-Datei anzusehen. Da kann man sehr
schön sehen, was der Compiler aus dem C-Code gemacht hat.

Wenn ein Interrupt auftritt und der Controller über die
Interrupt-Vektortabelle in die ISR springt, wird hardwaremäßig
automatisch das I-Bit (globales Interrupt-Enable) im Register SREG
gelöscht. Ist die ISR beendet (in Assembler mit dem Befehl reti [return
from interrupt]) wird dieses Bit ebenfalls automatisch durch die
µC-Hardware wieder gesetzt. Möchte man, dass eine ISR durch einen
anderen Interrupt unterbrochen werden kann, dann kann man durch
manuelles Setzen des I-Bits in der ISR dafür sorgen, was aber meist mit
größter Vorsicht zu genießen ist!

Wenn man sich den Assembler-Code der ISR anschaut, sieht man am Anfang
jede Menge push-Befehle. Diese 'retten' alle wichtigen Register auf
den Stack. Irgendwo steht da dann auch push 0x3F, das ist das SREG. Am
Ende der ISR (vor dem reti) werden die ganzen Daten mit pop-Befehlen
wieder vom Stack geholt. Diesen Code erzeugt der Compiler selbst. Da
brauchst Du Dich als C-Programmierer nicht drum zu kümmern!

Generell sollte man den Inhalt einer ISR wirklich auf das allernötigste
beschränken. Da Du in Deiner Hauptprogramm-Endlos-while-Schleife sowieso
nix machst außer warten, solltest Du in der ISR lediglich ein Flag
setzen (Das kann ein beliebiges Bit in irgendeiner globalen Variablen
sein oder auch eine komplette Variable) und dieses Flag im
Hauptprogramm abfragen. Man sollte in einer ISR auch nach möglichkeit
keine Funktionsaufrufe unterbringen. Das kann zu Ärger führen. Auch die
Erzeugung von Wartezeiten mit Zählschleifen ist sehr fragwürdig. Warum
benutzt Du keine Bibliotheksfunktionen (delay)?

Ich weiß natürlich nicht, ob Du das Programm noch erweitern möchtest,
aber wenn Du es tun solltest, dann solltest Du es auf jeden Fall ein
wenig 'umbauen'.

Gruß

Johnny

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.