Subroutine wird fälschicherweise ausgeführt

Gast #316330
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
Gast #316331
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
Gast #316332
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
Gast #316334
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

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.