www.mikrocontroller.net

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


Autor: S. Streibl (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Εrnst B✶ (ernst)
Datum:

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

/Ernst

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: S. Streibl (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: S. Streibl (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: S. Streibl (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
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.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.