Forum: Mikrocontroller und Digitale Elektronik Interruptproblem bei AT90S1200


von Fiffi (Gast)


Lesenswert?

Hallo,

warum kommt nach folgendem Initialisierungscode ein Interrupt, wenn
PD2=0 und der Interrupt auf steigende Flanke eingestellt ist ?

(habe nur im AVR-Studio 3.56 simuliert ...)

.INCLUDE "1200def.inc"

.DEF   sreg_int_ext    = r0

.DEF  temp      = r16
.DEF  temp_int_ext    = r18
.DEF  temp_int_ext2    = r19

.EQU  INT0_FALLING_EDGE   = 2
.EQU  INT0_RISING_EDGE    = 3

.CSEG
.ORG  0x0
  rjmp  RESET
  rjmp  EXT_INT0  ;External Interrupt0 Vector Address
  reti      ;Overflow0 Interrupt Vector Address
  reti      ;Analog Comparator Interrupt Vector Address

RESET:
  cli      ; Global Interrupt Disbale

  clr  temp
  out  DDRD, temp  ; Port D = Inputs

  ser  temp
  out  PORTD, temp  ; Enable Internal Pull-Up resistors for Port D

  clr  temp
  out  GIMSK, temp  ; Disable External Interupt0

  ldi  temp, INT0_FALLING_EDGE
  sbis  PIND, BL_INP_PORT_BIT
  ldi  temp, INT0_RISING_EDGE

  out  MCUCR, temp  ; negatived edge of the input pin state

  ldi  temp, 0x40
  out  GIMSK, temp  ; Enable External Interupt0

  sei      ; Global Interrupt Enable

  rjmp  MAIN

EXT_INT0:
  in  sreg_int_ext, SREG  ; save the status register

;  Eigentlicher Code ...

  ldi  temp_int_ext, INT0_FALLING_EDGE
  sbis  PIND, BL_INP_PORT_BIT
  ldi  temp_int_ext, INT0_RISING_EDGE
  out  MCUCR, temp_int_ext  ; negatived edge of the input pin state

  out  SREG, sreg_int_ext
  reti

MAIN:

  rjmp  MAIN


Vielen Dank für eure Hilfe !

von Uwe (Gast)


Lesenswert?

Hi!
Vermutlich wird das (leider) nicht löschbare Flag beim setzen der
PullUp's mit gesetzt und löst bei "sei" dann aus. Du muust das ganze
also irgendwie anders abfangen.
Was ich aber noch gesehen habe:>.DEF   sreg_int_ext    = r0
Wenn ich mich nicht irre sollte
>in  sreg_int_ext, SREG  ; save the status register
einen Fehler erzeugen weil "in" mit Rd-Registern angegeben ist und
Rd=R16-R31 ist.

MFG Uwe

von Fiffi (Gast)


Lesenswert?

Halo Uwe,

>Du muust das ganze also irgendwie anders abfangen.

Aber wie, ohne viel Zeit zu verschwenden ?

Ein korrekter Interrupt wäre, wenn MCUCR Bit0 ungleich dem INPD Bit 0
ist.

.DEF  temp_int_ext    = r18
.DEF  temp_int_ext2    = r19

; Am Anfang des Interrupts
  in  temp_int_ext, PIND
  lsr  temp_int_ext
  lsr  temp_int_ext
  andi  temp_int_ext, 1
  in  temp_int_ext2, MCUCR
  andi  temp_int_ext2, 1
  cp  temp_int_ext, temp_int_ext2
  breq  int0_ok
  reti        ; check if the interrupt is correct (must be: MCUCR Bit 0 
!=
PD2) [costs 9µs]

int0_ok:

Kenntst du eine schnellere Lösung ?

>einen Fehler erzeugen weil "in" mit Rd-Registern angegeben ist und
>Rd=R16-R31 ist.

Also bei mir in der Hilfe steht folgendes:

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

von Fiffi (Gast)


Lesenswert?

Verschrieben!

Ein korrekter Interrupt wäre, wenn MCUCR Bit0 ungleich dem INPD Bit 2
ist.

von Uwe (Gast)


Lesenswert?

Hi!
"temp_int_ext"  ist doch bei Init=0(notfalls ldi temp_int_ext,0)
In der ISR schreibst du dann:
EXT_INT0:
  in  sreg_int_ext, SREG  ; save the status register

  tst temp_int_ext
  breq null

;  Eigentlicher Code ...

  ldi  temp_int_ext, INT0_FALLING_EDGE
  sbis  PIND, BL_INP_PORT_BIT
  ldi  temp_int_ext, INT0_RISING_EDGE
  out  MCUCR, temp_int_ext  ; negatived edge of the input pin state

null:  out  SREG, sreg_int_ext
  reti

Das könnte etwas schneller sein.

>Also bei mir in der Hilfe steht folgendes:

>IN Rd,A      0 &#8804; d &#8804; 31, 0 &#8804; A &#8804; 63
>  PC <- PC + 1

Komische Sache. Im Instruktion Set steht es tatsache so, nur dann ist
die Unterscheidung in Rr und Rd sinnlos wenn sich keiner drann hält.

MFG Uwe

von Fiffi (Gast)


Lesenswert?

Hallo Uwe,

vielen Dank für deine Idee !

In deiner Lösung war nur ein kleiner Fehler: nach dem ersten falschen
Interrupt muss sich das Register "temp_int_ext" verändern.

Ich habe es nun so gemacht:
EXT_INT0:
  in  sreg_int_ext, SREG  ; save the status register

  tst  temp_int_ext
  brne  int0_ok
  ser  temp_int_ext
  reti
int0_ok:

von Uwe (Gast)


Lesenswert?

Hi!
Ja, ist mir später auch noch eingefallen.

Kürzere Variante wäre:
.
.
.

  clr  temp_int_ext
  out  DDRD, temp_int_ext  ; Port D = Inputs
  ser  temp
  out  PORTD, temp  ; Enable Internal Pull-Up resistors for Port D

  sei      ; Global Interrupt Enable (Falscher Interr.)
  ldi  temp_int_ext, INT0_FALLING_EDGE (Jetzt OK)
  rjmp  MAIN

EXT_INT0:
  in  sreg_int_ext, SREG  ; save the status register

  tst temp_int_ext
  breq null

;  Eigentlicher Code ...

  ldi  temp_int_ext, INT0_FALLING_EDGE
  sbis  PIND, BL_INP_PORT_BIT
  ldi  temp_int_ext, INT0_RISING_EDGE
  out  MCUCR, temp_int_ext  ; negatived edge of the input pin state

null:  out  SREG, sreg_int_ext
  reti

Nun sollte es aber hinhauen. Ach ja, du wolltest hoffentlich noch ein
"reti" einbauen.

MFG Uwe

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.