mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Genauigkeit der internen STK500 Frequenz


Autor: Friedrich K. (fiete)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Friedrich K. (fiete)
Datum:

Bewertung
0 lesenswert
nicht 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...
.include "m8def.inc"

.equ F_CPU = 3686400
.equ BAUD = 9600


.def temp1=r16
.def temp2=r17
.def stunden=r18
.def minuten=r19
.def sekunden=r20
.def flag=r21
.def flag2=r25
.def subcount=r22
.def einer=r23
.def zehner=r24

.dseg


.cseg

.org 0x0000
    rjmp  boot

.org OC1Aaddr
    rjmp  CTC_OverFlow

;#################################################################################
;#  AUTOMATIC BAUDRATE CALCULATION  -- AUTOMATIC BAUDRATE CALCULATION  -- AUTOMA #
;#################################################################################

.equ UBRR_VAL   = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; clever runden
.equ BAUD_REAL  = (F_CPU/(16*(UBRR_VAL+1)))     ; Reale Baudrate
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promille
 
.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))       ; max. +/-10 Promille Fehler
  .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
.endif
;#################################################################################


boot:

;Stackpointer Init
    ldi  temp1,HIGH(RAMEND)
    out  SPH,temp1
    ldi  temp1,LOW(RAMEND)
    out  SPL,temp1
;Set Baudrate
    ldi  temp1,HIGH(UBRR_VAL)
    out  UBRRH,temp1
    ldi  temp1,LOW(UBRR_VAL)
    out  UBRRL,temp1
;Set framerate 8 to 8 Bit
    ldi  temp1,(1<<URSEL)|(3<<UCSZ0)
    out  UCSRC,temp1
;Start USART
    sbi  UCSRB,TXEN

;set CTC

  ;set OverFlow value
    ldi  temp1,HIGH(3600-1)
    out  OCR1AH,temp1
    ldi  temp1,LOW(3600-1)
    out  OCR1AL,temp1
  ;init CTC
    ldi  temp1,(1<<WGM12)|(5<<CS10)
    out  TCCR1B,temp1
  ;init CTC
    ldi  temp1,1<<OCIE1A
    out  TIMSK,temp1
  ;set prescaler  
    ldi temp1, 0b00000101  
    out TCCR0, temp1

;clear all:
    clr  temp1
    clr minuten
    clr stunden
    clr flag
    

;interrupts aktiviren

    sei

loop:  in temp1,SREG
    cpi  flag,1
    breq  Ausgabe
    out SREG,temp1
    rjmp  loop


Ausgabe:

    mov  einer,stunden
    rcall  Ascii_Umrechner

    mov  zehner,einer
    rcall  send

    ldi  zehner,':'
    rcall  send

    mov  einer,minuten
    rcall  Ascii_Umrechner

    mov  zehner,einer
    rcall  send

    ldi  zehner,':'
    rcall  send

    mov einer,sekunden
    rcall  Ascii_Umrechner

    mov  zehner,einer
    rcall  send
    ldi  zehner,10
    rcall  send
    ldi  zehner,13
    rcall  send
    
    clr flag
    out SREG,temp1
    rjmp loop

send:
    sbis  UCSRA,UDRE
    rjmp  send
    out  UDR,zehner
    nop
    ret

Ascii_Umrechner:
    cpi  einer,10
    brsh  zehn
    subi  einer,(-'0')
    ldi  zehner,'0'
    rjmp  send
zehn:  cpi  einer,20
    brsh  zwan
    subi  einer,(10-'0')
    ldi  zehner,'1'
    rjmp  send
zwan:  cpi  einer,30
    brsh  dreisg
    subi  einer,(20-'0')
    ldi  zehner,'2'
    rjmp  send
dreisg:  cpi  einer,40
    brsh  virsg
    subi  einer,(30-'0')
    ldi  zehner,'3'
    rjmp  send
virsg:  cpi  einer,50
    brsh  funfz
    subi  einer,(40-'0')
    ldi  zehner,'4'
    rjmp  send
funfz:  subi  einer,(50-'0')
    ldi  zehner,'5'
    rjmp  send



CTC_OverFlow:
    in temp2,SREG
    inc  sekunden
    cpi  sekunden,60
    breq  min
    rjmp  end_uhrwerk
min:  clr  sekunden
    inc  minuten
    cpi  minuten,60
    breq  stun
    rjmp  end_uhrwerk
stun:  clr  minuten
    inc  stunden
    cpi  stunden,12
    brne  end_uhrwerk
    clr  stunden
    rjmp  end_uhrwerk

    
end_uhrwerk:

    ldi  flag,1        ;flag setzen
    out SREG,temp2
    reti


Autor: Friedrich K. (fiete)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Peter R. (pnu)
Datum:

Bewertung
0 lesenswert
nicht 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%.

Autor: Henk (Gast)
Datum:

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

Autor: Friedrich K. (fiete)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Henk (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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. ;-)

Autor: Friedrich K. (fiete)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: H.Joachim Seifert (crazyhorse)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Friedrich K. (fiete)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aha! Ok, das ist doch mal eine Ansage. Danke Joachim.

Autor: [Frank] (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Friedrich K. (fiete)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Henk (Gast)
Datum:

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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.