Hallo, ich wollte mir ein kleines Programm schreiben, dass folgendes macht: Zählt von 90 runter (jede Sekunde wird 1 abgezogen) bis null und dann wieder von vorne. Als Ausgabe benutzte ich ein HD44780-LCD Display, als PIC hab ich einen PIC16F84A, der mit 4 MHZ getaktet ist. Die Ausgabe am Display funktioniert, jedoch zählt das Programm einfach nicht runter. Programmablauf: -Display initalisieren -Timer initalisiern -Wort "TIMER" am Display ausgeben Timer: -Interrupts auschalten -Status sichern -Bis 15 zählen (1 Sekunden) - Sekunden 1 abzeiehen (wenn null, wieder Standardwert setzten) - In einer und zehner zerteilen - Am Display ausgeben -Status wiederherstellen -Interrupts erlauben Info's zum Programm -Timer: Vorverteiler 256:1, komme auf etwa 15,2 Interrupts pro Sekunde -Ausgabe: Display sollte immer zur 9. Stelle springen -Variablen: -Sekunde - speichert die kompletten Sekunden -Zehner - speichert die Zehnerstelle der Sekunden -Einer - speichert die Einerstelle der Sekunden -HexDec: Teil das Register Sekunden in die Einer und Zehner -Display: Die Routinen sind von sprut und funktionieren auch Wäre über Hilfe dankbar! MfG Julian
Es könnte nicht schaden loops3 bei main auch einen Startwert zu geben. Sonst musst du evtl. 17 Sekunden warten bevor das erste mal runtergezählt wird. Diese beiden Zeilen in der Interruptroutine löschen bcf INTCON, GIE bsf INTCON, GIE Das hier: Int_end swapf s_copy, w ; STATUS zur�ck movwf STATUS swapf w_copy, f ; w zur�ck mit flags swapf w_copy, w bcf INTCON, T0IF ; Interrupt-Flag l�schen bsf INTCON, GIE ; enable Interrupt (macht RETFIE aber auch allein) retfie änderst du besser so: Int_end bcf INTCON, T0IF ; Interrupt-Flag l�schen swapf s_copy, w ; STATUS zur�ck movwf STATUS swapf w_copy, f ; w zur�ck mit flags swapf w_copy, w retfie
Hab den Code geändert, funzt aber trotzdem nicht (hab 1min gewartet, um zu testen, ob es evtl. an der Timerconfig liegt, ist aber nichts passiert) :(
movlw B'00001111' ; pull-up, internen Takt z�hlen, Vorteiler 256:1 movwf OPTION_REG Da liegt der Vorteiler glaube ich auf dem WDT. ;) Was kann man überhaupt auf dem Display sehen?
Auf dem Display wird immer nur "Timer" ausgegeben. Der Timer wird aber ausgelöst, wenn ich nämlich zu Anfang z.B. einfach eine 1 Ausgebe, ist direkt das ganze Display voll mit einsen. Code: [...] org 0x00 goto main org 0x04 intvec movwf w_copy ; w retten swapf STATUS, w ; STATUS retten bcf STATUS, RP0 ; Bank 0 movwf s_copy movlw '1' movwf LcdDaten call OutLcdDaten [...] Interrupts scheinen also ausgelöst zu werden. Auch die Loops3-"Schleife" (ist ja keine wirkliche Schleife) funktioniert (wenn ich da den Code zur Ausgabe ans Display setzte), nur nachdem er von den Sekunden 1 abgezogen hat, gibt es Porbleme. Er springt nämlicher dann immer zu Ende_zählen. Beispiel: Code: [...] ; Intrupt servic routine Int_serv ; Pr�fen, ob 1Sek vorbei ist decfsz loops3, F goto Int_end movlw '1' movwf LcdDaten call OutLcdDaten ; Z�hlervariable neu setzten movlw Z�hler movwf loops3 ; 1 Sekunde abziehen, wenn 0, von vorne z�hlen decfsz sekunden, F goto Ende_z�hlen movlw '2' movwf LcdDaten call OutLcdDaten [...] Ende_zählen movlw '3' movwf LcdDaten call OutLcdDaten [...] Hier erschienen nur 1 und 3 auf dem Display
>nur nachdem er von den Sekunden 1 abgezogen >hat, gibt es Porbleme. Er springt nämlicher dann immer zu Ende_zählen. > ; 1 Sekunde abziehen, wenn 0, von vorne z�hlen > decfsz sekunden, F > goto Ende_z�hlen Das hast du ja auch so programmiert ;) Über goto Ende_z�hlen springt er nur wenn sekunden 0 ist.
>Über goto Ende_z�hlen springt er nur wenn >sekunden 0 ist. Korrektur: wenn sekunden 0 wird nach dem dekrement.
Nunja, müsstest den ganzen Code lesen. Die [...] bedeuten nämlich, dass da gekürzt wurde. In wirklichkeit steht da: Ende_zählen ; Sekunden 0, deshab Wert wieder setzten movlw Max_Sekunden movwf sekunden und damit sollte sekunden wieder 90 sein (ist der Wert von Max_Sekunden z.Z.)
>Über goto Ende_z�hlen springt er nur wenn >sekunden 0 ist. Vieleicht etwas schlecht formuliert. goto Ende_z�hlen wird ausgeführt solange sekunden nicht 0 ist nach dem dekrement.
Stimme. Kleiner Denkfehler gemacht. Dürfte aber so gehen: decfsz sekunden, F goto Sekunde_NN goto Ende_zählen Sekunde_NN
Der Code funktioniert aber auch nicht :( Am Display steht nur: TIMER )( SEK
>Am Display steht nur: >TIMER )( SEK Dann funktioniert HexDec wohl nicht!
Nunja, HexDec sollte funzen, da diese Routine aus einem funktionierendem Projekt (Kurzzeittimer, ist hier im Forum) ist. Auch ändert sich die Zeichen nie, was sie ja eigentlich sollten, da die Variable sekunden stendig verringert wird.
holger wrote: >> movlw sekunden > > Was ist hier falsch? Würde mal sagen: nichs. Kommt aber darauf an, wo das steht.
>>> movlw sekunden >> Was ist hier falsch? >Würde mal sagen: nichs. Oh doch, übersetze den Befehl Bewege Konstante sekunden (0x27) nach w. Wie wäre es mit einem movwf sekunden?
Nunja, wenn ich jetzt noch wüsst, wo das steht, wäre das nicht schlecht. Hab es nur einmal hier gefunden: Code: ; Einer und Zehner berechnen movlw sekunden movwf temp call HexDec Und hier soll der Wert von sekunden nach temp kopiert werden. Stimmt doch, oder?
Oder wäre das hier richtig?: Code: ; Einer und Zehner berechnen movf sekunden, 0 movwf temp call HexDec
Nein, movlw kopiert die Adresse von Sekunden nach W also 0x27. Wenn du den Inhalt von sekunden nach W haben willst, musst du movfw schreiben. OK? Sven
Hab nochmal bei Sprut geschaut, da steht folgendes (der Befehl movfw ist gar nicht aufgeführt): MOVF Kopiere den Inhalt der Speicherzelle f nach... wenn d=0: Der Inhalt der Speicherzelle f wird in das Arbeitsregister kopiert wenn d=1 Der Inhalt der Speicherzelle wird in die selbe Speicherzelle kopiert. Es passiert also gar nichts. Allerdings kann man dadurch prüfen, ob in der Speicherzelle der Wert 0 steht, da dann das Zero-Flag gesetzt werden würde. MOVWF Kopiere den Inhalt von W in die Speicherzelle f MOVLW Kopiere einen Zahl (k) nach W Und ich will den Wert von sekunden in W haben, damit ich diesen später in temp laden kann, also schreibe ich dafür: Code: movf sekunden, w ;Inhalt von sekunden nach w kopieren movwf temp ;Inhalt von w nach temp kopieren
>MOVF >Kopiere den Inhalt der Speicherzelle f nach... Richtich der war das! Tschuldigung kenn mich mit Assembler nicht so gut aus.
Julian W. wrote: > > Und ich will den Wert von sekunden in W haben, damit ich diesen später > in temp laden kann, also schreibe ich dafür: > > Code: > movf sekunden, w ;Inhalt von sekunden nach w kopieren > movwf temp ;Inhalt von w nach temp kopieren Ja, das ist so richtig. Es gibt aber noch die Pseudo- oder auch Spezialbefehle. Unter denen befindet sich der Befehl movfw. Er macht genau das selbe wie movf blabla,w. Die Pseudobefehle kennt nur der Assembler. Er übersetzt sie in die entsprechenden "echten" Befehle. Ich nutze eigentlich nur movfw von diesen Befehlen. Die anderen eigentlich nicht. Sven
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.