Forum: Mikrocontroller und Digitale Elektronik Interrupt funktioniert nicht


von Armin A. (10110010)


Lesenswert?

Hallo,

ich möchte einen AtTiny13A-SU programieren
Pin3 soll ein Eingang sein und 2 & 1 ein Ausgang.
Der Interrupt soll auf Steigende Flanken reagieren (INT0).

Hier mein Code

rjmp RESET      ;Reset
    rjmp PPM      ;Interupt Pin1
    reti        ;PCINT0     -> Pin Change Interrupt Request 0
  reti        ;TIM0_OVF   -> Timer/Counter Overflow
  reti        ;EE_RDY     -> EEPROM Ready
  reti        ;ANA_COMP   -> Analog Comparator
  reti        ;TIM0_COMPA -> Timer/Counter Compare Match A
  reti        ;TIM0_COMPB -> Timer/Counter Compare Match B
  reti        ;WDT        -> Watchdog Time-out
  reti        ;ADC        -> ADC Conversion Complete

RESET:
  LDI r16, low (RAMEND)
  OUT SPL, r16    ;Setzt sen StackPointer auf Anfang
  LDI r16, 0b00000110
  OUT DDRB, r16    ;Setzt Pin1->Output, Pin2->Output, Pin3->Input
  LDI r16, 0b00001000
  OUT PORTB, r16    ;PullUp
  LDI r16, 0b01000000
  OUT GIMSK, r16    ;Aktiviert Interupt INT0
  LDI r16, 0b00000011
  OUT MCUCR, r16    ;Interupt nur bei Steigender Flanke
    SEI

Loop:
  nop
  rjmp Loop

PPM:
  CLI
  IN R15,SREG
        ... Tu was...
  OUT SREG,R15
  SEI

  RETI

Wenn ich im Simulator unter I/O dem Pin3 Signal gebe, interesiert das 
den Interrupt nicht!

Warum?

von Rolf M. (rmagnus)


Lesenswert?

Irgendwie sind bei dir die Pins anscheinend komplett durcheinander:

Armin A. schrieb:
> ich möchte einen AtTiny13A-SU programieren
> Pin3 soll ein Eingang sein und 2 & 1 ein Ausgang.
> Der Interrupt soll auf Steigende Flanken reagieren (INT0).

INT0 liegt nicht auf Pin 3, sondern auf Pin 6.

> rjmp RESET      ;Reset
>     rjmp PPM      ;Interupt Pin1

Hier soll es plötzlich Pin 1 sein?

>   LDI r16, 0b00000110
>   OUT DDRB, r16    ;Setzt Pin1->Output, Pin2->Output, Pin3->Input

Nein, das setzt PB1 und PB2 auf Ausgang. Das sind Pin 6 und 7.

>   LDI r16, 0b00001000
>   OUT PORTB, r16    ;PullUp

Und zwar bei Pin 2.

>   LDI r16, 0b01000000

Es wäre besser, hier mit Registernamen zu arbeiten, damit man nicht Bits 
abzählen muss.

>   OUT GIMSK, r16    ;Aktiviert Interupt INT0
>   LDI r16, 0b00000011
>   OUT MCUCR, r16    ;Interupt nur bei Steigender Flanke
>     SEI
>
> Loop:
>   nop
>   rjmp Loop
>
> PPM:
>   CLI

Ein CLI ist nicht nötig, das macht der Prozessor schon selber.

>   IN R15,SREG
>         ... Tu was...
>   OUT SREG,R15
>   SEI

Und ein SEI sollte niemals in einer ISR stehen, wenn man nicht explizit 
will, dass sich ISRs gegenseitig unterbrechen können.

>   RETI
>
> Wenn ich im Simulator unter I/O dem Pin3 Signal gebe, interesiert das
> den Interrupt nicht!
>
> Warum?

Weil Pin 3 der falsche ist.

: Bearbeitet durch User
von Armin A. (10110010)


Lesenswert?

Hallo,

vielen Dank für deine Antwort.
Wollte eigentlich PB anstatt Pin schreiben.
Heist das, dass ich PCINT3 aktivieren muss, damit Interupts an PB3 
gefeuert werden?

Heist doch, dass PCMSK auf 0b00001000 gesetzt werden muss?

Wenn ich das aber richtig verstehe, reagiert der Interupt auf jede art 
von Änderung (Steigende-, und Fallende Flanke).

Welcher Interrupt wird gefeuert?

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


Lesenswert?

Armin A. schrieb:
> Heist doch, dass PCMSK auf 0b00001000 gesetzt werden muss?

Um auch in zwei Wochen durchzublicken, gewöhne dir besser so eine 
Schreibweise an:
1
   ldi  r16,(1 << PCIE)           ; enable the PC INT
2
   out  GIMSK,r16               ; set the register
3
   ldi  r16, (1 << PCINT3)      ; PC INT on PB3 - Pin 2 on Tiny13
4
   out  PCMSK,r16
5
   ldi  r16,(1 << PCIF)           ; clear pending interrupts
6
   out  GIFR,r16
Damit musst du die absolute Position des Bits gar nicht kennen - der 
Assembler wühlt für dich in den Datenblättern.
Als nächstes stimmt die Vektor Tabelle nicht, siehe Tabelle 18 im DB:
1
         rjmp  RESET          ; Reset Handler
2
         rjmp  EXT_INT0       ; IRQ0 Handler
3
         rjmp  PCINT0         ; PCINT0 Handler
4
         rjmp  TIM0_OVF       ; Timer0 Overflow Handler
5
         rjmp  EE_RDY         ; EEPROM Ready Handler
6
         rjmp  ANA_COMP       ; Analog Comparator Handler
7
         rjmp  TIM0_COMPA     ; Timer0 CompareA Handler
8
         rjmp  TIM0_COMPB     ; Timer0 CompareB Handler
9
         rjmp  WATCHDOG       ; Watchdog Interrupt Handler
10
         rjmp  ADC ; ADC Conversion Handler
Entscheide dich also, ob du den INT0 oder den PCINT benutzen willst. der 
PC interrupt reagiert auf beide Flanken, der INT0 ist programmierbar, 
auf welche Flanke er reagiert.
INT0 liegt fest auf PB1 (Pin 6).

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Matthias S. schrieb:
> Als nächstes stimmt die Vektor Tabelle nicht

Deshalb nimmt man ja auch keine Tabelle, sondern die im Datenblatt 
angegebenen Vektornamen.
Besonders einfach geht das mit folgendem Macro:

Beitrag "Re: avr asm: interrupt int0 löst bei fallender flanke nicht aus"


Generell:
Immer wenn es für etwas einen vordefinierten Namen gibt, benutzt man 
diesen und keine magischen Hexwerte oder Adressen, wo niemand mehr 
durchsieht.

von Armin A. (10110010)


Lesenswert?

Hallo,

ich werde das heute Abend mal ausprobieren.
In der Doku, die ich hatte, war die bei mir genannte Liste.
Scheine da wohl eine falsche Doku gehabt zu haben.

Wusste nicht, dass es sowas wie (1 << PCINT3) gibt.
In den Beispielen die ich gesehen habe, werfen die immer mit Hex-Angaben 
rum.
Da fand ich Binär überschaulicher.

Muss ich ein Include einbauen, damit ich sowas wie eine Intelisense habe 
für diese Hilfen wie (1 << PCINT3)?

von Michael U. (amiga)


Lesenswert?

Hallo,

man kann es auch so machen:
1
;****************************** Verktor-Liste ************************
2
3
.CSEG
4
       rjmp    Reset
5
6
.ORG  OC2addr
7
  rjmp  irq_1ms
8
9
.ORG  ICP1addr
10
  rjmp  irq_capture
11
12
.ORG  OVF0addr
13
  rjmp  irq_overflow
14
         
15
;****************************** Programm-Beginn **********************
16
17
;*********************************************************************
18
;  Initialisierungsroutine
19
;*********************************************************************
20
21
.ORG  INT_VECTORS_SIZE
22
23
; Hardware initialisieren
24
25
Reset:
26
27
...
dann muß man nur die benutzten eintragen und der Assembler weiß auch, 
wie lang die Interrupttabelle beim konkreten AVR ist.

Gruß aus Berlin
Michael

von Karl M. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Armin,

schaut man sich mal die Include Datei tn13def.inc des Atmel Assembler 
für denen Attiny13 an, so findet man sehr viele Definitionen.

Z.B. Der Abschnitt "INTERRUPT VECTORS"

Dann könnte man sich fragen, was die alle bedeuten und schaut gespannt 
in das Atmel AVR Datenblatt des Attiny13.

# http://www.atmel.com/Images/doc8126.pdf

Voila, da steht dann "alles" und vielleicht noch mehr zu den Internas 
eines Atmel AVR µC.

Hilft Dir dies weiter ?

Weiteres Basiswissen gibt es unterhalb Dokumente:

http://www.atmel.com/devices/ATTINY13A.aspx?tab=documents

# AVR Instruction Set Manual

# AVR001: Conditional Assembly and portability macros
# AVR072: Accessing 16-bit I/O Registers

von Thomas F. (igel)


Lesenswert?

Armin A. schrieb:
> Muss ich ein Include einbauen, damit ich sowas wie eine Intelisense habe
> für diese Hilfen wie (1 << PCINT3)?

Nein, das steht bereits alles fertig in der "tn13def.inc" die du im 
Atmel Studio ja sowieso schon "included" hast.

von Armin A. (10110010)


Lesenswert?

Das include fehlt bei mir.
Werde das nachziehen.

Danke

von Armin A. (10110010)


Lesenswert?

Mal ne frage.

die INC ist mehrere KB groß
der Tiny hat aber nur 1K.
Nimmt der Compiler nur das raus, was auch benötigt wird?

von Thomas F. (igel)


Lesenswert?

Armin A. schrieb:
> Das include fehlt bei mir.

Wenn man im AVR Studio ein neues Projekt anlegt wird man ja nach dem 
Controller gefragt. Danach steht in der ersten Codezeile automatisch:
1
.include "tn13def.inc"

Wenn nicht dann schreib das einfach von Hand dahin.


Armin A. schrieb:
> die INC ist mehrere KB groß
> der Tiny hat aber nur 1K.

Die Definitionsdatei wird nicht in Assembler übersetzt. Das ist nur eine 
Hilfsdatei für den AVRAssembler. Damit werden die Namen wie PCINT3 im 
Code wieder in den Binärcode (wie du ganz zu Anfangs auch verwendet 
hast) zurück übersetzt.

von Thomas F. (igel)


Lesenswert?

Kleines Beispiel:

Armin A. schrieb:
1
> OUT GIMSK, r16    ;Aktiviert Interupt INT0

Da stehen jetzt z.B. GIMSK. Der Assembler schaut jetzt in der .inc nach 
und findet:
1
.equ  GIMSK  = 0x3b

Der Assembler ersetzt jetzt GIMSK zu:
1
OUT 0x3b, r16

Fertig.

von Armin A. (10110010)


Lesenswert?

alles klar, Danke

von Rolf M. (rmagnus)


Lesenswert?

Armin A. schrieb:
> Hallo,
>
> vielen Dank für deine Antwort.
> Wollte eigentlich PB anstatt Pin schreiben.

Stimmt aber so oder so nicht, denn INT0 ist weder Pin 3, noch PB3.

> Heist das, dass ich PCINT3 aktivieren muss, damit Interupts an PB3
> gefeuert werden?

Ja. Der PCINT hat den Vorteil, dass er auf mehrere Pins reagieren kann, 
während der INT immer an einen einzelnen Pin gebunden ist. Dafür kann 
man beim INT mehr einstellen.

> Wenn ich das aber richtig verstehe, reagiert der Interupt auf jede art
> von Änderung (Steigende-, und Fallende Flanke).

Ja, richtig. Du kannst dann in der ISR den Wert des Pins auslesen, um zu 
erkennen, ob es eine steigende oder fallende Flanke war, wenn der Puls 
am Eingang nicht gerade kürzer ist als die Latenz des Interrupts.

von Armin A. (10110010)


Lesenswert?

Hallo,

habe jetzt mal weiter probiert.

Das .include macht irgendwie Probleme. Wenn ich das verwende und dann 
einmal Ausführe, meckert der über Zuordnumgen innerhalb der Datei.

Deshalb alles nochmal Binär.

Jetzt habe ich alles so eingestellt, dass Pin6 (PB1) ein Eingang ist. 
Pin 2 & 3 ein Ausgang (PB3 & 4).

Der Interrupt wird aber immer noch nicht gefeuert!

  rjmp  RESET          ; Reset Handler
    rjmp  INT0H            ; IRQ0 Handler
    RETI                 ; PCINT0 Handler
    RETI                 ; Timer0 Overflow Handler
    RETI                 ; EEPROM Ready Handler
    RETI                 ; Analog Comparator Handler
    RETI                 ; Timer0 CompareA Handler
    RETI                 ; Timer0 CompareB Handler
    RETI                 ; Watchdog Interrupt Handler
    RETI                 ; ADC Conversion Handler

RESET:
  LDI r16, low (RAMEND)
  OUT SPL, r16     ; Setzt sen StackPointer auf Anfang
  LDI r16, 0b00011000
  OUT DDRB, r16     ; Setzt Pin6->Input, Pin2->Output, Pin3->Output
  LDI r16, 0b00000010
  OUT PORTB, r16     ; PullUp
  LDI r16, 0b01000000
  OUT GIMSK, r16     ; Aktiviert Interupt INT0
  LDI r16, 0b00000011
  OUT MCUCR, r16     ; Interupt nur bei Steigender Flanke
    SEI

Loop:
  nop
  rjmp Loop

INT0H:
  CLI
  IN R15,SREG
        ... Mach was ...
  OUT SREG,R15
  SEI

  RETI

von S. Landolt (Gast)


Lesenswert?

Woran merken Sie, dass der Interrupt nicht ausgelöst wird?

(Nur am Rande: in der ISR sind cli und sei überflüssig, denn beim 
Einsprung wird cli von der Hardware ausgeführt, und reti beinhaltet 
das sei.)

von Thomas F. (igel)


Lesenswert?

Armin A. schrieb:
1
LDI r16, 0b00011000
2
OUT DDRB, r16     ; Setzt Pin6->Input, Pin2->Output, Pin3->Output

Der Kommentartext passt nicht zu den Bits.

Ansonsten sollte das Programm funktionieren.
Da du den Pull-up eingeschalten hast musst du PB1 auf Masse ziehen und 
dann wieder loslassen.

von S. Landolt (Gast)


Lesenswert?

> Der Kommentartext passt nicht zu den Bits.
Passt schon, wenn man
> Pin 2 & 3 ein Ausgang (PB3 & 4)
berücksichtigt.

von Armin A. (10110010)


Lesenswert?

Ich setze einen brakpoint unter Loop und einen unter INT0H.
Mit F10 gehe ich Zeile für Zeile durch.
Wenn ich im I/O Fenster jetzt aus Pin6 Signal gebe, müsste er doch 
eigentlich auf den 2. Breakpoint springen.
Selbst wenn ich den Pullup nicht setze kommt er nie zum INT0H.

Müsste der doch eigentlich.

Deshalb die fragte, was ich falsch mache.

von S. Landolt (Gast)


Lesenswert?

> Wenn ich im I/O Fenster jetzt aus Pin6 Signal gebe
Sollte das nicht PINB1 (==INT0) sein?

von Armin A. (10110010)


Lesenswert?

Der 2. von rechts in der Bitreihe.
Ich meinte den Physikalischen Pin.

von spess53 (Gast)


Lesenswert?

Hi

>  LDI r16, 0b00011000
>  OUT DDRB, r16     ; Setzt Pin6->Input, Pin2->Output, Pin3->Output

Setzt Pin3->Output, Pin4->Output

MfG Spess

von S. Landolt (Gast)


Lesenswert?

Das ist jetzt doppelt schlecht, ich arbeite noch mit einem steinalten 
AVR-Studio und habe keinen ATtiny13, nur einen 85. Konkret läuft Ihr 
Programm auf meinem ATtiny85 (mutatis mutandis), wie ja Thomas Forster 
auch schon schrieb, aber darüber hinaus kann ich nichts sagen, da muss 
jemand anders helfen.

von S. Landolt (Gast)


Lesenswert?

Habe ich das richtig verstanden, Sie arbeiten ausschließlich mit dem 
Simulator?
  Ich habe nun Ihr Programm in meinen, wie gesagt steinalten, 
AVR-Studio-Simulator gesteckt, und es funktioniert. Könnte es sein, dass 
Sie Ihren irgendwie falsch bedienen?
  Und wie wäre es, das Ganze konkret in Hardware aufzubauen und 
auszuprobieren, ist ja nichts Großes?

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


Lesenswert?

Armin A. schrieb:
> Mit F10 gehe ich Zeile für Zeile durch.
> Wenn ich im I/O Fenster jetzt aus Pin6 Signal gebe, müsste er doch
> eigentlich auf den 2. Breakpoint springen.
> Selbst wenn ich den Pullup nicht setze kommt er nie zum INT0H.
>
> Müsste der doch eigentlich.
>
> Deshalb die fragte, was ich falsch mache.

 Du machst nichts falsch, AVR Studio macht das für dich.
 Schmeiss den Sch... raus, baue das Ganze auf einem Breadboard auf.

 P.S.
 Natürlich feuert dein INT erst beim loslassen (ev. beim Prellen).

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

Liegt das Problem mit Ihrem Simulator vielleicht daran:
Beitrag "Re: AVR-Studio Simulation/Debugging springt nicht in ISR"
?

von Rolf M. (rmagnus)


Lesenswert?

spess53 schrieb:
> Hi
>
>>  LDI r16, 0b00011000
>>  OUT DDRB, r16     ; Setzt Pin6->Input, Pin2->Output, Pin3->Output
>
> Setzt Pin3->Output, Pin4->Output

Es setzt PB3 und PB4 als Output. Das sind Pin 2 und Pin 3.

von Armin A. (10110010)


Lesenswert?

Ha, genau das Problem ist es!
Habe jetzt "Mask interrupts while stepping" auf False gesetzt und er 
springt in den Interrupt!

Vielen Dank!

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


Lesenswert?

Armin A. schrieb:
> Das .include macht irgendwie Probleme. Wenn ich das verwende und dann
> einmal Ausführe, meckert der über Zuordnumgen innerhalb der Datei.

Eigenartig. Eigentlich sollte ein
1
; general device setup
2
; this is for the ATtiny 13
3
.NOLIST                ; Disable listfile generation 
4
.include "tn13def.inc"
5
.LIST
am Anfang der Datei bestens funktionieren. "Gänsefüsschen" nicht 
vergessen.

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.