Uhr über 8051-Prozessor sehr ungenau

#5678028
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
}
Gast #5678046
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.
#5678053
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.
#5682403
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.
Angehängte Dateien:
#5682422
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.
Moderator Persönliche Seite #5682423
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.
#5683932
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).
Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren