Hallo, ich wollte ein Zeitverzögerung von circa 1 Sekunde mit dem Timer0 realisieren. Der Pic Takt liegt bei 4Mhz d.h. 1Mhz intern. Ich benutze den Vorteiler vom Teiler und zwar 256:1! Also 1Mhz:256 = 3906,25Hz Das heisst ein Takt ist 1:3906,25Hz = 256µS Also dauert ein Timerüberflow 256µSx256 = 0,066S Das heisst für 1 Sekunde müsste ich den Timer 1S:0,066S = ca. 15 mal durchlaufen lassen. Bitte korrigiert mich, wenn ich mich irre! Also ich habe es so aufgebaut: >movlw B'00000111' >movwf OPTION_REG Das geschiet in Speicherbank 0 >Zeitreset > clrf INTCON > clrf TMR0 > movlw D'15' > movfw counter >Wait > clrz > movf INTCON,0 > XORLW B'00000100' > bnz Wait > clrf INTCON > decfsz counter > goto Wait > return Ich hoffe ihr steigt durch den Kram durch =) Meine Frage ist also wo liegt hier ein Fehler?
Ich vermute mal, XORLW soll ein EX-OR machen, was willst Du damit erreichen? Mußt Du wirklich alle 8 Bits testen? Üblicher Weise nimmt man ein AND um ein bestimmtes Bit zu testen. Und überwinde mal Deine große Angst vor Kommentaren. Kommentiere Deinen Code, das hilft nämlich auch Dir selbst, ihn zu verstehen! Peter
Wenn schon ein timer, dann doch eher mit Interrupt, dann kann der Prozessor was anderes machen.
Peter Dannegger schrieb: > Ich vermute mal, XORLW soll ein EX-OR machen, was willst Du damit > erreichen? > Mußt Du wirklich alle 8 Bits testen? Üblicher Weise nimmt man ein AND um ein bestimmtes Bit zu testen. Hi, ob ich xor mache oder and.. ist doch wurscht. Aber trotzdem wäre es cool, wenn du mir zeigen könntest wie es mit and geht =) > Und überwinde mal Deine große Angst vor Kommentaren. Kommentiere Deinen > Code, das hilft nämlich auch Dir selbst, ihn zu verstehen! Ich verstehe es =) >Wenn schon ein timer, dann doch eher mit Interrupt, dann kann der >Prozessor was anderes machen. Soll er aber gar nicht. Also kann mir jemand sagen was hier falsch ist?
Nicolas Meyertöns schrieb: > Üblicher Weise nimmt man ein AND um ein bestimmtes Bit zu testen. > > Hi, ob ich xor mache oder and.. ist doch wurscht. Nicht ganz. Wenn du sicherstellen kannst, dass alle anderen Bits des getesteten tatsächlich 0 sind, dann ist es tatsächlich egal. Ansonsten nimmt man AND um sicherzugehen, dass einem nicht ein anderes Bit dazwischenfunkt. Ohne jetzt jemals PIC programmiert zu haben, würde ich mal sagen Wait clrz movf INTCON,0 ANDLW B'00000100' bz Wait Keine Ahnung, ob der OpCode tatsächlich ANDLW heist (einfach nur die Analogie zu XORLW) bzw. ob der Branch_if_zero tatsächlich bz heisst (auch hier wieder die Analogie zu bnz benutzt). Die Idee im Original war wohl solange in der Schleife zu bleiben, wie Bit 2 in INTCON gleich 0 ist. >> Und überwinde mal Deine große Angst vor Kommentaren. Kommentiere Deinen >> Code, das hilft nämlich auch Dir selbst, ihn zu verstehen! > > Ich verstehe es =) Na, dann reicht das ja auch. Blöd ist nur: Du verstehst es und findest trotzdem den Fehler nicht.
Danke für deine Antwort=) >Na, dann reicht das ja auch. >Blöd ist nur: Du verstehst es und findest trotzdem den Fehler nicht. Das ist allerdings blöd! xD >Die Idee im Original war wohl solange in der Schleife zu bleiben, >wie Bit 2 in INTCON gleich 0 ist. Genau, weil beim Timer-Overflow ja das Bit gesetzt wird, so wollte ich halt herraus finden, ob er schon 1 mal durch ist, wenn ja dann wird die 15 in "counter" um 1 verringert. Bis das irgendwann mal 0 ergibt, dann sollte er zurück springen. >Zeitreset > clrf INTCON > clrf TMR0 > movlw D'15' > movfw counter Hier soll erstmal das INTCON gelöscht werden (Mein Gedanke: so kann ich sicherstellen, dass nachher die Abfrage des Intcons kein Fehlergebniss liefert.) >Wait > clrz > movf INTCON,0 > XORLW B'00000100' > bnz Wait Hier soll er dann halt in der Schleife bleiben, bis Timeroverflow und eben entsprechend das Bit im INTCON gesetzt ist. > clrf INTCON > decfsz counter > goto Wait > return Wenn dann der Timer-Overflow da war, soll er diesen Part durchlaufen, (BNZ = Springe, wenn Z-Flag nicht gesetzt ist) also wenn das Z-Flag dann mal gesetzt ist, weil das Bit im INTCON High war, dann löscht er erstmal das INTCON Register (für die nächste runde) und verringert den Wert aus "counter" um 1. Ja aber iwie kommt er da nicht mehr raus, sprich er erreicht den Return Befehl nicht...
> clrz > movf INTCON,0 > XORLW B'00000100' > bnz Wait > Hier soll er dann halt in der Schleife bleiben, bis Timeroverflow > und eben entsprechend das Bit im INTCON gesetzt ist. Wie Karl-Heinz aber schon sagte, testet XOR nicht nur das eine Bit. Wenn auch noch irgendein anderes Bit in dem Register 1 ist, läuft die Schleife endlos.
Ich verstehe jetzt nicht so viel vom PIC, aber ist INTCON das richtige Register? Vom AVR her kenne ich das so, daß es ein Timer-Overflow bew. Compare-Register gibt. Kann aber beim PIC anders sein. Schon mal auf sprut.de nachgesehen?
Hi, ja habe es nachgelesen: "Jedes mal, wenn der Timer0 überläuft setzt er das Bit T0IF (Bit 2 im Register INTCON) auf 1" Ich versuche das ganze jetzt mit dem T0IF Interrupt. Ich melde mich später wenn ich weiter gekommen bin, danke schonmal an alle!
Stefan Ernst schrieb: >> clrz >> movf INTCON,0 >> XORLW B'00000100' >> bnz Wait > >> Hier soll er dann halt in der Schleife bleiben, bis Timeroverflow >> und eben entsprechend das Bit im INTCON gesetzt ist. > > Wie Karl-Heinz aber schon sagte, Ehre, wem Ehre gebührt. PeDa hat das aufs Tapet gebracht.
Nicolas Meyertöns schrieb: > Hi, ja habe es nachgelesen: > > "Jedes mal, wenn der Timer0 überläuft setzt er das Bit T0IF (Bit 2 im > Register INTCON) auf 1" > > Ich versuche das ganze jetzt mit dem T0IF Interrupt. > Ich melde mich später wenn ich weiter gekommen bin, danke schonmal an > alle! Du hast es immer noch nicht kapiert. Es geht nicht um das T0IF Bit. Es geht um all die anderen Bits die noch im INTCON Register untergebracht sind! Wenn auch nur eines davon auch auf 1 steht, dann geht deine XOR Geschichte in die Hose. Was ist so schwer daran, die beiden Zeilen einfach mal auszutauschen? Mag sein, dass das dein Problem nicht löst. Aber es ist auf jeden Fall die sauberere Lösung, denn mit deinem XOR schlummerte da ein Problem, dass nur darauf wartet hervorzukommen.
Hey, klar hab ich das kapiert, deswegen will ich es ja jetzt auch mit dem Interrupt machen! Sprich, XOR ist ganz raus! --> So brauche ich überhaupt gar nicht mehr ständig fragen ob sich der Zustand T0IF auf High geändert hat auch nicht mit AND!
Du hast irgendwie nix kapiert. Interrupt ist doch ne ganz andere Liga. Da kannst Du mit Deinem fundamentalen Wissen noch wesentlich mehr falsch machen. Was ist so schwierig den XOR gegen einen AND-Befehl zu tauschen? Diese Antwort bleibst Du Dir selbst wohl schuldig.
Nicolas Meyertöns schrieb: > Hey, klar hab ich das kapiert, deswegen will ich es ja jetzt auch mit > dem Interrupt machen! Den logischen Spring versteh ich jetzt nicht wirklich. Das ganze über einen tatsächlichen Interrupt abzuhandeln ist zwar grundsätzlich die bessere Lösung. Wenns aber mit Polling schon nicht funktioniert, wird dir ein Interrupt Handler auch nicht helfen. Es ist nur etwas komplizierter einen Imterrupt Handler aufzusetzen und man kann mehr falsch machen. > So brauche ich überhaupt gar nicht mehr ständig fragen ob sich der > Zustand T0IF auf High geändert hat auch nicht mit AND! Wenn du dir von einem Interrupt Handler dadurch einfacheren Code erwartest, muss ich dich leider enttäuschen. Denn letzten Endes kann dein Interrupt Handler auch nur irgendwo ein Bit setzen, dass die Zeit abgelaufen ist. Und rate mal, was die Hauptschleife in der Zwischenzeit machen wird? Warten und testen ob das Bit schon gesetzt ist :-) Also irgendwer muss auf jeden Fall warten, ob ein Bit gesetzt wird, egal wie man es dreht und wendet. Und um das zu testende Bit zu isolieren benutzt man einen AND und keinen XOR.
Hi, ja ok ich sehe es ein. Ich habe es durch ANDLW getauscht, das hat aber leider auch nicht geholfen... Das mit dem Interupt interessiert mich dann aber doch noch.. Was sagst du/ihr dazu: Sobald, aus dem Hauptprogramm ins UP gesprungen wird (call): ;•••••••••••••••••••••••••••••••••••••••• Zeitreset ;•••••••••••••••••••••••••••••••••••••••• movlw D'15' movfw counter movlw B'00000111' movwf OPTION_REG movlw B'10100000' movwf INTCON Hier soll dann halt die 15 in counter geschrieben werden, damit er 15 Timer-Overflows verweilt sage ich jetzt mal. Dann die Einstellungen für den Timer. Und anschließend noch, das Interupts genrell erlaubt sind und, dass mein Interupt erlaubt ist Timer-Overflow. Dann geht es im Quellcode direkt hiermit weiter: ;•••••••••••••••••••••••••••••••••••••••• Wait ;•••••••••••••••••••••••••••••••••••••••• tstf counter btfss STATUS,Z goto Wait return Hier fragt er im Grunde die ganze Zeit immer nur ab ob in counter schon eine 0 steht, wenn ja, dann wird der return ausgeführt (also zurück in das Hauptprogramm). Hier verweilt er also bis in counter eine "0" steht. Das soll mit dem Interupts passieren: ORG 0x04 movlw B'10100000' movwf INTCON decf counter RETFIE Also: ORG 0x04 weil ja hier die Interuptsroutine anfängt. Dann muss als erstes das T0IF wieder auf 0 gesetzt werden, weil er sonst nach dem Interupt direkt wieder rein springt. Und dann wird halt counter um 1 verringert und anschließend durch den RETFIE Befehl zurück zum Programm wo durch den Interupt unterbrochen wurde dadurch wird auch autom das GIE wieder gesetzt. Das muss dann eben 15 mal passieren, damit in counter eine 0 steht und er wieder zurück in das Hauptprogramm kommt. Bitte nicht wieder so agresive reagieren ich will nur lernen :/
Okay, nochmal vielen Dank an alle! Ich hab es jetzt mit dem Interupt geschafft.
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.