PIC - Probleme mit Timer

Persönliche Seite #1015492
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
Angehängte Dateien:
Gast #1015529
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
Persönliche Seite #1015617
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
Gast #1015626
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.
Persönliche Seite #1015700
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
Persönliche Seite #1015704
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren