mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Problem: INT0/1 auf Arduino


Autor: Simon E. (eingehirner)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Hallo zusammen,

ich komme nicht mehr weiter. Eigentlich ein einfaches Problem: den INT0 
und/oder INT1 auf einem Arduino Uno mit ATmega328P zum Laufen zu 
kriegen. Mein Code:
.include "../m328Pdef.inc"

.CSEG ; Program and flash data section

.org 0x0000     jmp     RESET           ; Reset Handler
.org 0x0002     jmp     EXT_INT0        ; IRQ0 Handler
.org 0x0004     jmp     EXT_INT0        ; IRQ1 Handler
...

.org 0x0034
RESET:
; Init stack pointer
  ldi r16, HIGH(RAMEND)
  out SPH, r16
  ldi r16, LOW(RAMEND)
  out SPL, r16

  ; Init INT0 pin
  cbi DDRD, 2 ; input
  sbi PORTD, 2 ; pull-up ON

  ; Init INT1 pin
  cbi DDRD, 3 ; input
  sbi PORTD, 3 ; pull-up ON

  ; Init LED pin
  sbi DDRB, 5 ; output
  cbi PORTB, 5 ; set to OFF

  ; Init counter pins PC0-3
  sbi DDRC, 0
  sbi DDRC, 1
  sbi DDRC, 2
  sbi DDRC, 3

  cbi PORTC, 0
  cbi PORTC, 1
  cbi PORTC, 2
  cbi PORTC, 3

  ; Interrupt register EICRA/B
  ; EICRA:    ISC11:0   11
  ;           ISC01:0   11
  ; EIMSK:    INT1      1 (enabled)
  ;           INT0      1 (enabled)

  lds r16, EICRA
  ori r16, 0x0F ; ISCx1:0 = 0b11
  sts EICRA, r16

  lds r16, EIMSK
  ori r16, 0x03 ; INT0/1 enable
  sts EIMSK, r16

  ; Activate interrupts
  sei

Loop:
  ; on-board LED on half brightness to show the loop is running
  sbi PORTB, 5
  nop
  nop
  nop
  nop
  nop
  nop
  nop
  nop
  cbi PORTB, 5
  nop
  nop
  nop
  nop

  rjmp Loop
; ======== ISR ===========
EXT_INT0:
  push r16
  in r16, SREG
  push r16

  ; Just count up in PORTC0-3
  in r16, PORTC
  inc r16
  andi r16, 0x0F
  out PORTC, r16

  pop r16
  out SREG, r16
  pop r16
reti

Nicht extrem komplex, sollte man meinen. Hab ich irgendwo ein massives 
Brett vor dem Kopf?
- Spannungsversorgung: stabil (USB)
- Pin D2/D3 lebendig: ja (kann als Nicht-Interrupt sowohl Signale 
erkennen als auch ausgeben)
- Loop läuft (LED gedimmt an)
- getestete Modi: Trigger bei level low, bei any logical change, bei 
falling flank und rising flank
- versuchte Aktivierung mit Jumperkabel an GND, an VCC
- mit und ohne internem Pull-Up getestet
- mit externem Pull-Down von 4,7kO getestet
- Interrupt-Vektoren sind an der richtigen Stelle (mit TIM0_OVF 
getestet)

Der Arduino hat einen Bootloader drauf, BOOTRST-Fuse ist programmiert, 
Bootsize ist 256 words; trotzdem ist mein RESET-Sprungbefehl an .org 
0x0000 (statt, wie im AVR-Datenblatt beschrieben, bei 0x3C00). Wenn ich 
ihn auf 0x3C00 umschreibe, läuft mein Programm nicht mehr und macht 
merkwürdige Sprünge, deshalb hab ich's (wider besseres Wissen(?)) so 
gelassen. Da der TIM0_OVF korrekt funktioniert, sollten INT0 und INT1 
das auch tun - oder?

(Dass bei INT0 und INT1 dieselbe ISR angesprungen wird, ist Absicht.)

Hat irgendwer eine Idee oder sieht sofort, was ich nach einer Woche 
Suchen noch nicht entdeckt hab? Macht der Arduino-Bootloader 
irgendwelche komischen Sachen, die ich später nicht mehr umdefinieren 
kann?

Viele Grüsse,
Simon

Autor: Wolfgang (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon E. schrieb:
> Hat irgendwer eine Idee oder sieht sofort, was ich nach einer Woche
> Suchen noch nicht entdeckt hab?

Im Simulator verhält sich das Programm so wie von dir erwartet?

Autor: Arduino Fanboy D. (ufuf)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Simon E. schrieb:
> Der Arduino hat einen Bootloader drauf, BOOTRST-Fuse ist programmiert,
> Bootsize ist 256 words; trotzdem ist mein RESET-Sprungbefehl an .org
> 0x0000 (statt, wie im AVR-Datenblatt beschrieben, bei 0x3C00).

Das ist schon OK so.
Bei 0x3C00 wohnt der Bootloader.

Das Lable RESET: sollte nicht RESET heißen, sondern Init !
Dann wird klarer, was es tut.

: Bearbeitet durch User
Autor: Chris H. (Firma: Selbständig Denkender) (keiningenieur)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon E. schrieb:
> lds r16, EIMSK
>   ori r16, 0x03 ; INT0/1 enable
>   sts EIMSK, r16

Die EIMSK liegt unter $3f und muss mit in/out angesprochen werden

Simon E. schrieb:
> sbi DDRC, 0
>   sbi DDRC, 1
>   sbi DDRC, 2
>   sbi DDRC, 3
>
>   cbi PORTC, 0
>   cbi PORTC, 1
>   cbi PORTC, 2
>   cbi PORTC, 3

so kompliziert 4 Zeilen reichen auch

ldi r16,$0e
out ddrc, r16

clr  r16
out  PortC,r16

Simon E. schrieb:
> ; Init INT0 pin
>   cbi DDRD, 2 ; input
>   sbi PORTD, 2 ; pull-up ON
>
>   ; Init INT1 pin
>   cbi DDRD, 3 ; input
>   sbi PORTD, 3 ; pull-up ON

  ldi r16,(1<<pd3 | 1<<pd2)
  out portd,r16

: Bearbeitet durch User
Autor: Simon E. (eingehirner)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Chris H. schrieb:
> Die EIMSK liegt unter $3f und muss mit in/out angesprochen werden

Das war's. Hammer! Brett vorm Kopf weg! Vielen, vielen Dank!

Beim Compilieren (mit avrasm2.exe) kommt kein Fehler, wenn ich mit 
lds/sts arbeite. Gibt es irgendeine "sinnvolle" Anwendung dafür, 
Register unter 0x3F00 damit anzusprechen?

Und: Woher weiss man sowas? Bisher war ich davon ausgegangen, dass 
in/out einfach effizientere, sprich schnellere Befehle sind, die man 
deshalb vorzugsweise nimmt (aber nicht nehmen muss). Die Doku von 
Atmel/Microchip gibt da nicht viel her:

IN:
Loads data from the I/O Space (Ports, Timers, Configuration registers etc.) into register Rd in the register file.

Operation:

(i)Rd ← I/O(A)

Syntax: Operands: Program Counter:

IN Rd,A 0 ≤ d ≤ 31, 0 ≤ A ≤ 63 PC ← PC + 1

LDS:
Loads one byte from the data space to a register. For parts with SRAM, the data space consists of the register file, I/O memory and internal SRAM (and external SRAM if applicable). For parts without SRAM, the data space consists of the register file only. The EEPROM has a separate address space.

A 16-bit address must be supplied. Memory access is limited to the current data segment of 64K bytes. The LDS instruction uses the RAMPD register to access memory above 64K bytes. To access another data segment in devices with more than 64K bytes data space, the RAMPD in register in the I/O area has to be changed.

This instruction is not available in all devices. Refer to the device specific instruction set summary. In particular, notice that ATtiny10-based devices use the LDS instead of this instruction.

Operation:

(i)Rd ← (k)

Syntax: Operands: Program Counter:

(i)LDS Rd,k 0 ≤ d ≤ 31, 0 ≤ k ≤ 65535 PC ← PC + 2
                        AAAAAAAAAAAAA

Oder kommt es darauf an?
A 16-bit address must be supplied.
Aber wie berücksichtigt man das?

Viele Grüsse,
Simon

Autor: Matthias S. (Firma: matzetronics) (mschoeldgen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon E. schrieb:
> Bisher war ich davon ausgegangen, dass
> in/out einfach effizientere, sprich schnellere Befehle sind, die man
> deshalb vorzugsweise nimmt

Wenn du dir das Datenblatt, und hier vor allem die Register Summary 
anschaust, sieht du, das Register unterhalb der Adresse 0x3F zwei 
Adressen haben. Die eine gilt für die Addressierung mit IN/OUT, die 
andere für STS/LDS. Du kannst EIMSK mit STS und mit IN/OUT ansprechen, 
musst aber dann die andere Adresse benutzen, die Definition im Header 
für EIMSK gilt für In/Out, wimre. Das ganze kommt daher, das heutige AVR 
viel mehr Register haben, die mit In/Out nicht mehr erreichbar wären. 
(und auch heute noch nicht bitadressierbar sind).

: Bearbeitet durch User
Autor: Chris H. (Firma: Selbständig Denkender) (keiningenieur)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
https://www.sparkfun.com/datasheets/Components/SMD/ATMega328.pdf

Datenblatt S.20 I/O-Memory und
RegisterSummery S.428 mal lesen ;)

Autor: Simon E. (eingehirner)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jep:
When addressing I/O Registers as data space using LD and ST instructions, 0x20 must be added to these addresses.

Nur dass ich unter "I/O registers" immer lediglich die Ports verstanden 
hab...

Super, danke für eure Hilfe! Ist lang her, dass ich das vollständig 
gelesen hab und damals vermutlich eher für den ATTiny2313, mit dem ich 
mehr Projekte realisiert hab... Immer dieser Tradeoff zwischen Effizienz 
und Korrektheit :-/

Jedenfalls läuft das Tierchen jetzt :-)

Viele Grüsse,
Simon

: 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]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [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.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.