Forum: Mikrocontroller und Digitale Elektronik PIC24 - FRC mittels Uhrenquarz kalibrieren


von Benjamin R. (shooter_benny)


Lesenswert?

Hallo,

ich verwende einen PIC24FJ64GB004 für eine USB Anwendung.

Ich würde gernen auf den internen FRC (8 Mhz; Genauigkeit typ: +/-0.25, 
min: -1.25%, max: +1,00%) zurückgreifen.
Die USB-Spezifikation schreibt für den Betrieb bei Full-Speed eine 
Genauigkeit von +/-0.25% vor.

Im Datenblatt steht für den USB-Betrieb ist kein externer Quarz nötig, 
allerdings steht nicht dabei das dies nur für den Betrieb bei Low-Speed 
zutrifft - ist aber anzunehmen (siehe oben: Genauigkeit des internen FRC 
außerhalb +/-0.25%)

Ich suche nun eine Möglichkeit den FRC hinreichend zu kalibrieren 
(Register OSCTUN). Zur Verfügung steht mir dazu ein (genauer) Uhrenquarz 
als SOSC, welche auch die RTCC Einheit speist.


Wie stelle ich das am besten an?
- Die Kalibrierung sollte dabei nicht all zu viel Zeit in Anspruch 
nehmen (max. 20 Sekunden)
- Timer stehen mir alle zur Verfügung, allerdings verstehe ich 
möglicherweise die verschiedenen "Clocks-Speise-Möglichkeiten" nicht 
hinreichend.


Das hab ich mir nun überlegt:
1. Timer1 wird über SOSC (Uhrenquarz) gespeist. Mit Prescaler von 256 
generiert er alle 1/128Hz = ~7,81ms einen Interrupt.

2. Timer2 wird durch Systemtakt (FRC / 2 = ~4MHz) versorgt. Kein 
Prescaler. Wert erhöht sich dabei ca alle 1/4Mhz = ~250ns um eins.

3. Auswerten (evtl. auch erst nach mehreren Zyklen, dann wäre aber 
sicherlich für Timer2 ein Prescaler nötig)
Wenn der FRC genau mit 8MHz schwingt dann müsste Timer2 einen Wert von 
31250 haben ( 1/128Hz : 1/4MHz = 31250 ), schwingt der Quarz mit 8000256 
Mhz, dann hätte Timer2 den Wert 31251, 31249 für 7999744 Mhz, usw.


Frage A: Kann ich Timer1 überhaupt von meinem Uhrenquarz speisen. Im 
Datenblatt steht dazu "External clock from T1CK pin (on the rising 
edge)". Heißt das ich benötige einen Uhrenquarz-OSZILLATOR?

Frage B: Kann ich mit dieser Vorgehensweise eine ausreichende 
Genauigkeit erreichen?

Frage C: Wird es überhaupt genauer wenn ich mit mehreren Zyklen 
auswerte, UND damit auch einen Precaler für Timer2 verwenden muss?

Frage D: (Zu Frage C) Wäre es genauer den Timer2 als 32-bit Timer laufen 
zu lassen, also wieder OHNE Prescaler?

Frage E: Kann ich dabei die Genauigkeit des Uhrenquarzes außer Acht 
lassen, sie wie ich es nun gemacht habe?

Frage F: Ist der Ansatz überhaupt brauchbar, funktioniert das überhaupt, 
oder gibt es "smartere" Lösungsansätze?


Vielen Dank fürs Lesen (ist nun doch etwas viel geworden) :)

mfg
Benny
von Michael H. (morph1)


Lesenswert?

Sorry, kanns sein das ich etwas nicht verstehe?

Laut dir:

Benjamin R. schrieb:
> Die USB-Spezifikation schreibt für den Betrieb bei Full-Speed eine
> Genauigkeit von +/-0.25% vor.

Laut Datenblatt:

> 8 MHz Internal Oscillator with 0.25% Typical Accuracy
(-1.25 +0.25 1.0)

ICh würd Microchip da mal soweit vertrauen :)

Abgesehen davon, auch die 1% PICs (PIC24FJ256GB210) oder auch die 2% FRC 
(PIC24FJ256GB110) machen keinerlei Probleme am USB-Bus, ist natürlich 
nur zum Testen geeignet, auf keinen Fall für die Produktion.
von Florian V. (Gast)


Lesenswert?

von Benjamin R. (shooter_benny)


Lesenswert?

Ok danke für die bisherigen Meinungen.

>Michael H.
>ICh würd Microchip da mal soweit vertrauen :)
Ich hätte das gerne sauber gelöst.

>Florian V.
Danke, den Thread hatte ich noch nicht gesehen. Aber man sieht das es 
selbst da keine 100% klare Aussage gibt.


Ich hab die ganzen Timer noch über und würde die gerne noch sinnvoll 
nutzen, damit ich ganz sicher weiß das Teil funktioniert in zwei Jahren 
auch noch, bin aber gleichzeitig auf die zusätzlichen IOs angewiesen, 
sonst würde ich ja sowieso einen Quarz nehmen. ;)

Mit Assembler habe ich leider nichts am Hut und möchte schon ganz gerne 
bei C bleiben. Den ASM Code zu portieren sehe ich aber problematisch, da 
die Instructions gezählt werden, was ich wiederrum bei C nicht kann:
1
volatile varInstructions = 0;
2
volatile varCalDone = FALSE
3
4
ISR_Timer1Overflow { Auswerten (varInstructions); varInstructions = 0; varCalDone = TRUE }
5
6
main:
7
8
while (!varCalDone) { varInstructions++; };

Problem: Je nach Optimierungsstufe und Compilerversion könnte der Code 
anders übersetzt werden, was dazu führt das ich u.U. eine sehr große 
Abweichung der gezählten Instruktionen hätte.


Deswegen auch mein Vorschlag mit den beiden Timern, sinngemäß:
1
// Timer1 Clock: 32,786 kHz, Timer2 Clock: FRC/2
2
ISR_Timer1Overflow { Auswerten (Timer2_Zaehlstand); }


Was meint ihr dazu? Zu einfach? Zu Umständlich?

mfg
Benny
von iaoffline (Gast)


Lesenswert?

Benjamin R. schrieb:
> Mit Assembler habe ich leider nichts am Hut und möchte schon ganz gerne
> bei C bleiben.

Da würd ich nicht dran rumschrauben, gibt es bei C keinen Inline Code?

Das ganze ist doch simpel gemacht, braucht kaum Flash und gerade mal 
30ms at startup. Der Pic geht danach so gut wie unverändert an den 
Start, nur halt mit garantierter Taktfrequenz.
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.