Hallo Wissende,
wieder einmal ein Anfänger der auf dem Schlauch steht :-)
Ich habe ein Lauflicht mit 3 Schieberegistern aufgebaut.
Jede Sekunde soll eine Led aktiviert werden, sind 24 Sekunden vorbei
(24Led's leuchten)wird die Kette gelöscht und das Spiel beginnt von
vorn.
Die ungefähre Sekunde habe ich mit einer Warteschleife (dly) realisiert.
Diese "Sekunde" ist jedoch logischerweise total ungenau.
Nun möchte ich gern diese dly Schleife durch ein Timer ersetzen.
Im Code ist der Timer auskommentiert, da er nur die Neustartzeit nach
24 Led's verzögert, die jedoch unmittelbat starten soll.
Ohne Timer funktioniert es, aber eben sehr ungenau.
Hier der Code:
.include "m8def.inc"
.def temp1 = r16
.def temp2 = r17
.def temp3 = r18
.def temp4 = r19
.def cnt = r20
.def SubCount = r21
.equ SCHIEBE_DDR = DDRB
.equ SCHIEBE_PORT = PORTB
.equ RCK = PB3 ;PIN 12 , PIN 10 auf Vcc
.equ SCK = PB1 ;PIN 11
.equ SIN = PB0 ;PIN 14
.org 0x0000
rjmp main
.org OVF1addr
rjmp timer1_compare
main:
ldi temp1, LOW(RAMEND) ; Stackpointer initialisieren
out SPL, temp1
ldi temp1, HIGH(RAMEND)
out SPH, temp1
;***************************Timer initialisieren ********************
ldi temp1, high(40000) ;Vergleichswert für Timer1
out OCR1AH, temp1
ldi temp1, low(40000)
out OCR1AL, temp1 ; 4 MHz / 40.000 / 100 = 1
ldi temp1, (1 << CS10)| (1<<WGM12) ;Vorteiler=1, Timer im CTC-Modus
out TCCR1B, temp1
ldi temp1, 1 << OCIE1A ;OCIE1A: Interrupt bei Timer Compare
out TIMSK, temp1
sei
; Die Port Pins auf Ausgang konfigurieren
ldi temp1, (1<<RCK) | (1<<SCK) | (1<<SIN)
out SCHIEBE_DDR, temp1
loop:
rjmp loop
timer1_compare:
;inc SubCount
;cpi SubCount, 100
;brne end
;clr SubCount
; Ein Datenbyte ausgeben
Anfang:
ldi temp2, 255 ; Anfangsmuster laden
ldi temp3, 255
ldi temp4, 255
ldi cnt, 25 ; Schleifenzähler laden
Ausgabe:
mov temp1, temp4
rcall Schiebe ; Daten schieben
mov temp1, temp3
rcall Schiebe ; Daten schieben
mov temp1, temp2
rcall Schiebe ; Daten schieben
rcall SchiebeOut ; Daten in Ausgangsregister übernehmen
dly: ; Diese Wartefunktion soll duch ein Timerinterrupt
ersetzt werden
dec r21
brne dly
dec r22
brne dly
inc r23
cpi r23, 21
brne dly
clr r23
lsl temp2
rol temp3
rol temp4
dec cnt ; Schleifenzähler verringern
brne ausgabe
push temp1 ;temp sichern
in temp1, SREG ;sreg sichern
; Die Ausgabe im Schieberegister in das Ausgaberegister übernehmen
;
; Dazu am RCK Eingang am Schieberegister einen 0-1-0 Puls erzeugen
;
SchiebeOut:
sbi SCHIEBE_PORT, RCK
cbi SCHIEBE_PORT, RCK
ret
;-----------------------------------------------------------------------
------
;
; 8 Bits aus temp1 an das Schieberegister ausgeben
Schiebe:
push temp2
ldi temp2, 8 ; 8 Bits müssen ausgegeben werden
Schiebe_1:
rol temp1 ; MSB -> Carry
brcs Schiebe_One ; Carry gesetzt? -> weiter bei
Schiebe_One
cbi SCHIEBE_PORT, SIN ; Eine 0 ausgeben
rjmp Schiebe_Clock ; und Sprung zur Clock Puls Generierung
Schiebe_One:
sbi SCHIEBE_PORT, SIN ; Eine 1 ausgeben
; einen Impuls an SCK zur Übernahme des Bits nachschieben
Schiebe_Clock:
sbi SCHIEBE_PORT, SCK ; Clock-Ausgang auf 1 ...
cbi SCHIEBE_PORT, SCK ; und wieder zurück auf 0
dec temp2 ; Anzahl der ausgegebenen Bits
runterzählen
brne Schiebe_1 ; Wenn noch keine 8 Bits ausgegeben ->
Schleife bilden
pop temp2
ret
end:
out SREG, temp1 ;sreg wiederherstellen
pop temp1 ;temp wiederherstellen
reti
;---- Interrupt-Routine Ende
Entschuldigt bitte diesen wüsten Code.
Kann mir jemand mitteilen, wo der Timer_compare1 hinein muss?
Habe schon alle möglichen Stellen probiert, jedoch ohne Erfolg.
Vielleicht muss man so etwas auch ganz anders Programmieren?
Wäre nett, wenn mir hier weitergeholfen würde.
Gruß Peter
>Kann mir jemand mitteilen, wo der Timer_compare1 hinein muss? >.org OVF1addr > rjmp timer1_compare Na, auf jeden Fall nicht in den Overflow Interrupt. Wie wäre es mit dem timer1_compare Interrupt? >Habe schon alle möglichen Stellen probiert, jedoch ohne Erfolg. Probieren bringt bei Interrupts nicht viel. >Entschuldigt bitte diesen wüsten Code. Kein Wunder das der nicht funktioniert.
holger schrieb: >>Kann mir jemand mitteilen, wo der Timer_compare1 hinein muss? > >>.org OVF1addr >> rjmp timer1_compare > > Na, auf jeden Fall nicht in den Overflow Interrupt. > Wie wäre es mit dem timer1_compare Interrupt? Ist er ja, Interrupt wird ja ausgelöst. > >>Habe schon alle möglichen Stellen probiert, jedoch ohne Erfolg. > > Probieren bringt bei Interrupts nicht viel. Mir schon klar, deshalb wende ich mich ans Forum. > >>Entschuldigt bitte diesen wüsten Code. > > Kein Wunder das der nicht funktioniert. Der Code funktioniert doch. Ich möchte nur dly durch eine Timerfunktion ersetzen. Die dly befindet sich aber mitten im Ablauf der Schieberei. Gruß Peter
Peter Bednarz schrieb: > Der Code funktioniert doch. Ich möchte nur dly durch eine Timerfunktion > ersetzen. > Die dly befindet sich aber mitten im Ablauf der Schieberei. Deine Frage läst sich nicht mit einem einfachen "da und dort" beantworten. Du musst die ganze Programmsystematik umstellen. Bei jedem Aufruf der ISR muss 1 Schiebeoperation und nur 1 erfolgen. Die Frage ist also nicht, wie kriegst du die Pausen zwischen die Schiebeoperationen rein, sondern wie teilst du die Schiebeoperationen auf, so dass du immer nur die nächste anstehende Schiebeoperation ausführst. Und diesen Code baust du dann in die ISR ein.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.