Forum: Mikrocontroller und Digitale Elektronik Uhr über 8051-Prozessor sehr ungenau


von Walther E. (tomete)


Lesenswert?

Guten Morgen.
Ich wollte eine kleine Digitaluhr bauen und diese über einen alten 
8051-Prozessor steuern. Das Problem hierbei ist, (ich denke, dass es 
irgendwie an dem sehr ungenauen Timer liegt) dass diese Uhr extrem 
schnell realisierbare Fehler aufweist.
Gibt es eine Möglichkeit, dies ohne einen neuen Quartz irgendwie 
auszugleichen?
Hier mein Code:
1
#include <8051.h>          
2
#include <lcd8bit.h>     // Displayansteuerung definieren
3
#include <stdio.h>
4
#include <stdlin.h>
5
6
  
7
unsigned int hour=8;
8
unsigned int minute=0;
9
unsigned int second=0;
10
unsigned int d ;
11
12
13
void main(void)
14
{
15
 
16
    while (1){
17
         second++;
18
         waitms(d);
19
       if(second==60)
20
           {
21
       second=0;
22
       minute++;
23
     }
24
     if(minute==60)
25
     {
26
       minute=0;
27
       hour++;
28
     }
29
     if(hour==24)
30
     {
31
      hour=0;
32
     }
33
34
  if((P3 & 0x04)==0){
35
    
36
      d =1000;
37
    
38
     }
39
    
40
     else {
41
    
42
       d=10;
43
    
44
     }
45
     
46
      wait_ms(d);
47
      lcd_printf("\a ");     // Display initialisieren
48
    lcd_printf("\n %u : %u: %u",hour, minute, second);
49
      // detach USB-Port
50
   usb_disable();
51
    
52
    }
53
54
}

: Bearbeitet durch User
von Georg G. (df2au)


Lesenswert?

Du verwirrst uns mit viel zu vielen Informationen.
Was für ein Quarz wird verwendet? Wie groß sind die Fehler? Wie kommst 
du vom Quarz auf die Sekunden? Wie ist wait_ms() realisiert?

von Mampf F. (mampf) Benutzerseite


Lesenswert?

Walther E. schrieb:
> (ich denke, dass es
> irgendwie an dem sehr ungenauen Timer liegt)

Ich sehe da überhaupt keinen Timer ...

von Ralph S. (jjflash)


Lesenswert?

... ich auch nicht. Wir sind wohl üner Sylvester blind geworden.

von hinz (Gast)


Lesenswert?

wait_ms(t) ist ein Schätzeisen. Wenns genau werden soll kommt man um 
Interrupts über den Timer kaum herum.

von -gb- (Gast)


Lesenswert?

Du zählst 61 Sekunden? Von Sekunde 0 bis 60. Und nein, nimm irgendeinen 
Hardwarezähler im IC und verwende den zum Zählen. Dessen Wert kannst du 
dann in die einzelnen Stellen der Anzeige umrechnen.

von Peter D. (peda)


Lesenswert?

Walther E. schrieb:
> wait_ms(d);

Egal, wie genau wait_ms() implementiert ist, es kann nicht hellsehen, 
wie lange der restliche Code rumrechnet.
Du brauchst in jedem Fall einen der HW-Timer. Von dem pollst Du das 
Überlaufbit oder setzt einen Interrupthandler auf.

von Walther E. (tomete)


Lesenswert?

OK, tut mir Leid. Hier die notwendigen Informationen:
Verwendet wird ein 16MHz-Quartz von RoboMall.
Den genauen Fehler habe ich bisher nicht ausgetestet, aber bereits nach 
einer Stunde geht die Uhr um ein paar Minuten nach. Bei Bedarf kann ich 
das noch einmal genau ermitteln.
Die waitms() ist aus einer Header-Datei aus dem Internet, wo nur das 
hier drin steht:

void wait_ms(unsigned int time);
void usb_disable(void);

Ansonsten ist noch die Bibilothek "AT89C513xA.h" eingebunden, die beim 
Kopieren irgendwie nicht mit mitkopiert wurde.

von Peter D. (peda)


Lesenswert?

Walther E. schrieb:
> Bei Bedarf kann ich
> das noch einmal genau ermitteln.

Nein, es besteht kein Bedarf. Wie bereits ausgeführt, muß es ungenau 
sein. Es ergibt auch keinen Sinn, es zu korrigieren.
Nur die HW-Timer laufen unabhängig von der Programmlaufzeit und deshalb 
gibt es sie auch.

: Bearbeitet durch User
von Ralph S. (jjflash)


Angehängte Dateien:

Lesenswert?

... für den Fall dass du KEIN Troll bist hab ich dir hier ein MCS-51 
Programm beigefügt, dass die die Verwendung von Timer2 im Interruptmodus 
zeigt. Hier allerdings für einen Quarz 12 MHz.

Ein 16 MHz Quarz ist grundsätzlich für einen Uhrenbetrieb suboptiomal, 
weil du keine genaue Teilerfrequen von 1 Sekunde "triffst".

Der Prozessorcoretakt läuft bei einem 16 MHz Quarz mit 1 1/3 MHz ... und 
dieses Drittel verhindert eine genaue Uhr mit 16 MHz Quarz.

von S. R. (svenska)


Lesenswert?

Walther E. schrieb:
> Den genauen Fehler habe ich bisher nicht ausgetestet, aber bereits nach
> einer Stunde geht die Uhr um ein paar Minuten nach.

Ich tippe mal stark darauf, dass du in deinem Code etwas falsch machst. 
So schlecht ist der Quarz nicht. Zähle mal aus, wieviele Timer-Ticks du 
pro Stunde (oder Tag) hast und wieviele dein Code erwartet.

Und ein Timer hat gefälligst unabhängig vom Programm zu laufen. Dein 
wait_ms() wartet (mehr oder weniger genau) eine Sekunde pro Tick, aber 
dass der restliche Code noch Zeit brauchst, hast du vergessen.

Ein guter Hinweis ist der hier:
> Der Prozessorcoretakt läuft bei einem 16 MHz Quarz mit 1 1/3 MHz ... und
> dieses Drittel verhindert eine genaue Uhr mit 16 MHz Quarz.

Das klingt schlüssig und liefert dir einen systematischen Fehler. Den 
kannst du rausrechnen, indem du z.B. alle N Minuten eine Sekunde 
überspringst oder mit einer höheren Auflösung rechnest.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Walther E. schrieb:
> Den genauen Fehler habe ich bisher nicht ausgetestet, aber bereits nach
> einer Stunde geht die Uhr um ein paar Minuten nach. Bei Bedarf kann ich
> das noch einmal genau ermitteln.

Ist ja logisch. Hier ein übertriebenes Beispiel:
1
- Du berechnest die Zeit, kostet 100ms an CPU-Zeit
2
- Du wartest 1000ms
3
- Du berechnest die Zeit, kostet 100ms an CPU-Zeit
4
- Du wartest 1000ms
5
- Du berechnest die Zeit, kostet 100ms an CPU-Zeit
6
- Du wartest 1000ms

Nach obigem Beispiel geht die Uhr bereits nach 10 Sekunden 1 Sekunde 
nach. Ok, der Prozessor braucht weit weniger als 100ms, deshalb wird das 
bei Dir nicht so krass ausfallen. Aber es fällt auf jeden Fall nach 
einer Stunde auf.

Dafür benutzt man einen Hardware-Timer, der in festen Intervallen 
arbeitet - und zwar unabhängig von der Rechenzeit zwischendurch. 
waitms() ist dafür unbrauchbar.

von Andreas R. (bastlerxxl)


Angehängte Dateien:

Lesenswert?

In der angehängten Datei findet sich auf Seite 76 ein vollständiges 
Programm für eine Uhr mit Kalender mit Schaltjahrerkennung und 
Umstellung auf Sommerzeit in Assembler für die MCS51 Controller. Man 
muss nur mit dem Timer Interrupt und einem externen Quarzoszillator 
(läuft stabiler als eine Armbanduhr) die Zeitbasis von 1 s erzeugen (ist 
in der Datei erläutert).

von Walther E. (tomete)


Lesenswert?

Vielen Dank für diesen Anhang. Hat mir extrem weiter geholfen.

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.