Forum: Mikrocontroller und Digitale Elektronik avr asm: interrupt int0 löst bei fallender flanke nicht aus


von ckrex (Gast)


Lesenswert?

Hallo an alle,

seit einigen Stunden versuche ich schon den interrupt für int0 und int1 
am atmega16 zu aktivieren. Im Forum, im wiki und im restlichen Internet 
habe ich bereits gesucht, jedoch brachten mich die Informationen auch 
nicht weiter. Wenn ich mir meinen Code anschaue kann ich auch keinen 
Fehler finden. Ich bin noch Anfänger in Sachen Assembler.
1
.include "m16def.inc"    ;Definitionen für den ATMega16 einbinden 
2
.org 0x0000        ;Die Interruptvektortabelle beginnt bei 0x0000 
3
4
5
rjmp RESET        ;1 POWER ON RESET 
6
rjmp INT0_HANDLER    ;2 Int0-Interrupt 
7
rjmp INT1_HANDLER    ;3 Int1-Interrupt 
8
reti          ;4 
9
reti          ;5 
10
reti          ;6 
11
reti          ;7 
12
reti          ;8 
13
reti          ;9 
14
reti          ;10 
15
reti          ;11 
16
reti          ;12 
17
reti          ;13 
18
reti          ;14 
19
reti          ;15 
20
reti          ;16 
21
reti          ;17 
22
reti          ;18 
23
reti          ;19 
24
reti          ;20
25
reti          ;21
26
27
RESET:            ;RESET Label 
28
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
29
  ldi r16, high(RAMEND)  ;Initialisierung des Stackpointers 
30
  out SPH, r16      ;erst das High - Byte 
31
  ldi r16, low(RAMEND) 
32
  out SPL, r16      ;dann das Low - Byte
33
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
34
35
36
37
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
38
39
  in R16,MCUCSR         ; Read MCUCSR
40
  ori      R16,1 << JTD        ; Set jtag disable flag
41
  out      MCUCSR, R16         ; Write MCUCSR
42
  out      MCUCSR, R16         ; and again as per datasheet 
43
44
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
45
46
47
  ldi r16, 0xFF      ;PORTC als Ausgang konfigurieren 
48
  out DDRC, r16
49
50
  ldi r16, 0x00      ;PORTD als Eingang konfigurieren 
51
  out DDRD, r16 
52
  ldi r16, 0xFF      ;Pull-up Widerstände für PORTD 
53
  out PORTD, r16      ;einschalten 
54
  ldi r16, 0b00001010    ;INT0 und INT1 einstellen für fallenden flanke
55
  out MCUCR, r16      ;FALLENDE Flanke löst den Interrupt aus  
56
  ldi r16, (1<<INT0) | (1<<INT1) ; hier nur int0 und int1 aktivieren
57
  out GICR, r16      ; hier freigabe für int0 und int1
58
59
60
              ; in der m16def.inc in Zeile 219 -220 findet man folgendes:
61
              ;.equ  INT0  = 6  ; External Interrupt Request 0 Enable
62
              ;.equ  INT1  = 7  ; External Interrupt Request 1 Enable
63
  
64
65
66
  sei            ; globale Interruptfreigabe
67
68
69
70
71
  ;;;;;;;;;;;;;;;;;;;;;;;;; test
72
  ;ldi r19, 0b11111111 
73
  ;out PORTC, r19 
74
75
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
76
77
WDH: 
78
  rjmp WDH        ;Hauptprogrammschleife macht nichts 
79
80
INT0_HANDLER: ;macht die led an
81
  push r16        ;Inhalt von r16 retten 
82
  in  r16, SREG      ;Inhalt des Statusregisters retten 
83
  push r16 
84
  ldi r16, 0b11111111 
85
  out PORTC, r16 
86
  pop r16          ;Statusregister wieder herstellen 
87
  out SREG, r16 
88
  pop r16          ;r16 wieder herstellen 
89
  reti          ;Rückkehr von der ISR 
90
91
INT1_HANDLER: ;macht die led aus
92
  push r16        ;Inhalt von r16 retten 
93
  in  r16, SREG      ;Inhalt des Statusregisters retten 
94
  push r16 
95
  ldi r16, 0b00000000 
96
  out PORTC, r16 
97
  pop r16          ;Statusregister wieder herstellen 
98
  out SREG, r16 
99
  pop r16          ;r16 wieder herstellen 
100
  reti          ;Rückkehr von der ISR


Wenn ich nun den pin 16 (int0) am µC auf Masse ziehe, dann sollte nach 
meinem Wissen der INT0-INTERRUPT ausgeführt werden. Die an portC 
angeschlossene LED bleibt jedoch aus. Was mache ich falsch?

Gruß
ckrex

von chris (Gast)


Lesenswert?

Hallo

erstmal dein Programm funktioniert nur nicht so wie du gedacht hast

1. du nutzt INT 0/1 diese liegen auf Portd und den hast du komplett als 
Ausgang geschaltet.
2. wenn die Ints auslösen, lösen beide auf fallende Flanke
3. und einer springt den falschen ISR_Handler an der nur ein reti ist

mal nachgeschaut auf welchen adressen die Handler liegen??

von LostInMusic (Gast)


Lesenswert?

rjmp RESET           ;1 POWER ON RESET
rjmp INT0_HANDLER    ;2 Int0-Interrupt
rjmp INT1_HANDLER    ;3 Int1-Interrupt

Diese drei "rjmp" durch "jmp" ersetzen.

von chris (Gast)


Lesenswert?

ich muss mich korrigieren zu Punkt 1. streiche erstatzlos das PD als 
ausgang geschlatet ist die sind gepullupt sry...

du musst bei der org Anweisung

weitermachen mit

.org 0x0000
rjmp    reset
.org 0x0002
rjmp    Int0_Handler
.org 0x0004
rjmp    Int1_Handler

denn gehts auch schau mal ins Datenblatt

rjmp ist -2kbyte zurück und +2kbyte vorwärts

jmp ist bis 4Mbyte Sprungweite

von chris (Gast)


Angehängte Dateien:

Lesenswert?

falls du wirklich in ASM schreiben willst empfiehl ich dir es ähnlich 
dem Anhang zu machen und zu includieren macht vieles einfacher...

von ckrex (Gast)


Lesenswert?

Danke für die schnellen Rückantworten!
Mein Fehler liegt wie chris schon geschrieben habe in der falschen 
addressierung der interruptvektortabelle. Ich hab wohl aus irgendeinem 
Grund geglaubt, dass diese so änlich wie die vom atmega8 adressiert 
wird.
Zitat von chris:

>rjmp ist -2kbyte zurück und +2kbyte vorwärts
>
>jmp ist bis 4Mbyte Sprungweite

Woher weiß man soetwas? Im Datenblatt zum atmega16 unter der Kategorie 
"Instruction Set Summary" kann ich keinen Hinweis dazu finden.

Was bedeutet eigentlich die Syntax: "PC <- PC + k + 1" (rjmp) die man 
ebenfalls im "Instruction Set Summary" unter der Kategorie "Operations" 
finden kann?


>falls du wirklich in ASM schreiben willst empfiehl ich dir es ähnlich
>dem Anhang zu machen und zu includieren macht vieles einfacher...

Danke. Ich muss in ASM schreiben weil das von der Schule so verlangt 
wird.
Außerdem ist es doch ganz cool wenn man es kann ;)

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

ckrex schrieb:
> Woher weiß man soetwas? Im Datenblatt zum atmega16 unter der Kategorie
> "Instruction Set Summary" kann ich keinen Hinweis dazu finden.

Auf Seite 45 im ATMega16 Datenblatt (meines ist 06/08), Kapitel 
Interrupts ist beispielhaft die komplette IRQ Vektortabelle aufgeführt 
und da stehen 'jmp'. rjmps wären auch nur 2 Bytes lang und die 
Vektortabelle des Mega16/32 reserviert 3 Bytes pro Vektor.

: Bearbeitet durch User
von sosole (Gast)


Lesenswert?

>Vektortabelle des Mega16/32 reserviert 3 Bytes pro Vektor.

soso

von oldmax (Gast)


Lesenswert?

Hi
>Danke. Ich muss in ASM schreiben weil das von der Schule so verlangt
>wird.
>Außerdem ist es doch ganz cool wenn man es kann ;)

Na, dann hilft dir vielleicht ein Beitrag in AVR-Praxis "keine Angst vor 
Assembler" etwas weiter. Findest du in der Rubrik FAQ. Viel Spaß.
gruß oldmax

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Matthias Sch. schrieb:
> rjmps wären auch nur 2 Bytes lang und die
> Vektortabelle des Mega16/32 reserviert 3 Bytes pro Vektor

Tja, wer zählen kann, ist bei Assembler klar im Vorteil. Sind auch nur 2 
Bytes. Trotzdem ist der Hinweis auf die Vektortabelle im Datenblatt 
deswegen nicht schlecht :-)

: Bearbeitet durch User
von chris (Gast)


Lesenswert?

ckrex schrieb:
> Zitat von chris:
>
>>rjmp ist -2kbyte zurück und +2kbyte vorwärts
>>
>>jmp ist bis 4Mbyte Sprungweite
>
> Woher weiß man soetwas? Im Datenblatt zum atmega16 unter der Kategorie
> "Instruction Set Summary" kann ich keinen Hinweis dazu finden.

im AVR4 Studio unter Help -> Assembler Help da kommen gleich die ganzen 
Befehle einfach mal ansehen

> Was bedeutet eigentlich die Syntax: "PC <- PC + k + 1" (rjmp) die man
> ebenfalls im "Instruction Set Summary" unter der Kategorie "Operations"
> finden kann?

PC = ProgrammCounter
k   = Konstante ist dein Label wo du hin willst

heißt es wird quasi in den ProgrammCounter geschrieben
so ähnlich wie
add      r16,r17 ; R16+R17 werden addiert und in R16 steht das Ergebniss

ckrex schrieb:
> Danke. Ich muss in ASM schreiben weil das von der Schule so verlangt
> wird.
> Außerdem ist es doch ganz cool wenn man es kann ;)

Es ist nicht nur cool wenn man es kann es bringt ne Menge 
Sytemverständis wie der µC tickt und persönlich kann ich sagen du hast 
maximale Kontrolle ohne Umwege.
Wenn du zu den Hochsprachen wechseln solltest ist es ein Vorteil wenn 
man sich damit auskennt.

von sosole (Gast)


Lesenswert?

>Tja, wer zählen kann, ist bei Assembler klar im Vorteil. Sind auch nur 2 Bytes.

soso

von LostInMusic (Gast)


Lesenswert?

> k = Konstante ist dein Label wo du hin willst

Nein, bei rjmp ist k die um 1 verminderte Differenz zwischen der 
Adresse des Sprungziels und der Adresse der rjmp-Instruktion. Das muss 
auch so sein, denn nur dann steht nach Ausführung von "PC <-- PC + k + 
1" durch die ALU im PC (program counter) der gewünschte Wert, nämlich 
die Sprungziel-Adresse. (Wenn Du Zweifel hast, schau es Dir im 
Disassembler an. Dabei beachten: Die Adressen liegen im Flash, der 
wortweise adressiert wird.)

Nur beim absoluten Springen mit jmp gibt k direkt die Zieladresse an.

>soso

Dem kann ich mich nur anschließen... :-/

von ckrex (Gast)


Lesenswert?

Hier ist übrigens noch eine Referenz für avr assembler
http://www.atmel.com/webdoc/avrassembler/index.html

von Peter D. (peda)


Lesenswert?

Man sollte immer die im betreffenden Include-File definierten 
Vektornamen verwenden.
Besonders einfach geht das mit folgendem Makro:
1
.include "m48def.inc"                   ;target
2
;--------------------------------------------------------------------------------
3
.macro  isr                             ;macro for Interrupt Service Routine
4
        .set    _curr_addr = pc
5
        .org    @0
6
        rjmp    _curr_addr
7
        .org    _curr_addr
8
.endmacro
9
;--------------------------------------------------------------------------------
10
        .org    0x0000
11
        rjmp    init
12
        .org    INT_VECTORS_SIZE
13
init:
14
        ; init stuff
15
main:
16
        ; main loop
17
        rjmp    main
18
;--------------------------------------------------------------------------------
19
        ISR     OC1Aaddr
20
        ; interrupt handler
21
        reti
22
;--------------------------------------------------------------------------------

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.