Forum: Mikrocontroller und Digitale Elektronik M16C62 32kHz Quarz zu ungenau ?!


von SuperGrobi (Gast)


Lesenswert?

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

von SuperGrobi (Gast)


Lesenswert?

hmmm ist die frage "zu blöd" gestellt ?!

von Judge (Gast)


Lesenswert?

Hallo,

poste doch mal Deine Timer-Konfiguration. Ich denke nicht das der Quarz
derart daneben liegt.

Gruss
Judge

von Kurt (Gast)


Lesenswert?

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

von crazy horse (Gast)


Lesenswert?

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.

von SuperGrobi (Gast)


Lesenswert?

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

von SuperGrobi (Gast)


Lesenswert?

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

von sascha (Gast)


Lesenswert?

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

von Marko B. (Gast)


Lesenswert?

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.

von SuperGrobi (Gast)


Lesenswert?

@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

von Freak5 (Gast)


Lesenswert?

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.

von Andi (Gast)


Lesenswert?

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

von Andi (Gast)


Lesenswert?

Meinte eigentlich
 32768 = 8 x 3276 + 2x 3280.

MfG
Andi

von Marko B. (Gast)


Lesenswert?

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.

von SuperGrobi (Gast)


Lesenswert?

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

von Andi (Gast)


Lesenswert?

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

von Marko B. (Gast)


Lesenswert?

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.

von SuperGrobi (Gast)


Lesenswert?

@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 :)

von Andi (Gast)


Lesenswert?

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

von pripri (Gast)


Lesenswert?

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

von Marko B. (Gast)


Lesenswert?

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.

von SuperGrobi (Gast)


Lesenswert?

@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

von Marko B. (Gast)


Lesenswert?

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.

von pripri (Gast)


Lesenswert?

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

von SuperGrobi (Gast)


Lesenswert?

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

von Andi (Gast)


Lesenswert?

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

von SuperGrobi (Gast)


Lesenswert?

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

von Andi (Gast)


Lesenswert?

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

von SuperGrobi (Gast)


Lesenswert?

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