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.