Forum: Mikrocontroller und Digitale Elektronik atmega 168 INT0 löst keinen Interrupt aus! Assembler!


von Patt :. (patt)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe ein Problem mit einem Atmega 168. Es wird die ISR vom INT0 
nicht ausgeführt.
Zu dem Program. Das Program soll über ISR auf 2 Sachen reagieren.
1.An der RS232 Zeichen empfangen und reagieren --> funktioniert
2.An INT0 PD2 Pin4 vom Mega auf eine Flanke reagieren die im 
Sekundentakt
     anliegt. Das funktioniert nicht!!!!!
Das ganze Program soll bzw ist ein Temperaturlogger mit Echtzeituhr.
Dieses läuft schon auf einen Atmega8. Aber wegen des Platzmangels 
(8kByte)
hab ich das Program jetzt auf einen Atmega168 umgeschrieben. Alle
anderen Funktionen ( twi, Pin´s schalten/lesen ) funktionieren.
Am INT0 liegt der Takt von der Echtzeituhr. Bei einer Flanke soll dann
das Datum und Uhrzeit ausgelesen werden und mit der eingelesenen 
Temperatur
vom LM75 im EEprom 24C32 abgespeichert werden. Über die RS232 wird dann 
mit bestimmten Zeichen/Befehlen das EEprom ( Uhrzeit mit Temp-Werten ) 
ausgelesen und an der RS232 ausgegeben zur weiteren Verarbeitung.
Das war es im groben. Das Program im Anhang wurde von mir stark gekürzt,
damit es übersichtlicher wird ( Aufruf von Funktionen / Auswertung 
RS232,...)
Also bitte nicht an bestimmten Aufrufen stören lassen.


Ja mein Programmierstil lässt sehr zu wünschen übrig.
Wäre aber trotzdem sehr dankbar wenn mir einer den Fehler zeigt bzw
auch andere Tips gibt!!!

Hab die Funktion die den Interrupt für den INT0 einstellt vergessen:
sek_int_ein:
  push  temp

    ldi  temp,0b00000010  ; falling edge of INT0 generates ; 
an interrupt request
    sts  EICRA,temp

;    ldi  temp,0b00000001  ; External interrupt request 0 ; 
enable
    ldi  temp,0b00000001
                          ;external interrupt request 0 enable
    sts  EIMSK,temp

  pop    temp
ret

Gruß patt

von Vuvuzelatus (Gast)


Lesenswert?

>    ldi  temp,0b00000010  ; falling edge of INT0 generates
>                          ; an interrupt request
>    sts  EICRA,temp

Schätzfrage: Wieviele Leute werden wohl Lust darauf haben, das 
Datenblatt hervorzuholen, um darin das richtige Kapitel zu suchen, um 
dort nachzuschauen zu können, ob 0b00000010 jetzt die richtigen Bits 
einschaltet oder nicht?

>bzw auch andere Tips gibt!!!

Gerne, hier Deiner erster: Benutze Bitnamen. Dazu sind sie da.
1
  ; falling edge of INT0 generates an interrupt request
2
  ldi  temp, 0<<ISC11 | 0<<ISC10 | 0<<ISC01 | 1<<ISC00
3
  sts  EICRA, temp

von Karl H. (kbuchegg)


Lesenswert?

Zahlenfetischist?
1
;.org INT0addr
2
;    rjmp  int_int0            ; Interruptvektor für Int0== $002    ; External Interrupt Request 0
3
4
.org 0x0002  jmp  int_int0
5
6
;.org URXCaddr                                   ; Interruptvektor für UART-Empfang 
7
;      rjmp int_rxc
8
9
.org 0x0024  jmp  int_rxc

Was ist falsch an
.org INT0addr

richtig. Gar nix. Ich such mir jetzt nicht das Datenblatt raus um 
nachzusehen, ob der Interrupt tatsächlich an 0x0002 liegt. Wenn du 
INT0addr benutzen würdest, und diese Konstante vom Assembler als 'jawohl 
existiert' bestätigt wird, brauch ich nix nachsehen. Der INterrupt 
Vektor liegt dann genau dort wo er hingehört

Auch
1
int_rxc:
2
3
  cli                    ; alle Interrupts sperren
4
5
6
    ....
7
8
  sei                    ; alle Interrupts wieder freigeben
9
10
reti

Wozu soll das gut sein? Interrupts sind sowieso in einer ISR gesperrt. 
Daher gibt es ja auch einen reti, der im Grunde nix anderes ist, als ein 
ret mit einem nachfolgenden sei.

Ganz im Gegenteil: indem du selbst in der ISR noch einen cli, ganz 
speziell aber einen sei machst, kannst du dir Fehler einhandeln. Die 
Interrupts werden dann ein kleines bischen zu früh freigegeben und wenn 
du Pech hast und die Interrupts nur häufig genug kommen, dann schachteln 
sich die ISR Aufrufe auf dem Stack ineinenader, bis der Stack übergeht.


Aber:
Ich vermisse zb, wo du den Interrupt Pin auf Eingang einstellst?

von patt (Gast)


Lesenswert?

Hallo,


erstmal Danke für eure Tips. So wie ich das verstehe, steht eigentlich
kein Fehler in dem Teil. --> Ich muß was übersehen bzw was vergessen 
haben.
Werd vielleicht mal ein kleines Prog machen, was NUR auf den INT0 
reagiert
und dort versuchen den INT zum laufen zu bewegen.

;    rjmp  int_int0            ; Interruptvektor für Int0== $002    ; 
External Interrupt Request 0

.org 0x0002  jmp  int_int0

;.org URXCaddr                                   ; Interruptvektor für 
UART-Empfang
;      rjmp int_rxc

.org 0x0024  jmp  int_rxc

Ich habe die Namen int_int0 nur durch HEX-Werte ersetzt damit ich sehen
kann ob dort der Fehler liegt. War nur als Test gedacht.

Das mit dem cli und dem sei in der SEI hab ich mal von jemandem 
abgeschrieben
und bis jetzt einfach per copy and paste wiederverwendet. Muß aber auch 
gestehen, dass ich mir dazu keine großartigen Gedanken gemacht habe :-(
Leuchtet aber ein und wie!!!!!!! --> wird geändert.

--> Aber:
Ich vermisse zb, wo du den Interrupt Pin auf Eingang einstellst?
tja da sagt jemand was. Das muß ich kontrollieren, ABER ich habe den Pin 
nicht auf Ausgang geschalten und das Signal liegt ja am PIN an. --> 
sollte richtig stehen, werd ich aber kontrollieren.

Hat jemand ein kurzes Bsp-Programm in Assembler was den INT0 mit ISR 
bearbeitet??? Oder jemand noch eine Idee was falsch sein könnte.

Danke für eure Hilfe/Antworten.

Gruß patt

von Vuvuzelatus (Gast)


Lesenswert?

Der Fehler liegt in den Zeilen

> sts  EIMSK, temp
> sts  EICRA, temp

Damit beschreibst Du falsche Registeradressen.

Richtig wäre:
1
out  EIMSK, temp

oder
1
sts  EIMSK+0x20, temp

und für "sts EICRA, temp" analog.

Lies die Erläuterungen dazu im Datenblatt, Kapitel I/O-Memory.

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Vuvuzelatus schrieb:
> und für "sts EICRA, temp" analog.

Falsch. EICRA liegt bei Adresse 0x69 und muss deshalb mit lds/sts 
angesprochen werden.

von spess53 (Gast)


Angehängte Dateien:

Lesenswert?

Hi

>Hat jemand ein kurzes Bsp-Programm in Assembler was den INT0 mit ISR
>bearbeitet??? Oder jemand noch eine Idee was falsch sein könnte.

Anhang sollte funktionieren.

MfG Spess

von patt (Gast)


Lesenswert?

Hallo,

Danke, das Bsp werd ich späte bzw am WE gleich mal testen.
Was mir beim anschauen als erstes aufgefallen ist.
Du beschreibst das Register EIFR-->

ldi r16,$00                   ;INTF1,INTF0
out EIFR,r16

War eigentlich der Meinung, dass man das EIFR external Interrupt flag 
register für den Interrupt bei INT0 bzw INT1 nicht benötigt bzw das
nur ein Register ist in dem man nachschauen kann ob ein Interrupt 
aufgetreten
ist. Das werd ich aber sicher testen.

Danke.


Gruß patt

von spess53 (Gast)


Lesenswert?

Hi

>War eigentlich der Meinung, dass man das EIFR external Interrupt flag
>register für den Interrupt bei INT0 bzw INT1 nicht benötigt bzw das
>nur ein Register ist in dem man nachschauen kann ob ein Interrupt
>aufgetreten
>ist.

Mach dir keine Gedanken. Ich habe mir mal ein Programm geschrieben das 
mir diesen Code (IR-Tabellen, Initialisierung ...) generiert. Die beiden 
Zeilen habe ich nur vergessen zu löschen.

MfG Spess

von Vuvuzelatus (Gast)


Lesenswert?

>EICRA liegt bei Adresse 0x69 und muss deshalb mit lds/sts angesprochen werden.

Ja, stimmt. Mein Fehler, sorry! "sts EICRA, temp" ist korrekt. Man kommt 
ja ganz durcheinander...

Diese beiden Varianten sind richtig:
1
ldi  temp, ...
2
out  EIMSK, temp  ; "out"!
3
4
ldi  temp, ...
5
sts  EICRA, temp

oder
1
ldi  temp, ...
2
sts  EIMSK+0x20, temp  ; "+0x20"!
3
4
ldi  temp, ...
5
sts  EICRA, temp

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Vuvuzelatus schrieb:
> Man kommt
> ja ganz durcheinander...

Geht mir auch immer so... ;-) Das Datenblatt beseitigt dann die letzten 
Zweifel.

von spess53 (Gast)


Lesenswert?

Hi

>Geht mir auch immer so... ;-) Das Datenblatt beseitigt dann die letzten
>Zweifel.

Einfach erst mal mit in/out probieren. Wenn es nicht geht, meckert der 
Assembler. Umgedreht allerdings nicht.

MfG Spess

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Ja, auch immer wieder gerne genommen ;-)

von Patt :. (patt)


Lesenswert?

Hallo,

Danke, das wars!!!!
Ich hab beim umbschreiben des Code vom Atmega8 zum 168 "jedes" out und 
in
in ein sts und lds umgeschrieben. Das Register EIMSK liegt im unteren 
Speicherraum --> Verwendung von out statt sts. War irgendwie der 
Meinung,
dass er Fehler bringt wenn ich was "falsch" verwende, wie er es eben 
auch
mit out macht wenn man sts verwenden muß. Naja, das ganze fällt unter
Erfahrungswerte.

Danke für Eure Hilfe und Tips!!!!
Jetzt freu ich mich über MEHR Speicher und ein paar schöne Features.


Gruß patt

von spess53 (Gast)


Lesenswert?

Hi

> War irgendwie der Meinung,
>dass er Fehler bringt wenn ich was "falsch" verwende, wie er es eben
>auch mit out macht wenn man sts verwenden muß

Nein, warum auch. EIMSK ist in der m168def.inc definiert mit:

.equ  EIMSK  = 0x1d

Beim Assemblieren wird nur überprüft, ob die einem Befehl übergebenen 
Argumente im zulässigen Bereich liegen. Und $1D ist für 'sts' zulässig.

MfG Spess

von patt (Gast)


Lesenswert?

Hallo,
da macht das programmieren gleich wieder mehr Spaß.
8kByte mehr Platz ;-)

Danke!

Gruß patt

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.