Forum: Mikrocontroller und Digitale Elektronik PIC - Probleme mit Timer


von Julian W. (julian-w) Benutzerseite


Angehängte Dateien:

Lesenswert?

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

von holger (Gast)


Lesenswert?

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

von Julian W. (julian-w) Benutzerseite


Angehängte Dateien:

Lesenswert?

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) :(

von holger (Gast)


Lesenswert?

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?

von Julian W. (julian-w) Benutzerseite


Lesenswert?

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

von holger (Gast)


Lesenswert?

>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.

von holger (Gast)


Lesenswert?

>Über  goto Ende_z�hlen springt er nur wenn
>sekunden 0 ist.

Korrektur: wenn sekunden 0 wird nach dem dekrement.

von Julian W. (julian-w) Benutzerseite


Lesenswert?

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.)

von holger (Gast)


Lesenswert?

>Ü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.

von Julian W. (julian-w) Benutzerseite


Angehängte Dateien:

Lesenswert?

Stimme. Kleiner Denkfehler gemacht. Dürfte aber so gehen:

decfsz sekunden, F
goto Sekunde_NN

goto Ende_zählen

Sekunde_NN

von Julian W. (julian-w) Benutzerseite


Lesenswert?

Der Code funktioniert aber auch nicht :(

Am Display steht nur:
TIMER   )( SEK

von holger (Gast)


Lesenswert?

>Am Display steht nur:
>TIMER   )( SEK

Dann funktioniert HexDec wohl nicht!

von Julian W. (julian-w) Benutzerseite


Lesenswert?

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.

von holger (Gast)


Lesenswert?

>  movlw sekunden

Was ist hier falsch?

von Julian W. (julian-w) Benutzerseite


Lesenswert?

holger wrote:
>>  movlw sekunden
>
> Was ist hier falsch?

Würde mal sagen: nichs.
Kommt aber darauf an, wo das steht.

von holger (Gast)


Lesenswert?

>>>  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?

von Julian W. (julian-w) Benutzerseite


Lesenswert?

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?

von Julian W. (julian-w) Benutzerseite


Lesenswert?

Oder wäre das hier richtig?:

Code:
 ; Einer und Zehner berechnen
 movf sekunden, 0
 movwf temp

 call HexDec

von Sven S. (stepp64) Benutzerseite


Lesenswert?

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

von Julian W. (julian-w) Benutzerseite


Lesenswert?

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

von holger (Gast)


Lesenswert?

>MOVF
>Kopiere den Inhalt der Speicherzelle f nach...

Richtich der war das! Tschuldigung kenn mich mit Assembler
nicht so gut aus.

von Sven S. (stepp64) Benutzerseite


Lesenswert?

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
Noch kein Account? Hier anmelden.