Forum: Mikrocontroller und Digitale Elektronik Interrupt beim AVR


von Oilaf (Gast)


Lesenswert?

Hallo,
ich versuche mich gerade daran einen Interrupt (INT0) auszulösen.
Mit dem Beispielprogramm aus dem "AVR-Tutorial interrupts" komme ich in 
dem AVR Studio 3.56 aber nicht ganz klar. Nach dem Assemblieren versuche 
ich den Interrupt in einem IO-Fenster Port D 0x12 Portpin PD2 von Hand 
auszulösen, aber nichts passiert. Erst wenn im DDRD 0x11 den DDD2 auf 1 
setze klappt das auslösen von Hand nur dass dann ja der PD2 als Ausgang 
geschaltet ist. So ungefähr verhält sich auch meine Schaltung da 
allerdings mit einem AT90S2313.
Für einen Tipp was ich falsch mache, wäre ich dankbar.

Gruß Olaf

von Stefan B. (stefan) Benutzerseite


Lesenswert?

AVR Studio 3.56 ist schon eine Zeit lang abgehangen und ich könnte das 
nur mit einem neueren AVR Studio testen (4.12 oder 4.13). Hängst du 
trotzdem mal deinen Quelltext an?

von Oilaf (Gast)


Angehängte Dateien:

Lesenswert?

Es ist eigentlich ähnlich gemacht, wie im "AVR-Tutorial interrupts".
das Verhalten ist bei beiden Quelltexten gleich.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

So hat etwas länger gedauert.

Ich hatte zuerst das falsche Target (Attiny2313 statt AT90S2313) und ein 
paar Probleme mit dem AVR Studio Simulator bis ich begriffen hatte wie 
und wann man PIND2 ändern darf (im Break).

Dein Programm habe ich auf das wesentliche (INT0-Demo) abgespeckt.
1
; ################
2
; ### Includes ###
3
; ################
4
.include "2313def.inc"
5
; TARGET = AT90S2313
6
7
; ####################
8
; ### Definitionen ###
9
; ####################
10
.def    temp    =r16
11
12
; #####################
13
; ### Vektortabelle ###
14
; #####################
15
.org 0x0000
16
         rjmp  main         ; Reset Handler
17
.org INT0addr
18
         rjmp  INT0_Handler  ; IRQ0 Handler
19
20
; #####################
21
; ### Hauptprogramm ###
22
; #####################
23
main:
24
    ; ########################
25
    ; ### Stack einrichten ###
26
    ; ########################
27
  ldi  temp, RAMEND
28
  out  SPL, temp
29
         
30
    ; #############################
31
    ; ### Interrupts einstellen ###
32
    ; #############################
33
34
    ; ISC01 (1<<1) 1 und ISC00 (1<<0) 0 
35
    ; => FALLENDE Flanke von INT0 erzeugt Interrupt
36
  ldi  temp, 0b00000010
37
;  ldi  temp, 0b00000000  ; altern.: LOW an PD2 gibt INT0
38
  out  MCUCR, temp
39
40
  ldi  temp, 0b01000000  ; INT0 (1<<6) an PD2 zulassen
41
  out  GIMSK, temp
42
43
  sei        ; Interrupts allgemein aktivieren
44
  
45
    ; #######################
46
    ; ### Arbeitsschleife ###
47
    ; #######################
48
loop:
49
  rjmp  loop       ; loop forever
50
51
; ########################
52
; ### Interrupthandler ###
53
; ########################
54
    ; ############
55
    ; ### Int0 ###
56
    ; ############
57
INT0_Handler:
58
  push  temp
59
  in  temp,sreg
60
  ; hier Nutzcode einfügen
61
  out  sreg,temp
62
  pop  temp
63
  reti
64
65
; Simulation in AVR Studio
66
;
67
; Der Interrupt bei fallender Flanke tritt auf, 
68
; wenn PIND2 auf HIGH gesetzt war und im Break 
69
; auf LOW gesetzt wird.
70
;
71
; 1/ Breakpoint auf "push temp" in INT0_Handler
72
; 2/ Run (F5)
73
; 3/ Break (Strg-F5)
74
; 4/ PIND2 ändern in Fenster I/O-View
75
; 1/ ...
76
;
77
; ENDE

von Oilaf (Gast)


Lesenswert?

Hallo Stefan,
vielen Dank für Deine Hilfe, aber mein eigentliches Problem ist offenbar 
nicht ganz deutlich geworden, ich habe mich wohl missverständlich 
ausgerückt. Das Problem besteht weniger darin, dass ich mit der 
Konfiguration des Interuts oder des Simulators nicht klar komme. Der 
Portpin scheint das Problem zu sein.
Konfiguriere ich ihn als Eingang
  ldi  temp, 0b11111011
  out  DDRD, temp
dann reagiert er nicht, weder im Simulator noch in der Schaltung.
Konfiguriere ich ihn als Ausgang
  ldi  temp, 0b11111111
  out  DDRD, temp
dann funktioniert es zwar im Simulator, aber in der Schaltung bedeutet 
das für den angeschlossenen Temperatursensor SMT 160-30 quasie ein 
Kurzschluss und ein Interrupt wird schon gar nicht ausgelöst.
Ich habe schon alles (mir) mögliche ausprobiert, aber alles ohne Erfolg.

Gruß Olaf

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Der Simulator kann keine externen Ereignisse erkennen, die must Du also 
manuell auslösen. Die Hardware in Deinem Fall wird nur funktionieren, 
wenn der Interruptpin als Eingang geschaltet ist. Warum probierst Du das 
Programm nicht auf dem Controller selbst? Schalte in der 
Interruptservice-Routine eine LED an / aus.

von Oilaf (Gast)


Lesenswert?

ja richtig alle Deine Vorschläge habe ich schon ausprobiert, ohne 
Erfolg. Wenn ich Port D Pin 2 (0x12 bit 2), bei auf Eingang (0x11 bit 2 
auf 0) konfigurierten DDRD, im Simulator hin und her schalte wird kein 
Interrupt ausgelöst. Die Sache mit der LED im INT0_Handler habe ich auch 
schon probiert, es verhält sich wie oben beschrieben.

Gruß Olaf

von Hannes L. (hannes)


Lesenswert?

Ich kenne zwar Deinen Sensor nicht, vermute aber, dass er einen 
open-Collector (open-Drain)-Ausgang hat, da brauchst Du einen 
PullUp-Widerstand. Oder bringt der Sensor selbst L- und H-Pegel?

Wenn Du den internen PullUp nutzen willst, dann muss DDR auf 0 (Eingang) 
und PORT auf 1 (PullUp ein).

...

von Oilaf (Gast)


Angehängte Dateien:

Lesenswert?

Ich hatte auch schon einen Schalter am PD2 angeschlossen, aber der 
SMT160 ist TTL/CMOS- kompatibel. Ich verstehe das nicht, es ist ja 
letzlich die gleiche Situation wie im AVR-Tutorial interrupts, das haben 
doch bestimmt schon viele Leute ausprobiert. Also muss der Fehler doch 
in meinem Aufbau/Programm liegen.

Gruß Olaf

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Abgesehen davon, Du benutzt einen Tiny2313, richtig? Nicht etwa einen 
90S2313? Noch ein Gedanke: der Sensor spuckt eine Rechteckfrequenz mit 
variablem Tastverhältnis aus. Wäre es in dem Fall nicht besser, den 
Input Capture Interrupt zu benutzen? Das würde die Zeitmessung erheblich 
vereinfachen.

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Noch etwas: es hat sich allgemeinhin als sinnvoll erwiesen, eine 
komplette Interrupt-Vektorentabelle an den Anfang des Codes zu stellen 
(anstatt einzelner .org-Segmente) und das eigentliche Programm immer 
nach den Interruptvektoren anfangen zu lassen. Somit können 
versehentlich aktivierte und ausgelöste Interrupts abgefangen werden, 
die ansonsten ein Chaos beim Einspringen in durch Programmcode belegte 
Vektoren anrichten könnten.

von Oilaf (Gast)


Lesenswert?

Doch es ist der 90S2313 gibt es mit dem ein Problem?
Natürlich kann ich das auch anders machen, das werde ich auch sicher 
irgendwann, wenn ich mich erst mal richtig in die AVR´s eingearbeitet 
habe.
Aber ich werde sicher wieder auf das Problem stoßen einen Interrupt 
auslösen zu müssen, und dann fange ich wieder an dieser Stelle an. Das 
ist sicher auch ein persönliches Problem, wenn ich mich erst mal an 
einer Sache festgebissen habe, dann kann ich nicht mehr loslassen.

Gruß Olaf

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Das kenne ich. Nein es gibt keine Probleme mit dem 90S2313, zumindest 
dort nicht. Es sollte gehen. Allerdings solltest Du das temp, in das Du 
das SREG gesichert hast, noch auf den Stack schreiben, sonst kannst Du 
es in der gesamten ISR nicht mehr verwenden. Hast Du denn jetzt auf dem 
Controller von Hand schon einen Interrupt ausgelöst? Wie sieht die 
Portregisterdefinition aus? Poste doch mal das Gesamtprogramm!

von Oilaf (Gast)


Angehängte Dateien:

Lesenswert?

Nein, das ist ja das Problem, ich kriege den Interrupt nicht ausgelöst. 
An dem Quellcode habe ich noch nichts geändert (Posting gestern 16:08). 
Zur Sicherheit habe ich noch mal den eigentlich bekanntetn Schaltplan 
dran gehängt, den SMT160 bzw. einen Schalter gegen Masse mit PullUp kann 
man sich sicher leicht dazudenken.
Hilfreich wäre ja auch ein Projekt, in dem die Sache mit einem Interrupt 
in der AVR-Basicline schon mal umgesetzt wurde und nachweislich 
funktioniert hat, ich habe noch nichts passendes gefunden.

Gruß Olaf

von Hannes L. (hannes)


Lesenswert?

Ich hatte mir Dein Programm gestern schonmal kurz angesehen, hatte es 
aber gleich wieder geschlossen, weil es sehr schwer lesbar ist. Da 
passen die Kommentare nicht zu dem Code, da werden Bits nicht beim Namen 
genannt, sondern als kryptische Binärzahlen. Da fehlte mir echt die 
Lust, wegen jedem Bit im Datenblatt nachzuschauen, was denn nun gemeint 
ist. Dazu kommt dann noch die Art der Interrupt-Vektoren und der 
unverständliche Unsinn in der Mainloop. Da aber zur Zeit einige Leute 
darüber meckern, wie hier Anfänger behandelt werden, habe ich mich mit 
der Kritik erstmal zurückgehalten.

Du fragst nach einem Programmcode, der im 2313 mit externem Interrupt 
arbeitet. Hier ist einer, der macht aber nicht das, was Du brauchst:
http://www.hanneslux.de/avr/mobau/impdecoder/idec2313.asm
Die Beschreibung dazu ist hier:
http://www.hanneslux.de/avr/mobau/impdecoder/idec.html

Nun zur Aufgabe, die Du erledigen willst...
Du willst eine Impulsbreite mit einem externen Interrupt messen, also 
ein Software-ICP.
Du hast in Deinem Programmentwurf in Main Int0 auf fallende Flanke 
eingestellt (MCUCR). Um eine Impulsbreite zu messen, brauchst Du aber 
beide Flanken. Du musst in der ISR die Flanke umschalten.

Hier ist eine Impulsbreitenmessung mit ext.-Int für Tiny15:
http://www.hanneslux.de/avr/mobau/fr_t15/T15frb01.asm
mit Beschreibung http://www.hanneslux.de/avr/mobau/fr_t15/fr_t15.html
und hier http://www.hanneslux.de/avr/index.html noch ein paar andere 
Beispiele.
Hier http://www.hanneslux.de/avr/pollin_ir8/index.html findest Du eine 
Impulsbreitenmessung im Tiny2313, die mit ext.-Int arbeitet. Da ist auch 
zu sehen, wie ich jetzt die Int-Vektoren anordne.

Zum Analysieren Deines Quelltextes bis ins Detail fehlt mir aufgrund der 
kryptischen Bitnamen immernoch die Lust, sorry.

...

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Der Interrupt funktioniert mit Sicherheit. Hast Du den Spannungswechsel 
an PD2 mal mit einem Multimeter gemessen, ob Du tatsächlich Low 
erreichst?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

@ Oilaf

Was du mit DDRD rummachst, verstehe ich nicht.

Hier die Erweiterung zum Toggeln der LED an PB0 aus deinem Schaltbild, 
wenn ein INT0 (Fallende Flanke: PD2 wechselt von HIGH auf LOW) auftritt.
1
; ################
2
; ### Includes ###
3
; ################
4
.include "2313def.inc"
5
; TARGET = AT90S2313
6
7
; ####################
8
; ### Definitionen ###
9
; ####################
10
.def    temp    =r16
11
.def    temp2   =r17
12
13
; #####################
14
; ### Vektortabelle ###
15
; #####################
16
.org 0x0000
17
         rjmp  main           ; Reset Handler
18
.org INT0addr
19
         rjmp  INT0_Handler  ; IRQ0 Handler
20
21
; #####################
22
; ### Hauptprogramm ###
23
; #####################
24
main:
25
    ; ########################
26
    ; ### Stack einrichten ###
27
    ; ########################
28
  ldi  temp, RAMEND
29
  out  SPL, temp
30
31
    ; ############################################
32
    ; ### LOW ACTIVE LED an PB0 initialisieren ###
33
    ; ############################################
34
    ; Toggelt später in INT0_Handler
35
  ldi  temp, 0b00000000  ; PB0 LOW (LED_AN)
36
  out  PORTB, temp
37
  ldi  temp, 0b00000001  ; PB0 Ausgang
38
  out  DDRB, temp
39
         
40
    ; #############################
41
    ; ### Interrupts einstellen ###
42
    ; #############################
43
44
    ; ISC01 (1<<1) 1 und ISC00 (1<<0) 0 
45
    ; => FALLENDE Flanke von INT0 erzeugt Interrupt
46
  ldi  temp, 0b00000010
47
  ;  ldi  temp, 0b00000000  ; altern.: LOW an PD2 gibt INT0
48
  out  MCUCR, temp
49
50
  ldi  temp, 0b01000000  ; INT0 (1<<6) an PD2 zulassen
51
  out  GIMSK, temp
52
53
  sei            ; Interrupts allgemein aktivieren
54
  
55
    ; #######################
56
    ; ### Arbeitsschleife ###
57
    ; #######################
58
loop:
59
  rjmp loop       ; loop forever
60
61
; ########################
62
; ### Interrupthandler ###
63
; ########################
64
    ; ############
65
    ; ### Int0 ###
66
    ; ############
67
INT0_Handler:
68
  push temp
69
  in   temp,sreg
70
  ; Anfang Nutzcode
71
  ; => PB0 toggeln
72
  push temp
73
  push temp2
74
  ldi  temp2, 0b00000001
75
  in   temp, PORTB
76
  eor  temp, temp2
77
  out  PORTB, temp
78
  pop  temp2
79
  pop  temp
80
  ; Ende Nutzcode
81
  out  sreg,temp
82
  pop  temp
83
  reti
84
85
; Simulation in AVR Studio
86
;
87
; !/ Keine Breakpoints
88
; 2/ Auto-Step (ALT-F5)
89
; 3/ PIND2 manipulieren und PORTB0 beobachten
90
;    PORTB0 toggelt, wenn PIND2 von HIGH => LOW wechselt
91
;.
92
; ENDE


Anschluss eines Schalters an PD2:
1
   ^ Vcc +5V
2
   |
3
   |
4
  +-+
5
  | | Pull-Up
6
  | | 10K
7
  +-+
8
   |
9
   |
10
   +--------+ PD2
11
   |
12
   |  |
13
 L +  + H (bei PD2)
14
      /
15
     /
16
    /  Schalter
17
   +
18
   |
19
   |
20
  --- GND

von Oilaf (Gast)


Lesenswert?

Erstmal vielen Dank für die Hilfe, ich will Euch auch nicht zu sehr 
nerven.
@ Hannes Lux,
da gebe ich Dir Recht, übersichtlich ist der Quelltext nicht gerade. Das 
liegt daran, dass ich in den Programmen immer viel ausprobiere und nach 
dem Ausprobieren nicht immer alles lösche. Ich habe sicher nicht so 
einen ganz profesionellen Programmierstil. Ich werde mir Deine Beispiele 
mal in Ruhe ansehen. Vielen Dank

@ Travel Rec.Ich schwöre, mit Oszilloskop direkt am Beinchen gemessen.

@ Stefan, ich probier deinen Quellcod nochmal aus, merkwürdig finde ich 
nur, dass das Verhalten im Simulator (AVR Studio 3.56) das Verhalten in 
der Hardware wiederspiegelt.

Gruß Olaf

von Hannes L. (hannes)


Lesenswert?

AVR-Studio 3.5x nimmt Niemand mehr, Du solltest aus Gründen der 
Kompatiblität mit den Helfenden auf AVR-Studio 4.xx updaten. Es muss ja 
nicht immer die allerneueste Version sein, aber zwischen 3.5x und 4.xx 
hat sich allerhand geändert.

...

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.