Archiv verlassen und diese Seite im Standarddesign anzeigen : Wieder ein LED-Blinker
shemazai
09.12.2004, 00:58
Hallo !
Habe mich durch zig andere Varianten von "LED-Blinker-mit-Timer-Interrupts" gelesen und kann den Fehler in meiner nicht entdecken... hat jemand ein Stichwort für mich ?
Das Problem: Statt dem erwarteten Verhalten (LED für ca. 1 Sek. ein, dann für ca. 1 Sek. aus), blitzt die LED in Abständen von ca. 1 Sek kurz auf. Warum ??
.include "m8def.inc"
.org 0x000
rjmp main
.org 0x008
rjmp TimerHandler
main: ldi r16,0xFF ; PortB ist Output
out DDRB, r16
ldi r16,0b00000100 ; Overflow Interrupt Enable
out TIMSK, r16
ldi r16,0b00000011 ; Timer div. 1/64
out TCCR1B, r16
ldi r16,0b00000000
out PORTB, r16
sei
loop: rjmp loop
TimerHandler: in r16,PORTB; Aktuellen Zustand von PORTB einlesen
sbrc r16,0; sind die LEDs gerade aus ?Dann Einschalten, sonst...
rjmp Ausschalten; ausschalten...
ldi r16,0b00000111
out PORTB,r16
rjmp Ende
Ausschalten: ldi r16,0b00000000
out PORTB,r16
Ende: reti
[/code]
Hallo,
ich schätze das Problem liegt in der Anweisung
"in r16, PORTB"
hier liest du nicht den Ausgangs-Portzustand,
sondern den Pegel der Pins am Chip.
Je nachdem, wie die externe Beschaltung mit der LED ist,
kann der Pegel dort nicht mehr eindeutig 1 oder 0 sein,
so wie du es ausgegeben hast.
Wenn z.B eine LED direkt am Port-Pin nach GND angeschlossen ist.
So leuchtet diese bei PORT=1,
aber die Spannnung am PIN bricht zusammen,
und der Pegel ist nur ca. 1-2 je nach LED.
Wenn man das per IN-Anweisung liest, ist das 0 und nicht 1.
Versuche mal, den Zustand in einem Register festzuhalten.
Gruß Jan
shemazai
09.12.2004, 19:37
Hallo !
Danke erstmal für die Antwort!
Hab' deinen Vorschlag entsprechend umgesetzt und das Programm dabei etwas vereinfacht, sieht jetzt so aus:
.include "m8def.inc"
.org 0x000
rjmp main
.org 0x008
rjmp TimerHandler
main: ldi r16,0xFF ; PortB ist Output
out DDRB, r16
ldi r16,0b00000011 ; Timer div. 1/64
out TCCR1B, r16
ldi r16,0b00000100 ; Overflow Interrupt Enable
out TIMSK, r16
ldi r16,0b00000000 ; Alle LEDs aus.
out PORTB, r16
sei
loop: rjmp loop
TimerHandler: com r16
out PORTB,r16
Ende: reti
Interessanterweise zeigt die Schaltung exakt dasselbe Verhalten wie vorher.
(Habe auch Varianten ausprobiert, bei denen der Zustand in einem anderen Register verwaltet wird, ebenfalls das gleiche Verhalten.)
An Pin 14 hängt ein 100 Ohm - Widerstand, daran die LED an Masse. Den Pin einfach nur eingeschaltet lassen funktioniert.
Ich vermute fast, daß schlicht *zwei* Interrupts kurz hintereinander generiert werden, könnte das sein ?
Grüße!
Alex
shemazai
09.12.2004, 20:40
Lösung gefunden !
Das Problem war schlicht, daß kein Stack initialisiert, jedoch (bei den Interrupts) benutzt wurde.
Fertiges Programm läuft und sieht so aus:
.include "m8def.inc"
.org 0x000
rjmp main
reti
reti
reti
reti
reti
reti
reti
.org 0x008
rjmp TimerHandler
main: ldi r16, LOW(RAMEND)
out SPL, r16
ldi r16, HIGH(RAMEND)
out SPH, r16
ldi r16,0xFF ; PortB ist Output
out DDRC, r16
ldi r16,0b00000011 ; Timer div. 1/64
out TCCR1B, r16
ldi r16,0b00000100 ; Overflow Interrupt Enable
out TIMSK, r16
ldi r16,0b00000000 ; Alle LEDs aus.
out PORTC, r16
sei
loop: rjmp loop
TimerHandler: com r16
out PORTC,r16
Ende: reti
Hi Alex,
Ich vermute fast, daß schlicht *zwei* Interrupts kurz hintereinander generiert werden, könnte das sein ?
Ja, könnte sein, zumal ich in deinem Code
das Setzen des eigentlichen Timerregisters vermisse.
bei mir sieht das so aus:
Ausschnitt aus einem Programm für ATTiny15L
.DEF mp = R16
.DEF timeval = R12
init: ...
ldi mp,0-30 ;0- weil der timer vorwärts zählt
mov timeval,mp ;timerwert (ca. 25 us)
ldi mp,1 ;timer0 Vorteiler auf 1
out tccr0,mp ;timer0 control
ldi mp,2 ;timer0 int enable
out timsk,mp ;timer int mask
out tcnt0,timeval ;timer setzen
...
;Timer0 interrupthandler
Timer0Int:
out tcnt0,timeval ;timer wieder setzen
...
reti
Das timerregister tcnt0 zählt vorwärts (!) bis zum Überlauf,
der dann den Interrupt auslöst.
In der Interruptroutine muss dann sofort das Timerregister
wieder besetzt werden, damit das Timing stimmt.
Aber eigentlich müsste es bei dir auch funktionieren,
da müsste das Timeregister eben einmal "ganz rum" zählen.
Deshalb hab ich das bisher nicht erwähnt.
Aber probier halt mal...
Gruß Jan
Ahh. ich sehe gerade, du hast es schon gelöst.
Da haben wir uns "überschnitten"
Also dann Viel Spaß noch....
Jan
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.