Hallo Leute Möchte auf einem PIC18F2550 jede Sekunde einen Zähler um 1 erhöhen. Daher will ich den Timer0 Interrupt verwenden. Habe noch nie mit einem Timer Interrupt gearbeitet, und daher einmal das Datenblatt zur Hand genommen. Folgende Überlegungen: Bit0-2: Prescaler soll 256 sein (TOPS0=1 TOPS1=1 TOPS2=1) (1 Timertakt müsste dann mit Prescaler 21,33uS betragen) BIT3: PSA = 0 Timertakt kommt von Prescaler Bit4: T0SE = 0 Für meine Anwendung unwichtig Bit5: Systemtakt soll verwendet werden (T0CS = 0) (bei 48Mhz durch 4 müsste der Timertakt 12Mhz betragen. 1 Timertick = 83,3nS) Bit6: T08Bit = 0 Timer0 ist 16Bit Timer (46875 Timerticks = 1 Sekunde. Also muss Timer0 mit 18661 vorgeladen werden) BIT7: TMR0ON = 1 Timer 0 einschalten Ist meine Überlegung bezüglich der Vorladung des Timers richtig, oder habe habe ich da etwas übersehen? Dankeschön für eure Antworten im Vorhinein
> 1 Timertakt müsste dann mit Prescaler 21,33uS betragen) das stimmt bei einem internen takt von 48MHz den rest habe ich mit dem datenblatt nicht kontrolliert. falls du C18 verwendest, nimm doch die funktion OpenTimer0() auf seite 62 von http://ww1.microchip.com/downloads/en/devicedoc/mplab_c18_libraries_51297f.pdf diese funktion wird vom C18-compiler in 2 oder 3 befehle umgewandelt, die genau die richtigen register korrekt setzen - der vorteil ist, dass wenn du den PIC-typ änderst, du die funktion nicht umschreiben musst, ganz abgsehen von der leseerlichkeit des codes.
Nein ich verwende den Mikroebasic Compiler von Mikroelektronika. 48Mhz Interner Takt stimmt. Wird über den PLL erzeugt. Mir ging es mehr darum, ob ich das Ausrechnen der einzelnen Zeiten, und das voreinstellen des Timers richtig kapiert habe.
t = frequenz, mit der der timer0 hochzählt t = (interner takt / 4) / prescaler edit: wieso nicht C18? der ist gut und gratis. ps: auch der mikrobasic wird irgend so eine Opentimer-funktion haben
Der Timer0 läuft dir alle ca 5.2ms über bei 192 Überläufen sind es exact eine Sekunde, prescaler 256 sowie free running.
@Chris: wie kommst du auf die zahlen? bei 48MHz und 8bit-timer käme ich wenigstens annähernd in deine region: 5.46ms
Sorry, das war mit 8bit timer, nur da bist du dir sicher, daß du keinen Fehler hast. Bei 16 bit kannst du den Timer laden, nur da hängst du dir einen Fehler rein, der mittels ASM Befehle sowie Register timing korrfigiert werden muß, welcher aber nur definitiv korrigiert werden kann wenn der timer0 keinen Prescaler hat, ansonsten hat der Pic nähmlich einen Jitter von 1 Instruktionszyklus, was ca 83.333 Nanosekunden sind welche in deinem Beispiel nicht korrigierbar sind, ca 2.4mS am Tag, der Rest ist korrigierbar, aber nur mittels Disassembler, Instruktionen Zählen sowie Datasheet genau lesen. Wenn man keinen Vorteiler verwendet, dann ist dieser Jitter auch korrigierbar, was aber nicht Zweckmäßig ist. Deshalb, wenn es um genaue Zeit geht, versucht man einen free running Timer zu haben, den man nicht im Interrupt neu läd.
> Sorry, das war mit 8bit timer,nur da bist du dir sicher, daß du > keinen Fehler hast. ja?!? das haste mit 8bit auch. sobald die frequenz nicht 2^x ist, kommste auf krumme kommazahlen beim timer, egal ob mit 16 oder 8 bit. mit 16 bit hast du bei gleichem code einfach 256 mal weniger interrupts als bei 8 bit ;-) aber ja: entweder assembler-code anschauen und im code den timer-vorladewert anpassen oder einen timer über einen externen 32.768kHz-quarz betreiben.
2.4 ms am Tag sind genau genug. Zur Zeit habe ich es provisorisch mit einer Variable im Main gemacht. Der läuft pro Sekunde !! 200mS !! plus minus genau. Einmal betragen 5 Sekunden nur 4 Sekunden, einmal 6 Sekunden und das nächste mal irgendwo dazwischen :-) War bis jetzt noch immer genau genug. Soll ja nur ein freier Logger weren, der alle 20 Minuten einen Wert abspiechert, und keine Uhr. Mir ging es wie gesagt nur um die Umrechnung. Dankeschön dafür.
Stimmt, hatte mich verrechnet, sorry war Windows taschenrechner 1(µS)/12(T$aktzeit)=0.083333µS*256(Prescaler)*256(8Bit)=5461.333333µS je Timerüberlauf, ca 5.46mS sehr praktisch für Timeouts, entprellungen usw. 1S (1000/5.46133333) ergeben 183 überläufe. Gegenprobe 183*5.461333 = 999423.9999, da fehlen also 576 µS je Sekunde. 5461... /576 = 9.481481481, und jetzt 256 zum Quadrat durch ANS 65536/9.481...=6912 . Dies ist jetzt dein Korrekturfaktor bei einer 16bit Variable. Gegenprobe: 65536/6912=9.481481481 , dasselbe wie oben. Das heißt, du hast eine free running Timer mit diesmal ca 5mS ticks sowie eine 16bit Variable zur Korrektur um eine genaue Zeit zu erhalten um damit eine Null Fehler zeit zu haben. Max Abweichung 5.461mS aber keinen kummulativen Fehler. C Code zur Veranschaulichung Es wird angenommen, daß zum Systemstart alle Variablen mit 0 Belegt werden. time_error ist eine 16bit Variable, time_sec ist unixtime warscheinlich 32bit und time_cnt ist eine 8bit variable. time_error+=6912; // korrectur factor if (!CURRY) // wenn die variable nicht übergelaufen ist if(!time_cnt--) { time_cnt=183; time_sec++; }
Ansonsten 16bit Wert 46875 im Timer in der Interruptroutine laden, und mit einem Fehler von ca 2Sekunden zuviel am Tag leben, oder Wert 46874 laden, disassemblieren, timing anpassen auf 21µS aber die 2 Taktzyklen delay nach dem Laden des Wertes beachten, eventuell auch 46873 laden, mit nop/goto die Zeit korrigieren und der fehler ist dann nur mehr ca 2ms zuviel am Tag.
Bei Wert im Timer laden, wurde von einem Prescaler von 256 ausgegangen. Sorry, bin nicht angemeldet
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.