Forum: Mikrocontroller und Digitale Elektronik Interrupt-Vektoren


von TomTom (Gast)


Lesenswert?

Hallo,

ich beschäftige mich z.Z. intensiv mit einem Drehimpulsgeber den ich an
die beiden Interrupt Eingänge meines Atmega16 angeschlossen habe.

Habe programmiertechnisch soweit alle fertig, nur will es halt nicht so
laufen wie ich mir das vorstelle.

Irgendwie komme ich jetzt nicht so ganz klar mit den Ablauf eines
Interrupts.

Mein Programm ist nach dem folgende Schema aufgebaut:

1.Stack einrichten
2.PortD Eingang (Drehimpulsgeber)
3.PortC Ausgang (LC-Display)
4.Into & Int1 enablen
5.LCD INIT
6.LCD CLEAR

dann kommen die
Interrupt Vektoren
------------------
7.rjmp  reset2
  rjmp  Int0
  rjmp  Int1


reset2:
  Ausgangszustand Drehimpulsgeber ermitteln
        Interrupts erlauben (sei)

main:
        (HP)
        rjmp main


INTO:
       (Auswertung Drehrichtung)
INT1:
  (Auswertung Drehrichtung)

ENDE


Das Hauptpogramm funbktioniert ohne die Interruptroutine einwandfrei.
Nur wenn ich meine Routine einbau und ich den Drehgeber drehe. Flackert
das LCD und zeigt wirres zeug.

Frag ist : liegt es jetzt generell am Ablauf des kompletten Programms
mitsamt dem Interrupt ?



Wenn der Ablauf denn so stimmt muss es ja an der Routine selber liegen.

von Niels H. (monarch2)


Lesenswert?

Mein Auto steht in der Garage und springt nicht an. Liegt das jetzt am
nicht eingeschaltetem Licht oder an den Kaninchen, die meine Tochter im
Garten züchtet.


Man gebe mir eine Glaskugel, mal sehen, was sich machen lässt.

von Kai (Gast)


Lesenswert?

Versuch mal den Drehimpulsgeber nicht mit Interrupt auszuwerten. Frag
ihn einfach in nem Abstand von z.B. 1 ms ab...

Kann es vlt. auch sein, dass du die Interruptvektoren an der falschen
Adresse angegeben hast?

MFG

Kai

von Kai (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe gerade in meiner Datenblatt-Sammlung etwas über Drehimpulsgeber
gefunden.
Da kann man lesen(sehen): Entprellen!!!
Und zwei Flußdiagramme zur Abfrage mit µC. Einmal jede ms, das andere
mir Interrupt.

MFG

Kai

Auszug aus Datenblatt angehängt...

von Karl H. (kbuchegg)


Lesenswert?

Mein Programm ist nach dem folgende Schema aufgebaut:
>
> 1.Stack einrichten
> 2.PortD Eingang (Drehimpulsgeber)
> 3.PortC Ausgang (LC-Display)
> 4.Into & Int1 enablen
> 5.LCD INIT
> 6.LCD CLEAR
>
> dann kommen die
> Interrupt Vektoren
> ------------------
> 7.rjmp  reset2
>   rjmp  Int0
>   rjmp  Int1

Wie muss ich das jetzt interpretieren?
Du kannst die Interruptvektoren nicht einfach
dorthin schieben wo's Dir passt. Die muessen
ganz am Anfang stehen.
Datenblatt lesen.

von TomTom (Gast)


Lesenswert?

@alle: Danke für die Hilfe.....

@Karl Heinz

Danke, genau das wollte ich wissen.

Die müssen also ganz am Anfang stehen. Ich habe wohl an der falschen
stelle im Datenblatt geschaut ("External Int" anstatt "Interrupts"
Kapitel schäm)....
Ich habe es aber jetzt gefunden. DAnke


Trotzdem noch ne Frage:

Was passiert nachdem der Interrupt Vektor nach einem INT durchlaufen
ist ?
fängst dann wieder bei Reset an oder da wo ursprügnlich die
Unterbrechung war ?
Ich hab natürlich mit Push und Pop das SREG und andere Register
gesichert.

von Kai (Gast)


Lesenswert?

Am Ende deiner Interruptroutine muss ein RETI stehen. Damit springt der
Controller wieder an die Stelle im Programm zurück, an welcher er in
den Interrupt gesprungen ist. Beispiel:

rjmp   reset2
rjmp   Int0
rjmp   Int1

... weiterer Code ...

Int0:               ; Start der Interrupt Routine
     push    SREG   ; Register sichern
     push    XYZ

     ... viel Code für Interrupt ...

     pop     XYZ    ; Register wieder herstellen
     pop     SREG

     reti           ; Interrupt verlassen und weiter um Hautprogramm

MFG

Kai

von Karl H. (kbuchegg)


Lesenswert?

Nein.
Ein Interrupt ist wie ein normaler CALL (*), nur dass der
Unterprogrammaufruf eben nicht durch einen Assemblerbefehl
ausgeloest wird, sondern durch irgendein Ereignis. Daher
muessen die Vektoren auch auf definierten Stellen stehen.
Bei einem normalen CALL gibt man ja die Adresse an an die
gesprungen werden soll. Bei einem externen Pin, der ein
Spannungssignal kriegt, geht das aber nicht. (**)

(*) Im Prinzip. Im Detail gibt es natuerlich Unterschiede.
RETI statt RET verwenden. Waehrend ein Interrupt abgearbeitet
wird, sind andere Interrupts automatisch gesperrt. ...

(**) Zumindest nicht auf einem AVR. Auf anderen Prozessoren
geht das sehr wohl, dann braucht man aber eine zusaetzliche
Hardware: einen Interruptcontroller.

von Olaf_K (Gast)


Lesenswert?

Hallo,

noch eine kleine Falle: Die Interrupttabelle beim Mega16 besteht aus 2
Worten pro Eintrag, sollte also aus JMPs bestehen, nicht RJMPs. Das
wird so gemacht, da man bei AVRs mit mehr als 8K Flash sonst nicht den
ganzen Adreßraum anspringen könnte. Siehe Datenblatt.

MfG Oil

von TomTom (Gast)


Lesenswert?

Ok..danke

So noch mehr Newbie fragen .....

Den Befehl "sei", den kann ich doch hinsetzten wo ich möchte oder ?
Ich möchte nämlich erst zu einen bestimmten Zeitpunkt im Programm einen
Interrupt erlauben.

Im GICR habe ich zuvor die Ints enabled. Das ist doch korrekt oder ?

von Kai (Gast)


Lesenswert?

@Oli
Danke, ich denke da hat bisher auch noch keiner dran gedacht! Habs auch
erst gesehen, als ich deine Antwort gelesen hab.

von TomTom (Gast)


Lesenswert?

@Olaf


Aha...das ist ja mal interressant.
Das habe ich im Datneblatt nicht gesehen

von TomTom (Gast)


Angehängte Dateien:

Lesenswert?

Habe mal meine main.asm angehängt.

Könnt ihr euch ja mal anschaun.... ;)

von Kai (Gast)


Lesenswert?

Ich würde mal die von Olaf angesprochene Sache mit den
Interruptverktoren ändern. Sonst fällt mir auf den ersten Blick nichts
auf - habs nur kurz überflogen.

MFG

Kai

von Christoph Kessler (Gast)


Angehängte Dateien:

Lesenswert?

Meine Drehgeberroutine hab ich auch mal angehängt, ist vielleicht etwas
kompakter

von TomTom (Gast)


Angehängte Dateien:

Lesenswert?

Dankeschön, aber ich bekomm diesen Code auch nicht am laufen.

Ich verzweifel hier schon.

Ich möchte auf meinem Display einfach, zum testen, zwei Wert von 0-9
einstellen können.

Ich kann beim Druck auf die Achse zwischen den Werten hin und her
springen (Cursor springt, Cursor blinkt).
Sobald ich aber drehe funktioniert nix mehr.
Es soll doch einfach nur Decrement oder Increment ausgeführt werden,
den neuen Wert auf dem Display angezeigt werden und danach soll
entweder auf einen Interrupt oder auf den nächsten Tasterdruck gewartet
werden.

Kann es an den Fusebits liegen ? (BOOTRST)
Oder an IVSEL ?
Oder leigt es daran wann und wo ich mit dem Befehl "SEI" die
Interrupts erlaube ?

Ich habe mal den Quellcode angehangen....

Über ein paart Tipps freue ich mich sehr....

von Simon K. (simon) Benutzerseite


Lesenswert?

@Christoph Kessler: Was is dasn fürn Quatsch? Der Peter Danegger hat in
der Codesammlung einen C-Code liegen der wesentlich kürzer ist. Sollte
ohne Probleme auf ASM portierbar sein.

von Kai (Gast)


Lesenswert?

Hallo TomTom,

wie Olaf oben schon gesagt hat, solltest du die Sprungbefehle von rjmp
in jmp ändern (in der angehängten Datei noch nicht geschehen!).
Bei den Fusebits musst du nur darauf achten, dass deine Reset- und
Interruptvektoren nicht in den Bootbereich verschoben werden. BOOTRST
sollte unprogrammed sein (= 1) und IVSEL sollte = 0 sein. Siehe S.44
Tabelle 19 und S.45.

MFG

Kai

von TomTom (Gast)


Lesenswert?

Ohhhh man.......


Ich habe natürlich alle Rjmps geändert, ausser die Sprünge für die
Vektoren selber, ich depp.....

Jetzt gehts.......


SUPER

von Simon K. (simon) Benutzerseite


Lesenswert?

die jumps im code kannst du als rjmp lassen. aber die befehle für die
vektoren müssen jmps sein.

von TomTom (Gast)


Lesenswert?

Eine Frage habe ich noch :


Wie kann ich das Int Eingänge wieder ausschalten wenn ich keinen
Interrupt mehr zulassen möchte ?

von Kai (Gast)


Lesenswert?

Du kannst entweder alle Interrupts mit CLI ausschalten oder im GICR die
Bits 6 und 7 wieder auf 0 setzen. Wenn du nur die Int Eingänge
verwendest, würde ich den CLI Befehl verwenden.

MFG

Kai

von Hannes L. (hannes)


Lesenswert?

Da kaum ein sinnvolles Programm ohne Timer-Interrupt auskommt, ist es
wohl besser, die Enable-Flags in GICR zurückzusetzen.

...

von Kai (Gast)


Lesenswert?

@Hannes: Betonung auf NUR!

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.