Forum: Mikrocontroller und Digitale Elektronik Timer0 Interrupt PIC18F2550 ->Fragen


von ERTA (Gast)


Lesenswert?

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

von Master S. (snowman)


Lesenswert?

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

von ERTA (Gast)


Lesenswert?

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.

von Master S. (snowman)


Lesenswert?

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

von Chris (Gast)


Lesenswert?

Der Timer0 läuft dir alle ca 5.2ms über bei  192 Überläufen sind es
exact eine Sekunde, prescaler 256 sowie free running.

von Master S. (snowman)


Lesenswert?

@Chris: wie kommst du auf die zahlen? bei 48MHz und 8bit-timer käme ich 
wenigstens annähernd in deine region: 5.46ms

von Chris (Gast)


Lesenswert?

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.

von Master S. (snowman)


Lesenswert?

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

von ERTA (Gast)


Lesenswert?

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.

von Chris (Gast)


Lesenswert?

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++;
       }

von Chris (Gast)


Lesenswert?

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.

von Chris (Gast)


Lesenswert?

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