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