Forum: Mikrocontroller und Digitale Elektronik PIC 16F Externer Takt zählt falsch


von Gernot s. H. (picbier)


Angehängte Dateien:

Lesenswert?

Hallo! Bin neu hier.
Also ich bin neu in die Thematik eingestiegen. Finde alles auch super 
spannend. Aber jetzt bin ich inzwischen ratlos.
Ich versuche mir meinen eigenen Frequenzzähler zu bauen.
Ich weiß, es gibt fertige Lösungen aber ich will es selber probieren.
Ich arbeite mit MPLAB und momentan mit dem PIC16F876A, 4 MHz.
Mein Programm "soll" so arbeiten:
Mit Timer2 und einem 8 bit Register (0x20) lasse ich eine Schleife 1 
Sekunde
lang rattern. Meine Konfig für TMR2 sieht so aus:
PRE = 16, POST = 10, PR2 = 249
Damit möchte ich bis zum Interrupt 40 mS verzögern. Wenn PIR, 1 gesetzt 
ist dann inkrementiere ich 0x20 welches ich mit 231 vorgeladen habe.
Theoretisch müsste ich dann bis zum Überlauf in 0x20 25 "Runden" diese 
40 mS verzögern. Das wären dann nach meiner Rechnung 1000 mS und damit 1 
Sekunde.

Nebenher ist mein Timer1 so konfiguriert dass es an RC0 jedesmal 
incrementiert wenn ein high Pegel kommt.
Das tut der auch.

Ich simuliere momentan die Eingangssignale an RC0 mit MPLAB.
Dazu habe ich mit STIMULUS unter der Registerkarte PIN / Register 
Actions
als Signal RC0 ausgewählt, Time Units sind Cyc und dann in die Time 
Tabelle
200 | 1, 400 | 2 ... bis 1200 | 0 eingetragen. Dann habe ich noch Repeat 
after 1 dec angeklickt.

Wenn ich jetzt mein Proggi laufen lasse stht im Timr1 Register 11998.
Es müsste doch aber nur 2500 sein?

Ich habe inzwischen keine neuen Ideen mehr.
Ich hoffe ihr könnt meinen Code entziffern.
Wäre super nett wenn ihr euch die Mühe machen könntet mir zu helfen.

PICBier

von Gernot s. H. (picbier)


Lesenswert?

Hat niemand eine Idee?

PICBier

von Jens (Gast)


Lesenswert?

So ein chaotisches Programm habe ich noch nicht gesehen. Durch die 
komischen Macro-Definitionen total unübersichtlich. Außerdem kann ich 
nicht erkennen, wo deine Interuptroutine beginnt. Register werden 
offenbar auch keine gerettet.

Schaue dir mal www.sprut.de an und versuche es dann noch mal...

von Gernot s. H. (picbier)


Lesenswert?

Hallo.
Sprut kenne ich schon. Ist genial die Seite.

Wieso komische Macro-Definitionen?
Ich hab doch nur das Bankumschalten als Makro definiert.
Andere Makros habe ich doch gar nicht.
Interrupt verwende ich auch nicht darum habe ich auch keine 
Interruptroutine mit einprogramiert und die Timer setzen zwar ein 
Interruptbit aber es wird nicht in die Interruptroutine gesprungen.
Warum soll ich denn Register retten?
Bei der Interruptbehandlung ist mir das klar aber doch so bei diesem 
Code nicht. Oder doch? Wie gesagt ich bin Anfänger und lerne gerne etwas 
dazu.
Aber nun zu dem Problem. Das wäre meine Hauptschleife. Ich hoffe man 
kann diese besser entziffern.
1
;Hauptprogramm
2
main
3
4
;Timer1 anschalten
5
bsf T1CON, 0
6
;Timer2 anschalten
7
bsf T2CON, 2
8
9
bcf PIR1, 1 ;Interrupt von Timer2 zurücksetzen
10
btfss PIR1, 1 ;Wenn Timer2 überläuft dann springen und ...
11
goto $ - d'1'
12
incfsz 0x21, 1 ;erhöhe Register 0x21. Wenn dieses überläuft, dann springe
13
goto $ - d'4'
14
15
;Messung beendet also Timer ausschalten
16
bcf T1CON, 0 ;Timer 1 aus
17
bcf T2CON, 2 ;Timer 2 aus
18
19
bcf STATUS, 2 ;Überlauf zurücksetzen
20
bcf PIR1, 1 ;Interrupt von Timer2 zurücksetzen
21
movlw d'231' ;Register neu beladen
22
movwf 0x21 
23
24
goto main

Trotzdem danke.

PICBier

von Sebastian H. (sebihepp)


Lesenswert?

Benutze für Sprünge bitte Sprungmarken.
Erstens wird der Code besser lesbar und zweitens hat MPLAB bei
mir nach Sprüngen ein nop eingesetzt. Warum MPLAB das gemacht hat
weiss ich nicht, ich denke aber es hängt mit damit zusammen, dass
Sprünge 2 Zyklen benötigen und einer somit wegfällt.

Und versuche mal folgende Einstellungen bei Stimulus:
Time Units: us
Repeat after: 1000 dec
Restart at: 0 dec
Werte: 0 | 0, 500 | 1

Dann sollte in Timer1 genau 1000 stehen.

von Gernot s. H. (picbier)


Lesenswert?

Hallo!
Danke für die Mühe!
Ok, werd ich mir merken. Ich kann es aber besser lesen, wenn ich gerade 
für
sowas wie
btfss xyz
goto $ - 1
keine Sprungmarke verwende.
Ja goto´s brauchen 2 Zyklen. Ich habe auch herausgefunden, dass btfss 
auch 2 Zyklen benötigt wenn es den nächsten Befehl überspringt.
Ansonsten nur ein Zyklus.

Mein Timer zeigt jetzt 2667 an ???
Ich glaube das Problem liegt darin, dass ich zu viele Befehle brauche 
bis das Interruptbit von Timer 2 erneut abgefragt wird.
Komisch, dass mein Timer ja nicht einmal im groben den richitgen Wert 
anzeigt. Also muss ich mir nochmal komplett was neues überlegen.

Zu dem wegfallen nochmal: Was meinst du damit genau?
Ein Sprung kostet doch immer 2 Zyklen. Egal ob Sprungmarke oder die
$ - xyz Version?

Danke nochmals.

PICBier

von Sebastian H. (sebihepp)


Lesenswert?

Das mit dem "wegfallen"... das Wort ist falsch gewählt.
Die PICs basieren auf einer 2 stufigen Pipeline, wobei jeder
Pipelineschritt nochmal 4 Takte braucht. Im Normalfall braucht einen
das nicht zu interessieren. Der PIC sorgt dafür, dass alles glatt läuft.
Aber der ProgrammCounter wird bei einem Sprung erst im zweiten Schritt
beschrieben. Also muss der Befehl direkt nach dem Sprung verworfen
werden. Wie gesagt macht das eigentlich der PIC selber. Aber MPLAB
setzt nach jedem goto ein nop. Zumindest hat mir das der Disassembler
angezeigt. Dadurch musst du nicht $+1 sondern $+2 für den nächsten
Befehl schreiben. Ich gebe aber keine Gewähr, dass das immer so ist.
Lediglich bei mir war es immer so.

Zu dem Timing: Timer2 wird ja alle 40ms aufgerufen. Der PIC selber
ist mit 4MHz getaktet, richtig? Dann braucht ein Befehl gerade mal
1us. Somit darfst du maximal 40 000 Befehle zwischen den Abfragen
des Interruptflags haben. Ich denke nicht, dass dort das Problem
liegt. =)

Stelle Stimulus mal so ein, wie ich es vorher beschrieben habe und
sage mir, was für ein Ergebnis du bekommst.

Viele Grüße
Sebastian

von Sebastian H. (sebihepp)


Lesenswert?

Ach, nebenbei. Wann schaust du dir das Timer-Register an?
Setze mal die letzt Anweisung als Breakpoint.
Du löschst Timer1 nämlich nicht vor "goto main", somit zählt er
in der nächsten Sekunde immer weiter. Das würde die höheren Werte
erklären.

von Gernot s. H. (picbier)


Lesenswert?

Hallo!
Hatte viel zu tun darum die Antwort etwas später.
Ja das war auch ein Fehler! Den Timer2 habe ich nicht gelöscht und 
deshalb hat der immer weiter gezählt. Das auf die Zeit hochgerechnet 
macht sich bemerkbar. Jetzt zählt er auf jeden Fall richtig.
Ich kann damit jetzt sehr gut Frequenzen im unteren Bereich messen.
Ohne die zusätzliche Schleife mit 25 Runden kann ich dafür sehr gut 
Frequenzen im höheren Bereich messen.
Eine Sache noch die ich auch herausgefunden habe:
Wenn man den Timer 2 benutzt ist es unratsam dem Prescaler sehr hoch zu 
wählen. Dadurch habe ich sehr ungenaue Werte gemessen.
Wenn ich aber den Postscaler hoch gewählt habe und den Prescaler auf 1:1 
gelassen habe, waren meine Werte deutlich besser.
Ich hab auch mal was von einem "linear" IC ??? gehört, das praktisch nur 
ein Frequenzzähler ist. Das soll so funktionieren:
Man legt einmal eine obere Referenzfrequenz an und eine untere. Dann 
misst das IC die Frequenz und stellt das als 8 bit Wert zur Verfügung.
Parallel oder I2C weiß ich nicht mehr. Habt ihr ne Ahnung was das für 
ein IC ist? Und wenn ja, welche Bezeichnung hat das? Ich meine keines 
was eine Frequenz in analoge Werte umwandelt. (LM2907)

Danke für die Hilfe!!!

PICBier

von Gernot s. H. (picbier)


Lesenswert?

Hallo nochmal. Kommt noch etwas dazu.
Das mit dem Prescaler stimmt nicht ganz.
Ich messe jetzt im Bereich 10-12 KHz mit einem Prescaler von 32.
und einem Post von 16. Komischerweise messe ich damit fast auf das Hz 
genau.
Der Logik aber müsste doch gerade das Prescalen die Ungenauigkeit extrem 
hochtreiben? Wenn der auf 32 gestellt ist, dann wird doch das 
Periodenregister immer bei jeder 32sten Flanke erhöht. Oder nicht?
Das heißt im schlimmsten Fall wäre je nach Frequenz +-32.
Aber bei mir ist gerade das Gegenteil der Fall.
Wenn ich mit 1:1 messe alo 1mS verzögere und das 250 mal mache dann muss 
ich das Ergebnis im Timer noch *4 mehmen für 1 Sekunde.
Aber da habe ich zum Teil Abweichungen von mehreren KHz.
Verstehe ich nicht ganz. Aber es wird auf jeden Fall reichen
um die Frequenz vom TCS230 zu messen. (auf 10-12 KHz gestellt).
Wobei man unter 10 Hz doch recht ungenau wird. +- 5%

Mal sehen ob das reicht.

Schöne Grüße

PICBier

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.