Forum: Mikrocontroller und Digitale Elektronik ATMega328P /avrasm External Interrupt funktioniert nicht


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Antonis (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Ich benutze folgenden Code um mit einem ATMega328P externe Interrupt 
auszulösen:
1
;
2
; MultiLaserTrigger.asm
3
;
4
; Created: 24.10.2016 15:41:11
5
; Author : antonios.styogiannis
6
;
7
.def temp   = r16
8
.def ledson = r17
9
10
.org 0x0000
11
      rjmp     main                  ; Reset Handler
12
13
.org 0x0002
14
      rjmp     EXT_INT0
15
16
main:
17
        ; Stackpointer initialisieren
18
       ldi     temp, HIGH(RAMEND)
19
       out     SPH, temp
20
       ldi     temp, LOW(RAMEND)     
21
       out     SPL, temp
22
       ldi     temp, 0b11111111            ; Port B auf Ausgang
23
       out     DDRB, temp
24
       ldi     ledson, 0b11111111     ; Inverted, all leds off.
25
       ldi     temp, (1 << ISC01) | (1 << ISC00) 
26
       sts     EICRA, temp
27
       ldi     temp, (1 << INT0)
28
       sts     EIMSK, temp
29
       ldi     temp, (1 << IVSEL)
30
       sts     MCUCR, temp
31
       ldi     temp, 0b00000001   ;new
32
       sts     EIFR, temp
33
       sei
34
       com     ledson
35
       out     PORTB, ledson
36
37
loop1:
38
       rjmp    loop1
39
    
40
EXT_INT0:
41
       out     PORTB, ledson
42
       com     ledson
43
       reti

Der Interrupt wird aber nicht ausgelöst.
Wenn Ich den gleichen Code in C benutze, funktioniert es.
Kann man mir helfen?

Vielen Dank.

von Peter II (Gast)


Bewertung
0 lesenswert
nicht lesenswert
ein Kurzer blick ins Datenblatt liefert:

[asm]
Address LabelsCodeComments
.org 0x001
0x001 rjmp EXT_INT0 ; IRQ0 Handler
0x002 rjmp EXT_INT1 ; IRQ1 Handler
[/asm]

dort steht also bei org die 0x01.

von Antonis (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Für den ATMega328P die Adresse für den INT0 ist 0x0002:

1 0x0000 RESET External Pin, Power-on Reset, ...
2 0x0002 INT0 External Interrupt Request 0
3 0x0004 INT1 External Interrupt Request 1
...

Ich habe auch INT0addr staat 0x0002 benutzt und es hat auch nicht 
funktioniert.

von S. Landolt (Gast)


Bewertung
0 lesenswert
nicht lesenswert
EIMSK, MCUCR und EIFR werden per out angesprochen, siehe im Datenblatt 
'Register Summary'.

von Antonis (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Wenn Ich out für EICRA benutze bekomme Ich "Operand 1 out of range: 
0x69".
Ich habe "out" statt "sts" für EIMSK, MCUCR und EIFR benutzt aber es 
funktioniert auch nicht.

von S. Landolt (Gast)


Bewertung
0 lesenswert
nicht lesenswert
> ldi     temp, (1 << IVSEL)
> sts     MCUCR, temp
Der tiefere Sinn hierfür?
Aus dem Datenblatt:
"When the IVSEL bit is cleared (zero), the Interrupt Vectors are placed 
at the start of the Flash memory. When this bit is set (one), the 
Interrupt Vectors are moved to the beginning of the Boot Loader section 
of the Flash."

von Antonis (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich habe
1
   ldi temp, (1 <<IVSEL )
2
   out MCUCR, temp

kommentiert und nochmal versucht. Funktioniert auch nicht.

von S. Landolt (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Mit INT0addr ?

von Antonis (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Sowohl mit "INT0addr" als auch mit "0x0002". Funktioniert auch nicht.

von Theor (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Auf welche Weise stellst Du denn fest, das es nicht funktioniert?

Du könntest zuerst einmal im Simulator schauen, ob die Bits der 
Steuerregister wie gewollt gesetzt werden.
Zuletzt kann man dort auch sehen, ob die ISR angesprungen wird.

Ich habe mir den Code nicht im Detail angeschaut, aber das 
"ausprobieren" von STS anstelle OUT könnte bedeuten, dass evtl. nicht 
bekannt ist, dass etwa EIMSK unter zwei Adressen erreichbar ist, die 
sich aber darin unterscheiden ob sie mit OUT oder STS benutzt werden.

Die Definition von EIMSK in den include-Files (das ich übrigens in 
Deinem Quellcode nicht sehe), ist nur für einen der beiden Fälle 
ausgelegt. D.h.: Man kann OUT EIMSK, ... nicht einfach durch STS EIMSK, 
... ersetzen.

Bei den hohen Adressen über 0x5F wirst Du gewarnt, wenn Du OUT verwenden 
willst, aber umgekehrt, bei den niedrigen Adressen gibt es keine 
Warnung, denn damit sind sowohl OUT als auch STS anwendbar. Nur sind das 
physisch zwei verschiedene Register.

von S. Landolt (Gast)


Bewertung
0 lesenswert
nicht lesenswert
INT0 (== PD2) hat einen externen pullup-Widerstand?

von S. Landolt (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Besser anders gefragt: wie wird INT0 angesteuert?

von Antonis (Gast)


Bewertung
0 lesenswert
nicht lesenswert
@Theor:
Für EIMSK kann ich auch OUT oder STS benutzen und bekomme weder eine 
Warnung noch einen Error.

Wie soll ich sonst auf das Register EICRA zugreifen?

@Landholt: INT0 hat einen 47Ohm Pull-Down Widerstand. Für EICRA benutze 
beide ISC01 und ISC00 1, das bedeutet dass, Eine steigende Flanke den 
Interrupt auslöst.

von S. Landolt (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Um die Sache abzukürzen: an PB1 LED+R, an INT0 ein externer Pullup und 
Taster gegen GND, dann läuft, d.h. die LED wird per Tastendruck 
umgeschaltet (mit Prellen), folgendes Programm bei mir:
1
.include "m328def.inc"
2
3
.def temp   = r16
4
.def ledson = r17
5
6
.org 0x0000
7
      rjmp     main                  ; Reset Handler
8
9
.org INT0addr
10
      rjmp     EXT_INT0
11
12
main:
13
       ldi     temp, 0b11111111            ; Port B auf Ausgang
14
       out     DDRB, temp
15
       ldi     ledson, 0b11111111     ; Inverted, all leds off.
16
       ldi     temp, (1 << ISC01) | (1 << ISC00) 
17
       sts     EICRA, temp
18
       ldi     temp, (1 << INT0)
19
       out     EIMSK, temp
20
       sei
21
       out     PORTB, ledson
22
23
loop1:
24
       rjmp    loop1
25
    
26
EXT_INT0:
27
       out     PORTB, ledson
28
       com     ledson
29
       reti

von Antonis (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ok.
Das hat auch endlich für mich funktioniert!
Ich sollte OUT für EIMSK benutzen.

Vielen Dank.

von Thomas E. (Firma: Thomas Eckmann Informationst.) (thomase)


Bewertung
0 lesenswert
nicht lesenswert
Antonis schrieb:
> INT0 hat einen 47Ohm Pull-Down Widerstand. Für EICRA benutze
> beide ISC01 und ISC00 1, das bedeutet dass, Eine steigende Flanke den
> Interrupt auslöst.

Gegen eine 47Ω-Widerstand? Der Eingang reagiert auf Spannung, nicht auf 
Wärme.

Antonis schrieb:
> ldi temp, (1 <<IVSEL )
>    out MCUCR, temp
>
> kommentiert und nochmal versucht. Funktioniert auch nicht.

Natürlich nicht. Was soll das überhaupt?

von Aufpasser (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Antonis schrieb:
> Ich sollte OUT für EIMSK benutzen.

Das hat dir doch der Landolt schon gesagt.

S. Landolt schrieb:
> EIMSK, MCUCR und EIFR werden per out angesprochen, siehe im
> Datenblatt
> 'Register Summary'.

von Marc V. (Firma: Vescomp) (logarithmus)


Bewertung
0 lesenswert
nicht lesenswert
Antonis schrieb:
> Ich sollte OUT für EIMSK benutzen.

 Oder Macros
1
.include  "m328pdef.inc"
2
;***  Damit man nicht lange ueberlegen muss..
3
.macro  xout
4
.if     @0 > 0x3F
5
        sts     @0, @1
6
.else
7
        out     @0, @1
8
.endif
9
.endmacro
10
11
.def temp   = r16
12
.def ledson = r17
13
14
    .CSEG
15
.ORG  0x0000
16
      jmp     main                  ; Reset Handler
17
18
.ORG  INT0addr            ;*  ATMEL liefert doch die Adresse
19
      jmp     EXT_INT0              ;* JMP benutzen bei M328P
20
21
main:
22
        ; Stackpointer initialisieren
23
       ldi     temp, HIGH(RAMEND)
24
       out     SPH, temp
25
       ldi     temp, LOW(RAMEND)     
26
       out     SPL, temp
27
       ldi     temp, 0b11111111            ; Port B auf Ausgang
28
       out     DDRB, temp
29
       ldi     ledson, 0b11111111     ; Inverted, all leds off.
30
   ;*****  INT0 auf steigende Flanke
31
       ldi     temp, (1 << ISC01) | (1 << ISC00) 
32
       xout     EICRA, temp            ;*****  Geht immer auf richtige Adresse
33
   ;*****  INT0 freigegeben
34
       ldi     temp, (1 << INT0)
35
       xout     EIMSK, temp            ;*****  Geht immer auf richtige Adresse
36
   ;*****  ???? Wozu das ????
37
;       ldi     temp, (1 << IVSEL)
38
;       sts     MCUCR, temp
39
   ;*****  INTF0 loeschen
40
       ldi     temp, 0b00000001   ;new
41
       xout     EIFR, temp            ;*****  Geht immer auf richtige Adresse
42
       sei
43
       com     ledson
44
       out     PORTB, ledson
45
46
loop1:
47
       rjmp    loop1
48
    
49
EXT_INT0:
50
       out     PORTB, ledson
51
       com     ledson
52
       reti

: Bearbeitet durch User

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]
  • [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.