Interrupt-Vektoren

Gast #273584
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.
Gast #273586
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
Gast #273587
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...
Angehängte Dateien:
#273588
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.
Gast #273589
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.
Gast #273590
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
#273591
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.
Gast #273592
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
Gast #273593
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 ?
Gast #273599
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....
Angehängte Dateien:
Gast #273601
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren