Forum: Mikrocontroller und Digitale Elektronik Genauigkeit der internen STK500 Frequenz


von Friedrich K. (fiete)


Lesenswert?

Hallo,

ich habe mit meinem Mega8 und dem STK500 eine Uhr programmiert, die ich 
jedoch nicht auf das Display ausgebe, sondern sekündlich auf UART.

Die CPU-Frequenz ist auf extern gefused und durch den STK500 
Frequenzgeber gegeben. AVR-Studio sagt 3868400 Hz. Weiß jemand, wie 
genau diese Frequenz wirklich ist? Das "Datenblatt" des STK500 schweigt 
diesbezüglich.

Der Fehler der Uhr ist ca. -1% Also nach 100sek. geht sie schon eine 
sek. falsch (nach) Könnte das der Taktgenauigkeit des STK500 
entsprechen?

Anmerkung:
Um Interruptzeiten möglichst kurz zu halten, setze ich ein Flag. Durch 
Vorteiler von 1024 und Interrupt nach 3600 zählungen macht das genau 
einen Interrupt pro sekunde ---> Ich bin ziemlich sicher, dass keine 
Interrupts verschluckt werden.
Ich war erstaunt, als ich gesehen habe, dass die Ausgabe von 10 Zeichen 
auf UART ca. 60.000 Takte braucht. Das sind wenn man großzügig rechnet 
bei 9600 Baud ca. 10ms ---> Die Übertragung sollte lange fertig sein, 
bis zum nächsten Interrupt.

Gruß, fiete

von Michael U. (amiga)


Lesenswert?

Hallo,

Friedrich Kpunkt schrieb:
> Hallo,
>
> ich habe mit meinem Mega8 und dem STK500 eine Uhr programmiert, die ich
> jedoch nicht auf das Display ausgebe, sondern sekündlich auf UART.
>
> Die CPU-Frequenz ist auf extern gefused und durch den STK500
> Frequenzgeber gegeben. AVR-Studio sagt 3868400 Hz. Weiß jemand, wie
> genau diese Frequenz wirklich ist? Das "Datenblatt" des STK500 schweigt
> diesbezüglich.
Den Takt erzeugt wohl ein Timer des AVR auf dem STK, sollte also 
eigentlich Quarzgenau sein.
>
> Der Fehler der Uhr ist ca. -1% Also nach 100sek. geht sie schon eine
> sek. falsch (nach) Könnte das der Taktgenauigkeit des STK500
> entsprechen?
Ohne Sourcecode ist es schwer einen Softwarefehler auszuschlißen...
>
> Anmerkung:
> Ich war erstaunt, als ich gesehen habe, dass die Ausgabe von 10 Zeichen
> auf UART ca. 60.000 Takte braucht. Das sind wenn man großzügig rechnet
> bei 9600 Baud ca. 10ms ---> Die Übertragung sollte lange fertig sein,
> bis zum nächsten Interrupt.

Warum? 9600Baud sind 960 Byte/s bei einem Stopbit und ohne zusätzliche 
Pause. 1000ms/960*10 sind also minimal 10,41ms für 10 Byte.
Die UART-Ausgabe braucht nur ca. 8 Takte pro Byte, der Rest ist Warten 
darauf, daß das Byte endlich mit den lahmen 9600 Baud rausgetaktet ist.
Es sei denn, man legt es in einen Buffer und sendet per 
UART-TXE-Interrupt.

Gruß aus Berlin
Michael

Gruß aus Berlin
Michael

von Friedrich K. (fiete)


Lesenswert?

Klar, gern zeige ich den Assembler-Code:

Warum ich so erstaunt war, über die 10ms UART-Sendezeit ist nur aus der 
Tatsache begründet, dass ich mich erst nen paar tage mit sowas 
beschäftige...
1
.include "m8def.inc"
2
3
.equ F_CPU = 3686400
4
.equ BAUD = 9600
5
6
7
.def temp1=r16
8
.def temp2=r17
9
.def stunden=r18
10
.def minuten=r19
11
.def sekunden=r20
12
.def flag=r21
13
.def flag2=r25
14
.def subcount=r22
15
.def einer=r23
16
.def zehner=r24
17
18
.dseg
19
20
21
.cseg
22
23
.org 0x0000
24
    rjmp  boot
25
26
.org OC1Aaddr
27
    rjmp  CTC_OverFlow
28
29
;#################################################################################
30
;#  AUTOMATIC BAUDRATE CALCULATION  -- AUTOMATIC BAUDRATE CALCULATION  -- AUTOMA #
31
;#################################################################################
32
33
.equ UBRR_VAL   = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; clever runden
34
.equ BAUD_REAL  = (F_CPU/(16*(UBRR_VAL+1)))     ; Reale Baudrate
35
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promille
36
 
37
.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))       ; max. +/-10 Promille Fehler
38
  .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
39
.endif
40
;#################################################################################
41
42
43
boot:
44
45
;Stackpointer Init
46
    ldi  temp1,HIGH(RAMEND)
47
    out  SPH,temp1
48
    ldi  temp1,LOW(RAMEND)
49
    out  SPL,temp1
50
;Set Baudrate
51
    ldi  temp1,HIGH(UBRR_VAL)
52
    out  UBRRH,temp1
53
    ldi  temp1,LOW(UBRR_VAL)
54
    out  UBRRL,temp1
55
;Set framerate 8 to 8 Bit
56
    ldi  temp1,(1<<URSEL)|(3<<UCSZ0)
57
    out  UCSRC,temp1
58
;Start USART
59
    sbi  UCSRB,TXEN
60
61
;set CTC
62
63
  ;set OverFlow value
64
    ldi  temp1,HIGH(3600-1)
65
    out  OCR1AH,temp1
66
    ldi  temp1,LOW(3600-1)
67
    out  OCR1AL,temp1
68
  ;init CTC
69
    ldi  temp1,(1<<WGM12)|(5<<CS10)
70
    out  TCCR1B,temp1
71
  ;init CTC
72
    ldi  temp1,1<<OCIE1A
73
    out  TIMSK,temp1
74
  ;set prescaler  
75
    ldi temp1, 0b00000101  
76
    out TCCR0, temp1
77
78
;clear all:
79
    clr  temp1
80
    clr minuten
81
    clr stunden
82
    clr flag
83
    
84
85
;interrupts aktiviren
86
87
    sei
88
89
loop:  in temp1,SREG
90
    cpi  flag,1
91
    breq  Ausgabe
92
    out SREG,temp1
93
    rjmp  loop
94
95
96
Ausgabe:
97
98
    mov  einer,stunden
99
    rcall  Ascii_Umrechner
100
101
    mov  zehner,einer
102
    rcall  send
103
104
    ldi  zehner,':'
105
    rcall  send
106
107
    mov  einer,minuten
108
    rcall  Ascii_Umrechner
109
110
    mov  zehner,einer
111
    rcall  send
112
113
    ldi  zehner,':'
114
    rcall  send
115
116
    mov einer,sekunden
117
    rcall  Ascii_Umrechner
118
119
    mov  zehner,einer
120
    rcall  send
121
    ldi  zehner,10
122
    rcall  send
123
    ldi  zehner,13
124
    rcall  send
125
    
126
    clr flag
127
    out SREG,temp1
128
    rjmp loop
129
130
send:
131
    sbis  UCSRA,UDRE
132
    rjmp  send
133
    out  UDR,zehner
134
    nop
135
    ret
136
137
Ascii_Umrechner:
138
    cpi  einer,10
139
    brsh  zehn
140
    subi  einer,(-'0')
141
    ldi  zehner,'0'
142
    rjmp  send
143
zehn:  cpi  einer,20
144
    brsh  zwan
145
    subi  einer,(10-'0')
146
    ldi  zehner,'1'
147
    rjmp  send
148
zwan:  cpi  einer,30
149
    brsh  dreisg
150
    subi  einer,(20-'0')
151
    ldi  zehner,'2'
152
    rjmp  send
153
dreisg:  cpi  einer,40
154
    brsh  virsg
155
    subi  einer,(30-'0')
156
    ldi  zehner,'3'
157
    rjmp  send
158
virsg:  cpi  einer,50
159
    brsh  funfz
160
    subi  einer,(40-'0')
161
    ldi  zehner,'4'
162
    rjmp  send
163
funfz:  subi  einer,(50-'0')
164
    ldi  zehner,'5'
165
    rjmp  send
166
167
168
169
CTC_OverFlow:
170
    in temp2,SREG
171
    inc  sekunden
172
    cpi  sekunden,60
173
    breq  min
174
    rjmp  end_uhrwerk
175
min:  clr  sekunden
176
    inc  minuten
177
    cpi  minuten,60
178
    breq  stun
179
    rjmp  end_uhrwerk
180
stun:  clr  minuten
181
    inc  stunden
182
    cpi  stunden,12
183
    brne  end_uhrwerk
184
    clr  stunden
185
    rjmp  end_uhrwerk
186
187
    
188
end_uhrwerk:
189
190
    ldi  flag,1        ;flag setzen
191
    out SREG,temp2
192
    reti

von Friedrich K. (fiete)


Lesenswert?

He Leute,

Habe zwei weitere Nachmittage mit der Fehlersuche zugebracht und komme 
zu dem Schluss, dass die Taktfrequenz des STK500 nur ca. 1% Genauigkeit 
hat (bei mir -0.7). Leider kann ich das nicht direkt nachmessen, sondern 
nur durch meine selbstgebastelte Uhr. (alternative Vorschläge?)

Im Debug-Modus des AVR-Studios zählt der code jedenfalls brav die genaue 
Taktfrequenz ab, bevor der nächste interrupt kommt. Programmierfehler 
hat ja hier auch keiner gefunden - zumindest keine groben ;-)

Als nächsten Schritt organisiere ich mir mal einen Quarz und gucke mal, 
ob meine Uhr vielleicht genauer geht.

Gruß, fiete

von Peter R. (pnu)


Lesenswert?

Mit Quarz ist die Taktfrequenz mindestens auf 0,1% genau, meistens um 
den Faktor 10 besser.

Eine 1%-ige Abweichung kann also nur durch einen Softwarefehler bedingt 
sein, oder dass die Quarzfrequenz keine Baudratefrequenz ist, also eine 
etwas krumme Zahl hat. Dann lässt sich die exakte Baudrate nur mit 
einigen Prozent Abweichung erreichen.

Bei der Übertragung mit RS232 machen Abweichungen bis 3 % üblicherweise 
nichts aus.

Es gilt folgende Abschätzung: Wenn das Telegramm eines Byte 10 Bit 
umfasst, kann im letzten Bit eine Abweichung eines halben Bit toleriert 
werden, ohne ins Nachbarbit zu geraten, da ja beim ersten Bit immer neu 
synchronisiert wird. Dem entspricht eine Toleranz von 1/20 also 5%.

von Henk (Gast)


Lesenswert?

vielleicht auch der übliche fehler, dass man beispielsweise bei voller 
60er sekunde erst resettet oder ähnliches? sowas hab ich schonmal 
gebracht.. schäm

von Friedrich K. (fiete)


Lesenswert?

@Peter:
Die Übertragung läuft einwandfrei. Die Übertragung ist lange 
abgeschlossen, bevor der nächste Interrupt die neue Sekunde einläutet 
und das Flag setzt, welche dann die Übertragung triggert.

@Henk:
Reset hatte ich auch schon als Verursacher vermutet. Was allerdings 
dagegen spricht ist, dass bei einem Reset alle "Zähler" mit clr auf null 
gesetzt werden, sodass es auffallen würde, wenn er einen Reset bekommt. 
Oder nicht?

von Henk (Gast)


Lesenswert?

Ähm nee ich habe mich undeutlich ausgedrückt. Ich meinte nur bzgl. 
deiner Aussage "eine Uhr gebaut" dass vielleicht bei Übernahme von 
Sekunden in Minutenvariablen oder so Ddu etwas verdreht haben könntest.

Ich hatte beispielsweise mal bei der falschen Sekunde hochgezählt und 
somit jede Minute eine Sekunde verloren. ;-)

von Friedrich K. (fiete)


Lesenswert?

Naja, der Zähler zählt von 0 bis 59. Wenn es bei 60 ist, wird er wieder 
auf null gesetzt. Also das stimmt auch.

von H.Joachim S. (crazyhorse)


Lesenswert?

Hm, auf meinem STK500 ist kein Quarz, sondern ein Keramikresonator. Gut 
und günstig für übliches (UART z.B.), nicht genau genug für ne Uhr. Ohne 
deine Software angeschaut zu haben - das liegt im Rahmen der Toleranz 
des Keramikresonators.

von Friedrich K. (fiete)


Lesenswert?

Aha! Ok, das ist doch mal eine Ansage. Danke Joachim.

von [Frank] (Gast)


Lesenswert?

@Friedrich:

Der 3.68MHz Takt wird durch den Timer des 8535 erzeugt, der mit einem 
7.37MHz Resonator versorgt wird. Der Resonator ist natürlich etwas 
weniger genau als ein Quarz. Auf dem STK500 ist aber ein diskret 
aufgebauter Oszillator mit Quarzsockel vorhanden, den man auch benutzen 
kann. Näheres in der STK500 Help Datei (STK500.CHM). Da gibt es auch 
einen kompletten Schaltplan des STK500.

von Friedrich K. (fiete)


Lesenswert?

Die Tempertaturabhänigkeit dieses Keramikresonators scheint auch recht 
stark zu sein. Oder andere Umwelteinflüsse, jedenfalls hat auch eine 
Overflow-Korrektur ein besseres, aber kein konstantes Ergebnis 
geliefert...

Mit meiner nächsten Bestellung wird mir auch ein hübscher Quarz frei 
haus geliefert werden, bin mal gespannt, wie es dann tickt.

von Henk (Gast)


Lesenswert?

"ein hübscher Quarz" - sei doch nicht so geizig, ein sortiment der 
gängigen größen hätte es doch auch getan?!

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.