Ich hab mir jetzt mal mit dem SKP16C62 ne Uhr programmiert, (die erste programmierte) nun musste ich Feststellen, das diese in einer Stunde um über eine minute falsch lief. Ist das im Rahmen der Quarzungenauigkeit ? sind dort so billige 32kHz Quarze verbaut, das die anstelle von 32768 Hz nur mit z.B. 32700 Hz laufen ? Oder wird das bei dieser Größenordnung dann doch an einem Programmierfehler liegen ? Gruss Thomas
Hallo, poste doch mal Deine Timer-Konfiguration. Ich denke nicht das der Quarz derart daneben liegt. Gruss Judge
nein nein, die Frage ist schon OK. Um einen Quarz auf die "richtige" Frequenz zu kriegen sind Einflussmöglichkeiten und Abgleichschritte notwendig. Ein Quarz lässt sich "ziehen", d.h. von der angegebenen Frequenz "weg" oder auch "hin". Bei einem üC wird normalerweise ein Inverter zur Schwingungsanregung verwendet. Das ist aber für die Genauigkeit meisst nicht optimal. Mit abstimmbaren Parr-Kondensatoren zum Quarz kann man hier einiges gutmachen. Diese C's haben normalerweise Werte bei 10..30 pF wenn dies abstimmbar sind (Drehkondensator) dann lässt sich der Quarz ev.!! "hinziehen". Günstiger ist meisst ein echter Schwingkreis (Spule und Kondensator gekoppelt mit dem Quarz). Mit der Spule und den Kondensatoren kann dann auch eine Temperaturkompensation vorgenommen werden (ist eine eignen Kunst). Kurt
sehr hübsch - aber die Rede war von einem Fehler 1min/h, das sind fast 2%. Da ist nichts mit ziehen oder Temperaturkompensation, das ist eindeutig ein Programmierfehler.
ohh, super. vielen Dank, dann suche ich erst mal, ob ich den Fehler finde. Beispiele gibt es ja genug hier, aber man will ja alles selbst machen :) Danke auch @Kurt für die Erklärung, das man den Takt mit Kondensatoren ziehen kann. ich hab die Timerkonfig aus dem SKP Demo übernommen, dabei wird der 32 kHz Takt durch 32 geteilt, also hab ich nur noch 1024 den dann noch mal geteilt durch 1023*0.01. Damit hab ich dann eigentlich einen 100ms Takt. Den hab ich nun als Grundlage genommen und jeden überlauf mit Interrupt meine "Zehntel-Sekunde-Variable" um eins hochgezählt usw. ich setz das nachher mal hier rein. Es kann natürlich auch sein, das das Programm zu groß ist und der das nicht mehr schafft, weil ich auch noch 5 Siebensegmentanzeigen multiplexe. Ich hab das Programm und die Timerkonfig jetzt nicht hier vorliegen, aber ich poste das heut nachmittag mal hier rein. mfg Thomas
Sorry wegen Ostern hat es etwas länger gedauert... also hier nun die Routinen: ich verwende als Grundlage das SKP Demo. Darin ist der Timer folgendermaßen eingestellt: --------------------------------------------------------------------- ta0mr = 0xc0; // Timer mode, fc32, no pulse output ta0 = (int)(( 1012*.1)); // 32kHz Quarz (32768/32 = 1024 +/- einige Prozent --------------------------------------------------------------------- diese ist schon entsprechend angepasst, so daß ein 100ms Interrupt erfolgt. Klar, INt macht keine Kommastellen, denke die werden das zum besseren verständnis gemacht haben. So, jetzt wird in der Timer-Interrupt Routine meine Uhr berechnet: --------------------------------------------------------------------- void ta0_irq(void) { static int old_ad0, old_ad1; p3_1 = 1; // Ausgang zu, Taktmessen auf 1 setzen ticks_100ms++; // Uhr // hier wird aus dem 100ms Takt die Uhrzeit erzeugt,die anschliessend // auf dem 7 Segment Anzeigen angezeigt wird if (Zehntel < 10) { Zehntel++; if (Zehntel == 10) // Erzeugen der Uhrzeit { Zehntel = 0; if (Sekunde < 60) { Sekunde++; } } } // if (Zehntel == 5) // erzeugen des Blinktaktes 0,5s // { Punkt = 1;} // für den Punkt // if (Zehntel == 0) // { Punkt = 0;} ---------------------------------------------------------------------- im Main mach ich dann den Rest: ---------------------------------------------------------------------- while(1) { p3_1 = 0; // Ausgang zum Taktmessen auf 0 setzen if (Sekunde == 60) { Sekunde = 0; if (Minute < 60) { Minute++; if (Minute == 60) { Minute = 0; if (Stunde < 24) { Stunde++; if (Stunde == 24) { Stunde = 0;} } } } } } ---------------------------------------------------------------------- Tja, nur irgendwie funktioniert das leider nicht, wie ich mir das dachte, vielleicht kann mir ja einer von Euch dabei helfen oder findet den Fehler schon auf anhieb. In dem Programm ist noch eine Ansteuerung einer 5-stelligen 7 Segmentanzeige und diverse AD Wandlungen. Kann ich bei Bedarf noch nachreichen :) vielen Dank mfg Thomas
Hallo, --------------------------------------------------------------------- ta0mr = 0xc0; // Timer mode, fc32, no pulse output ta0 = (int)(( 1012*.1)); // 32kHz Quarz (32768/32 = 1024 +/- einige Prozent --------------------------------------------------------------------- sollte es nicht so sein?? ta0mr = 0xc0; // Timer mode, fc32, no pulse output ta0 = (int)(( 1023*.1)); <---------------------------------! // 32kHz Quarz (32768/32 = 1024 +/- einige Prozent
Das Problem hier ist, daß der Interrupt nicht exakt alle 100ms erfolgt. TA0+1 ist das Teilungsverhältnis (Datenblatt Fig. 15.4). Der 32768Hz Takt wird erstmal durch 32 geteilt (TCK0,TCK1 = 1), was 1024Hz ergibt. Um jetzt auf exakt 10Hz zu kommen müßte man also durch 102,4 teilen. TA0 kann aber nur einen ganzzahligen Wert annehmen. Somit ergibt sich immer eine relativ deutliche Abweichung. Lösung: einen separaten 1Hz Timer (TCK0,1 = 1 und Teiler 0x03ff) für die RTC benutzen.
@sascha: ja, das stimmt, so war es auch und rehnerisch müsste das ja dann auch ta0 = (int)(( 1024*.1)); heissen... na ja, also die ziele, wie ich sie dort hingeschrieben hatte war schon mein kläglicher versuch, die Uhr anzupassen. was jedoch nicht viel bringt, da ich ja nicht mit Komma rechnen kann. Also ich will damit nur sagen mit 1023 ist es auch falsch. ich versuche jetzt mal den Vorschlag von Marko B. umzusetzen und mache mir noch einen Timer mit 1 Hz Takt. Mal schauen, was dabei rumkommt. :) vielen Dank für die Hilfe. Thomas
Wieso kannst du nicht mit einem Komma rechnen?? Dazu muss man ja nur definieren wo das komma sein soll und die eigentliche Zahl mal 10 nehmen oder mal 100... So würde ich es wenigstens am PC machen.
@SuperGrobi: Mach Dir doch einen Zähler in Deiner Timer-ISR der alle 5 Zehntel/Sekunden einen Abgleichwert in den Timer schreibt. Den Timer läßt Du ohne Prescaler laufen (Prescaler = 1). Als Timer-Wert setzt Du 3276 wenn der Zähler <> 5 ist. Bei Zähler = 5 setzt Du den Timer auf 3280 (Ausgleich auf ganze 32768) und den Zähler dann logischer weise auf 0. 32768 = 8 x 3276 + 3280. MfG Andi PS: Für 1/10, 1/100 oder 1/1000 Sekunden nimmt man besser einen Quarz mit 32,000KHz. Das geht besser auf.
Andi: gute Idee. In diesem Fall ist es aber IMHO nicht von Nachteil einen eigenen Timer zu nehmen, da der M16C62P elf separate Timer hat ... Was mir noch eingefallen ist: um die Genauigkeit zu erhöhen, solltest man den Oszillator mit High Drive betreiben (cm03 = 1), da die Leiterbahnen auf dem SKP Board etwas länger sind als nötig.
also ich hab mir jetzt mit TA2 den 1 Hz Timer gebastelt und hab die Uhr mal über Nacht laufen lassen. Jetzt sind es "nur noch" 31 Sekunden in 9 Stunden, die die Uhr nach läuft. Also müsste ich jetzt ca. alle 17 minuten eine Sekunde dazu zählen. Muss ich mir noch mal genau ausrechnen, hab das jetzt nur überschlagen. Ist denn diese Abweichung jetzt Quarzungenauigkeit ? Ich versuche dann erst noch mal den Vorschlag von Marko Oszillator auf High Drive umzusetzen. Der Vorschlag von Andi hört sich auch gut an. Muss mal sehen, wie ich das umsetzen kann. Das einfachste war jedoch gerad nen anderen Timer zu nehmen. Noch hab ich genug davon :) Ich hatte auch schon überlegt... das sind doch 16 Bit Timer, also kann ich doch den Vorteiler /32 weglassen, dann könnte man den Wert genauer einstellen... dank euch für die Hilfe. Thomas
Hier noch eine etwas genauere Aufteilung: 32768 = 8 x 3277 + 2 x 3276. Also 4 x 3277, 1 x 3276, 4 x 3277, 1 x 3276 usw... Oder einfach mit 9 x 3277 und 1 x 3275 in Verbindung mit Zehntel/Sekunden. 32768 = 9 x 3277 + 1 x 3275. Also wenn Zehntel < 10 dann den Timer mit 3277 einstellen ansonsten auf 3275. MfG Andi
SuperGrobi: also irgendwas hast Du falsch gemacht. Ich hab gestern auch mal testweise eine RTC programmiert (mit 1Hz Timer), nach 14h ist noch keine Abweichung feststellbar. Zum Vergleich hab ich den AVR Butterfly mitlaufen lassen, der geht inzwischen knapp 1s vor. Also ist der Quarz auf dem SKP wohl ganz gut. :) Was benutzt Du eigentlich als Referenz? Die Uhr meines Windows-Rechners driftet in einer Stunde locker um 10s. Daher Vergleiche ich die Uhren mit meinem Linux-Rechner, auf dem ntpd läuft.
@Andi: also wenn ich jedes mal den Timer neu laden muss, geht dabei nicht auch "Zeit" verloren ? Ich meine jetzt vom Verständnis her müsste ich den timer doch stoppen, neuen Wert laden und wieder starten. Sorry, bin halt noch nicht so lange dabei, hab das Manual noch nicht durch. :) @Marko:Als Referenz nehm ich die Windows-Uhr. Jetzt wo du es sagst... ja, sollte besser mal was anderes nehmen. Würd mich nicht wundern, wenn die Windows-Krücke falsch läuft :)
Da geht keinerlei Zeit verloren. Nur 4 Takte um einen konstannten Timer-Werte in den Timer zu schreiben (AVR) und ein paar Takte für den Algorithmus zum Handeln. Keine Ahnung wie das Dein C-Compiler macht da ich µC nur in ASM programmiere. MfG Andi
// timer init - timer a0 12Mhz f/32 100ms ta0mr = 0x80; // f/32 ta0 = 0x927c; // 37500; _asm(" FSET I"); // DISABLE_IRQ ta0ic = 2; // Set the timer's interrupt priority to _asm(" FCLR I"); // ENABLE_IRQ ta0s = 1; // Start timer A0 mit dem 12 mhz quarz der auf dem port ist, und nach 255 minuten (hatte nur ein byte hochgezählt) keine abweichung.
pripri: Logisch, geht auch. Der Vorteil, fC32 für die RTC zu benutzen liegt doch aber darin, daß die RTC im Wait Mode (wenn der CPU-Takt abgeschaltet ist) weiterlaufen kann. Im Wait Mode bei 3V braucht der 16C62P nur 6 uA (High Drive) bzw. 1,8 uA (Low Drive), so daß z.B. eine Lithium-Knopfzelle zur Pufferung einige Jahre hält. Sonst bräuchte man den *Uhren*quarz ja auch nicht.
@Marko: High Drive hat auch keine Änderung gebracht, die Uhr läuft einfach nach... so`n shit :) Du scheinst dann wohl einen "guten" Quarz erwischt zu haben. Hab das jetzt auch mit ner Stoppuhr gemessen. Hab jetzt mal den Vorschlag von pripri umgesetzt, wobei ich nur dazu bemerken muss, das das SKP mit der Demo auf 24 MHz läuft, aber egal, da dafür der 16 Bit Timer nicht reicht, hab ich jetzt halt einen 50ms Takt und die Zehntel Sekunden sind jetzt 20tel :) nach 8 minuten Test gibt es bis jetzt noch keine Abweichungen, lass das mal laufen. danke Euch... Thomas
Wie groß war denn die Abweichung bei Dir? Bei mehr als 10s/24h kann das eigentlich nicht am Quarz liegen, das wären mehr als 100ppm. Zum Vergleich: die Uhrenquarze von Reichelt sind mit +-30ppm spezifiziert.
@supergrobi ich habe die pll abgeschaltet, @Marko B. klar hast recht, baue momentan ne anzeige für carrerabahn und da wird das teil aus dem trafo gespeist und ist eh nur während der rennen an.
also na vielem hin und herprobieren, bin ich nun doch zu dem Schluß gekommen, das es der 32 kHz Quarz ist, der da ziemlich ungenau ist. Wenn ich mir den Uhren-Takt aus dem Systemtakt generiere läuft es problemlos mit "nur noch" 2sec/Tag zu langsam. Werde in der nächsten Woche einen Frequenzzähler bekommen, dann messe ich das noch mal genau nach. Die Uhr generiere ich mir jetzt erst mal aus nem PCF8583... vielen Dank noch mal für die freundliche Unterstützung an alle ! gruß Thomas
Versteh echt nicht, was Dein Problem ist. entweder man holt sich einen Quarz der z. B. für Millisekunden durch 1000 ohne Rest teilbar ist, berechnet aus 32768Hz 8 mal 3277 und 2 mal 3276 für 10 Zerhntel-Sekunden oder holt sich nen schnellen 4MHz. Einnes haben die alle gemeinsam: Die sind nicht ungenau! MfG Andi
na ja, ein Problem ist es ja nun eigentlich nicht mehr... Es war (ist) halt nur so, daß das ein M16C-SKP Entwicklungsboard ist, dort war halt alles fertig verlötet. Auch der 32 kHz Quarz. Da ich mir mit dem M16C nur die Programmierung der µC aneignen will, ist es mir es nun nicht mehr wert, dafür jetzt extra noch einen anderen Quarz einzulöten oder sonstiges zu machen. Ich meine, verstanden zu haben, das es nicht an meiner Programmierung lag und hab mich deshalb damit abgefunden. Mit dem 12 MHz Quarz funktioniert es ja und nun "stürze" ich mich halt lieber auf andere Sachen. Ich finde es wirklich super klasse von Euch, dass ihr mir mit hilfreichen Tips zu Seite gestanden habt und hoffe, das ich auch mich weiterhin mit meinen zugegebenermaßen oft ziemlich blöden Fragen an Euch wenden kann. :) Dank auch an dich Andi, ich glaube deine Rechnung verstanden zu haben und werd das bei meinen zukünftigen Programmen berücksichtigen. cu Thomas
Ich weis ja nicht wie es beim M16C ist, aber muß man nicht vom errechneten Timer-Wert 1 abziehen? Beim AVR im CTC-Mode (Clear Timer on Compare) ist es so, das z. B. für einen Timer mit 10000 10000-1 gesetzt werden muß da das Rücksetzen nach Gleichheit des Timers auch einen Timer-Takt kostet. Und 2 Sekunden am Tag entsprechen ca. 0,0024%, 1 Takt weniger von 32768Hz kommt ähnlich gleich. MfG Andi
oops... das wusste ich gar nicht :) kann natürlich sein... muss da mal nachschauen :) dank dir gruß Thomas
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.