Hallo
ich habe leider kaum Erfahrung in einer Hochsprache (weil mir nie
eingefallen ist, was ich programmieren sollte, was es nicht schon gibt).
Weil ich gerade sehr viel zeit an der Hand habe, habe ich mit Elektronik
angefangen und mich zu Mikrocontrollern vorgearbeitet. Weil die
Tutorialreihe, die ich dazu benutzte die Mikrocontroller in Assembler
programmiert, möchte ich das auch tun. Sicher werde ich danach auf C
wechseln, aber das erstmal in Assembler zu machen hilft mir sehr zum
Verständnis der Hardware und wie diese arbeitet.
Das zur Einführung, hier mein Problem:
Zum Verständnis wie ich Taster per Interrupts einbinden kann habe ich
einen einfachen Aufbau mit einem ATTiny13 zusammengesteckt:
|----Taster---- -ATTiny13 PortB1 (INT0) mit Pull-Up
Gnd
|----LED---Widerstand---- -ATTiny13 PortB0
Vcc
Dann habe ich dieses Programm geschrieben (wenn dieses gespame
unerwünscht ist, kann ich die Listings auch in ein Pastebin kopieren und
hier verlinken):
Dieses Programm funktioniert: drückt man den Taster geht die LED an,
drückt man ihn erneut geht sie aus. Ganz simpel.
Jetzt kommt mein Problem: aus Gründen bin ich auf einen ATmega8
umgestiegen. Die Schaltung habe ich folgendermaßen umgebaut:
|----Taster---- -ATmega8 PortD2 (INT0) mit Pull-Up
Gnd
|----LED--Widerstand----- -ATmega8 PortD0
Vcc
Also praktisch das Gleiche wie beim ATTiny13. Dann habe ich das Programm
entsprechend umgeschrieben (also die Registernamen geändert), die
Vektorliste erweitert und auch die Bits für den Interrupt geändert, wie
im Datenblatt das mega8 beschrieben.
Das Programm sieht nun so aus:
;------------------Reset und Interruptvariablen (fuer ATmega8!)
29
30
;.CSEG ; Assemblieren in den Flashspeicher (Code Segment)
31
.ORG 0 ; Adresse auf Null (Reset- und Interruptvektoren beginnen bei Null)
32
rjmp main ; Reset Vektor, Sprung zur Initiierung
33
rjmp int0_handler ; INT0-Int, aktiv Ext. int. request 0
34
reti ; INT1-Int, nicht aktiv Ext. int. request 1
35
reti ; Timer2-COMP, nicht aktiv Timer2 Compare Match
36
reti ; Timer2-OCF, nicht aktiv Timer2 Overflow
37
reti ; Timer1-CAPT, nicht aktiv Timer1 Capture Event
38
reti ; Timer1-COMPA, nicht aktiv Timer1 Compare Match A
39
reti ; Timer1-COMPB, nicht aktiv Timer1 Compare Match B
40
reti ; Timer1-OVF, nicht aktiv Timer1 Overflow
41
reti ; Timer0-OVF, nicht aktiv Timer0 Overflow
42
reti ; SPI, STC, nicht aktiv Serial transfer Complete
43
reti ; USART, TXC, nicht aktiv USART, Rx Complete
44
reti ; USART, UDRE, nicht aktiv USART, Data Register Empty
45
reti ; USART, TXC, nicht aktiv USART, Tx Complete
46
reti ; ADC-Int, nicht aktiv ADC Conversion Complete
47
reti ; EE_RDY, nicht aktiv EEPROM Ready
48
reti ; ANA_COMP, nicht aktiv Analog Comparator
49
reti ; TWI, nicht aktiv Two-wire Serial Interface
50
reti ; SPM_RDY, nicht aktiv Store program memory ready
51
52
;------------------Interrupt Service Routinen--------
53
54
int0_handler: ; bei Tastendruck:
55
push temp ; Das SREG in temp sichern. Vorher
56
in SREG_temp, SREG ; muss natürlich temp gesichert werden
57
58
in temp, PORTD0 ; Auslesen von PD0
59
cpi temp,0 ; ist PD0 = 0 (LED aus)?
60
breq it_is ; ja --> it_is
61
it_isnt: ; PD0 = 1, LED ist schon an
62
cbi DDRD,DDD0
63
rjmp end
64
it_is: ; PD0 = 0, LED ist aus
65
sbi DDRD,DDD0
66
end:
67
68
out SREG, SREG_temp ; Die Register SREG und temp wieder
69
pop temp ; herstellen
70
reti
71
72
;------------------Programmstart bei Reset-----------
73
74
75
main:
76
77
ldi temp, LOW(RAMEND)
78
out SPL, temp
79
ldi temp, HIGH(RAMEND)
80
out SPH, temp
81
82
ldi temp,(0<<DDD0)|(0<<DDD2)|(0<<DDD3)
83
out DDRD, temp
84
ldi temp,(1<<PD2)|(1<<PD3)
85
out PORTD,temp
86
87
; Ext. Int0
88
ldi temp,(1<<SE)|(1<<ISC01)|(1<<ISC11) ; fallende Flanke und schlafen ein
89
out MCUCR, temp
90
91
ldi temp,(1<<INT0)|(1<<INT1) ;INT0 aktivieren
92
out GICR, temp
93
sei ;Interrupts allgemein aktivieren
94
95
loop: ; Schleife zum schlafen
96
sleep
97
nop
98
rjmp loop
Das Problem: wenn ich auf den Taster drücke geht die LED an. Aber wenn
ich noch mal drauf drücke geht sie nicht mehr aus!
Wenn ich das Programm erweitere und einen zweiten Taster an INT1
anschließe kann ich die LED mit dem einen an- und dem anderen ausmachen,
also müssen die Interruptroutinen funktionieren.
Das Problem muss im Auslesen des Pins stecken. Ich bekomme aber für mein
Leben nicht heraus warum es auf dem Tiny geht und auf dem mega geht es
nicht.
Könnte mir das bitte jemand erklären oder sagen wo mein Fehler liegt?
Hallo
in temp, PORTD0 ; Auslesen von PD0 hier werden 8 Bits gelesen
cpi temp,0 ; ist PD0 = 0 (LED aus)? und verglichen
breq it_is ; ja --> it_is
it_isnt: ; PD0 = 1, LED ist schon an
cbi DDRD,DDD0 hier wird nur EIN Bit gesetzt
rjmp end oder geloscht
it_is: ; PD0 = 0, LED ist aus Anwort geht nicht !!!!
sbi DDRD,DDD0
end:
out SREG, SREG_temp ; Die Register SREG und temp wieder
pop temp ; herstellen
reti
gruß Helmar
In dem esrten Programm hast Du 2 Temp-Register (Temp und Temp2) benutzt.
In dem Programm für den Mega 8 nur TEMP. Vielleicht steht dadurch
irgendwelcher Mumpitz noch von der letzten Benutzung drin, der den
Effekt bewikt.
MfG Paul
Tip:
Das Register DDRD ist das Datenrichtungsregister des Ports D. Es legt
fest, ob der Pin als Ein- oder Ausgang benutzt wird. Zum Schalten der
Zustände eines als Ausgang definierten Pins muß ins Register PORTD
geschrieben werden ;-)