Genauigkeit der internen STK500 Frequenz

OP #1549933
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
#1550150
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
OP #1550665
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
OP #1553415
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
#1553447
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%.
OP #1553466
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?
Gast #1553481
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. ;-)
Gast #1553663
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.
OP #1553672
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.

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