Forum: Mikrocontroller und Digitale Elektronik Externer Interrupt - ATmega328P - Assembler


von Martin (Gast)


Lesenswert?

Hallo Zusammen,
ich beschäftige mich gerade mit dem Microcontroller "ATmega328P" und 
versuche in Assembler über die Externen Interrupts eine LED anzusteuern.

Ziel soll es sein, durch einen Interrupt INT0 oder INT1 die LED 
auszuschalten.

Als Entwicklungsboard benutze ich das Arduino Uno und als 
Entwicklungsumgeben das Atmel AVR Studio 7.0 mit AVRDude zum Flashen.

Hier mal mein Code:
1
.org 0x0000
2
  rjmp main
3
.org 0x0002
4
    rjmp int0_handler    ; IRQ0 Handler
5
.org 0x0004
6
    rjmp int1_handler    ; IRQ1 Handler
7
8
main:
9
  ; Setup interrupt INT0 and INT1
10
  ldi r16, (1<<ISC11) | (1<<ISC10)  ; INT0 and INT1 - falling edge 
11
  sts EICRA, r16            ; SET EICRA
12
  ldi r17, (1 << INT0) | (1 << INT1)  ; Enable INT0/INT1 interrupt
13
  sts EIMSK, r17            ; Set EIMSK
14
  ldi r16, 0x00            ; Set all ports of DDRD as input
15
    out DDRD, r16            ; Set DDRD
16
17
  sei                  ; Interrupt enable
18
19
  ; Setup LED Output
20
  ldi r16, 0xFF            ; Set all Ports of DDRB as output
21
    out DDRB, r16            ; Set DDRB
22
  ldi r16, 0xFF            ; Set all LEDs on PORTB high
23
    out PORTB, r16            ; Write PORTB
24
 
25
start:            ; Endless loop
26
    rjmp start
27
28
int0_handler:
29
  ldi r16, 0x00      ; Load R16 with 0
30
    out PORTB, r16          ; Write R16 out to PortB - All Outputs of low
31
  reti
32
33
int1_handler:
34
  ldi r16, 0x00      ; Load R16 with 0
35
    out PORTB, r16          ; Write R16 out to PortB - All Outputs of low
36
  reti

Meine LED an Port DDRB geht an, jedoch kann ich beide Taster an den 
Externen Interrupts drücken und die LED geht nicht mehr aus.

Zum Test ob die Schalter Funktionieren habe ich sie so einmal 
ausgelesen, dann konnte ich die LEDs an bzw ausschalten.

Könnt ihr mir helfen und sagen was ich übersehen oder falsch mache?

Gruß Martin

von input (Gast)


Lesenswert?

; Set all ports of DDRD as input

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


Lesenswert?

Martin schrieb:
> Könnt ihr mir helfen und sagen was ich übersehen oder falsch mache?
1
> int0_handler:
2
>   ldi r16, 0x00      ; Load R16 with 0
3
>     out PORTB, r16          ; Write R16 out to PortB - All Outputs of 
4
> low
5
>   reti
6
> 
7
> int1_handler:
8
>   ldi r16, 0x00      ; Load R16 with 0
9
>     out PORTB, r16          ; Write R16 out to PortB - All Outputs of 
10
> low
11
>   reti

 PortB bleibt auf 0, LEDs sind immer an.
 Probiere es mal mit EOR.
1
   ser    r17
2
   in    r16, PORTB
3
   eor    r16, r17
4
   out    PORTB, r16

: Bearbeitet durch User
von c-hater (Gast)


Lesenswert?

Martin schrieb:

>  ldi r16, (1<<ISC11) | (1<<ISC10)  ; INT0 and INT1 - falling edge

Nö. Um das zu erreichen, was der Kommentar meint, was hier passieren 
würde, hätte man eine andere Konstante benutzen müssen...

Was übrigens gleich beweist, dass du nicht wirklich beide Tasten 
getestet haben kannst, denn bei einer hätte es tastsächlich 
funktionieren müssen (und tut es tatsächlich auch).

Es sei denn, zu dem obigen Programmierfehler kommen noch andere Fehler, 
z.B. in der Beherrschung der Toolchain...

von Martin (Gast)


Lesenswert?

Hallo,
1
ser    r17           ; r17 mit 0xff fuellen
2
in    r16, PORTB     ; PORTB auslesen
3
eor    r16, r17      ; Exclusiv Oder mit r17 und r16
4
out    PORTB, r16    ; r16 zurueckschreiben

habe gerade mal versucht deinen Code zu verstehen.
Habe es mal in die InterruptRoutine eingebaut, hat leider nichts 
geholfen.

Ich habe auch das Gefühl, dass ich nicht mal in die Routine komme und 
irgendetwas bei der Initialisierung falsch gemacht habe.
Weis leider nur nicht was...

Martin

von c-hater (Gast)


Lesenswert?

Marc V. schrieb:

>  PortB bleibt auf 0, LEDs sind immer an.

Nö, die LEDs werden in main eingeschaltet.

>  ; Setup LED Output
>  ldi r16, 0xFF            ; Set all Ports of DDRB as output
>    out DDRB, r16            ; Set DDRB
>  ldi r16, 0xFF            ; Set all LEDs on PORTB high
>    out PORTB, r16            ; Write PORTB

Und sollen offensichtlich durch Betätigung eines der beiden Taster (egal 
welches) *aus*-geschaltet werden.

Nur leider ist der "Sense" für beide falsch konfiguriert. Die eine ist 
für LowLevel sensualisiert, die andere für steigende Flanke. Also keine 
von beiden für die eigentlich gewünschte fallende Flanke.

Nichtsdestotrotz müßte natürlich der versehentlich für LowLevel 
konfigurierte nach der fallenden Flanke trotzdem reagieren. Der 
Low-Pegel muss halt nur lange genug anliegen, was bei manueller 
Betätigung fast unvermeidbar sein dürfte...

Und der andere müßte eigentlich auch (spätestens beim Loslassen) 
reagieren.

Da dürften neben dem kleinen Programmfehler noch andere Fehler lauern. 
Vermutlich bei der Beherrschung der Toolchain...

von Martin (Gast)


Lesenswert?

Hi c-hater,
was genau meinst du mit der Beherrschung der Toolchain?
Ja da habe ich wohl einen Fehler mit der Einstellung der Fallenden 
Flanke gemacht. Aber eigentlich sollte der Interrupt trotzdem reagieren.

Gruß Martin

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


Lesenswert?

c-hater schrieb:
> Nur leider ist der "Sense" für beide falsch konfiguriert. Die eine ist
> für LowLevel sensualisiert, die andere für steigende Flanke. Also keine
> von beiden für die eigentlich gewünschte fallende Flanke.

 Ja.
 Richtig wäre es:
1
  ldi r16, (1<<ISC11) | (1<<ISC01)   ; INT0 and INT1 - falling edge 
2
  sts EICRA, r16                     ; SET EICRA

 Trotzdem hätte es zumindest bei einem funktioniren sollen.

Martin schrieb:
> Meine LED an Port DDRB geht an, jedoch kann ich beide Taster an den
> Externen Interrupts drücken und die LED geht nicht mehr aus.

 LEDs werden ublicherweise andersherum angeschlossen, ANODE uber 2K2 an
 VCC, Kathode an PORT.

 Taster an Masse und das andere Ende ist wo ?

von c-hater (Gast)


Lesenswert?

Martin schrieb:

> Ja da habe ich wohl einen Fehler mit der Einstellung der Fallenden
> Flanke gemacht. Aber eigentlich sollte der Interrupt trotzdem reagieren.

Das kommt auf die Schaltung an. Auch da kann man viel falsch machen. 
Also: Schaltplan posten.

Übrigens: was passiert eigentlich, wenn du die eine "aktive" Zeile in 
beiden ISRs auskommentierst? LED an oder aus?

Und was passiert, wenn du dazu auch noch die zweite dieser beiden Zeilen 
auskommentierst?

>  ldi r16, 0xFF            ; Set all LEDs on PORTB high
>    out PORTB, r16            ; Write PORTB

LED an oder aus?

von Martin (Gast)


Lesenswert?

Hallo,

c-hater schrieb:
> was passiert eigentlich, wenn du die eine "aktive" Zeile in
> beiden ISRs auskommentierst?

Leds sind immer noch an

c-hater schrieb:
> Und was passiert, wenn du dazu auch noch die zweite dieser beiden Zeilen
> auskommentierst?

Dann ist die LED aus.

Zum Schaltplan:
Led ist die LED direkt am Port 13 des Arduinos welche auf dem Board 
eingelötet ist.

Meine Taster sind an 5V und INT0 und INT1 angeschlossen. Damit sie nicht 
in der Luft "hängen" habe ich sie mit mit einem 10K Widerstand auf GND 
gezogen.

Gruß Martin

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


Lesenswert?

Martin schrieb:
> Meine Taster sind an 5V und INT0 und INT1 angeschlossen. Damit sie nicht
> in der Luft "hängen" habe ich sie mit mit einem 10K Widerstand auf GND
> gezogen.

 LOL.
 Umdrehen.

von Martin (Gast)


Lesenswert?

Hallo,
Umdrehen hat auch nichts gebracht...
Hat jemand noch eine Idee?
Kann es auch etwas mit dem Botloader des Arduinos zu tun haben? Dass die 
Interrupt Einsprungadressen andere sind?

Martin

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


Lesenswert?

Martin schrieb:
> Kann es auch etwas mit dem Botloader des Arduinos zu tun haben? Dass die
> Interrupt Einsprungadressen andere sind?
 Nein, aber beim m328 springst du in der InterruptTabelle normalerweise
 nicht mit rjmp, sondern mit jmp.

> Umdrehen hat auch nichts gebracht...
 Das kann nicht sein.

> Hat jemand noch eine Idee?
 Ja.
 Das was du geschrieben hast ist nicht das, was du gemacht hast.

: Bearbeitet durch User
von c-hater (Gast)


Lesenswert?

Martin schrieb:

> Meine Taster sind an 5V und INT0 und INT1 angeschlossen. Damit sie nicht
> in der Luft "hängen" habe ich sie mit mit einem 10K Widerstand auf GND
> gezogen.

Das hieße, die fallende Flanke tritt auf, wenn man die Taster losläßt, 
nicht, wenn man sie drückt. Also sinnvollerweise entweder die 
Tasterschaltung "umdrehen" oder die INTs für steigende Flanke 
"sensibilisieren". Tasterschaltung umdrehen hätte den Vorteil, dass man 
die internen Pullups nutzen kann und damit zwei Widerstände spart.

Ansonsten: Nach deinen Beobachtungen ist die Ansteuerung der LEDs 
korrekt. Bleibt also die Ansteuerung der Tasten. An welchen Eingängen 
hängen die denn physisch? (Pin-Nummer des ATMega?)

Den Mega328P gibt es in vier Gehäusevarianten, die nicht weniger als 
drei verschiedene Zuordnungen der INT-Pins zu den Pin-Nummern haben:

Package INT0-Pin INT1-Pin
TQFP32  32       1
MLF32   32       1
MLF28   28       1
PDIP28  4        5

von spess53 (Gast)


Lesenswert?

Hi

>  ldi r17, (1 << INT0) | (1 << INT1)  ; Enable INT0/INT1 interrupt
>  sts EIMSK, r17            ; Set EIMSK

EIMSK liegt auf IO-Adresse 0x3D. Da muss mit in/out zugegriffen werden. 
Mit STS greifst du ins Leere.

MfG Spess

von spess53 (Gast)


Lesenswert?

Hi

>EIMSK liegt auf IO-Adresse 0x3D.

Gemeint war natürlich 0x1D.

MfG Spess

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


Lesenswert?

spess53 schrieb:
> EIMSK liegt auf IO-Adresse 0x3D. Da muss mit in/out zugegriffen werden.
> Mit STS greifst du ins Leere.

 LOL.
 Man kann mit allem rechnen, nur nicht damit, dass die Fragesteller die
 entsprechenden Datasheets zuerst lesen.
 Wozu auch ?
 Irgendeiner wird es schon tun...

von Martin (Gast)


Lesenswert?

Hallo,

spess53 schrieb:
> EIMSK liegt auf IO-Adresse 0x3D. Da muss mit in/out zugegriffen werden.
> Mit STS greifst du ins Leere.

Ja das war das Problem, vielen dank.

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.