Genauigkeit interner Takt

wer

Neues Mitglied
02. Juli 2012
485
0
0
Sprachen
  1. Assembler
Die folgende Blinker sollte die LEDs jeweils eine Sekunde ein und eine Sekunde ausschalten. Es wird der default Takt, also kein externer Quarz verwendet.
Tatsächlich läuft der Blinker in 4 Minuten etwa 6 Sekunden vor. Das ist ein Fehler von 2,5%!!! Liegt das an der Ungenauigkeit des Taktes oder hab ich einen Fehler gemacht?

Code:
.NOLIST
.INCLUDE "m168padef.inc"
.LIST

.EQU	F_CPU	= 1000000		; Systemtakt in Hz


.DEF	A	= R16
.DEF	ssave	= R15
.DEF	leds	= R20
.DEF	cnt	= R21

.ORG 0
	rjmp	Reset

.org OC0Aaddr
        rjmp    OC0A_ISR	       ; Timer Overflow Handler
 
.ORG INT_VECTORS_SIZE

Reset:
	ldi	A, LOW(RAMEND)
	out	SPL, A
	ldi	A, HIGH(RAMEND)
	out	SPH, A
 
	ldi	A, 0xFF			; Port B auf Ausgang
	out	DDRB, A
 
	ldi	leds, 0xFF
	out	PORTB, leds

; Berechnung für F_CPU = 1000000
; 1000000 = 64*125*125
 
 	ldi	cnt, 124		; 125 = (0..124)
	out	OCR0A, cnt
	inc	cnt

	ldi	A, (1<<OCIE0A)		; Interrupt bei Compare Match A
	sts	TIMSK0, A
 
 	ldi	A, (1<<WGM01)		; CTC mode
	out	TCCR0A, A
	ldi	A, (1<<CS01)|(1<<CS00)	; Teiler 64
	out	TCCR0B, A
 
	sei
 
MainLoop:
	rjmp	MainLoop

OC0A_ISR:
	in	ssave, SREG
	dec	cnt
	brne	goon	
	ldi	cnt, 125
	com	leds
	out	PORTB, leds
goon:
	out	SREG, ssave
	reti

Edit: Setze ich den Comparewert auf 125 statt 124, dann kommt das ganz gut hin. Aber das ist meiner Meinung nach falsch, oder?
 
Hallo!

Mit dem internen Taktgeber wirst du nie (selten) genaue Werte erzielen können. Da muss schon ein externer Quarz her.

Ob vielleicht noch zusätzlich ein Fehler im Programm ist, kann ich dir leider nicht sagen, da ich Assembler nicht beherrsche.


Gruß
Merzi
 
Hallo!
Mit dem internen Taktgeber wirst du nie (selten) genaue Werte erzielen können. Da muss schon ein externer Quarz her.
Ob vielleicht noch zusätzlich ein Fehler im Programm ist, kann ich dir leider nicht sagen, da ich Assembler nicht beherrsche.

Daß ich keine genauen Ergebnisse bekomme ist mir klar, aber 2,5% ist verdammt viel, oder?
 
Ich würde garnicht sagen, dass die 2,5% viel sind. Ich selbst hab auch mal ein Programm erstellt, welches im Sekundentakt hochzählen soll und hatt nach einer Minute schon 1-2 Sekunden Abweichung.
 
Hallo zusammen!

Vielleicht helfen euch ja die Diagramme weiter, die auch im Datenblatt zu finden sind.
Mega168_int-OSC.gif

Dort kann man sehr schön die Unterschiede des internen Oszillators erkennen, wenn es z.B. nur um die Umgebungstemperatur oder die Versorgungsspannung geht! :wink:

Solche Abweichungen, wie ihr sie beschrieben habt, sind also gar nicht so selten...... und sogar bekannt.


Grüße,
Cassio
 
vorab:
-Stackpointer brauchste nicht reinitialisieren
-Du läßt das Datenrichtungsregister von PortB über R16, und das Datenregister von PortB über R20 je auf 255 setzen. Direkt hintereinander, mit 2 LDI. Du könntest die durchaus über dasselbe Rechenregister setzen, mit nur einem LDI.
(-strenggenommen mußt Du in der ISR das SREG nicht sichern, da es außerhalb dieser (nicht unterbrechbaren) ISR nach dem SEI nie wieder verwendet wird. )
-zum Toggeln der LEDs könntest Du auch einfach jedesmal 255 in das PIN-Register (von PortB) schreiben; würde in der ISR das COM sparen...
aber das hat nichts mit Deinem Problem zu tun...

Du hast folgendes gerechnet:
64(Prescaler)*125(Compare)*125(Software-Zähler)=1.000.000 (was der Taktfrequenz in Herz entspricht), insofern richtig.

Wie geht das mit dem Compare?
Wenn der Counter den Comparewert erreicht (also OCR0A=TCNT0) , wird TCNT auf 0 gesetzt. Dein Timer soll aber 125 Schritte machen. Von 0 auf 1, von 1 auf 2, ... von 124 auf 125 (was dann gleich 0 sein soll, und den Interrupt auslösen soll).
OCR0A=125 sollte also stimmen.

LotadaC
 
Du hast folgendes gerechnet:
64(Prescaler)*125(Compare)*125(Software-Zähler)=1.000.000 (was der Taktfrequenz in Herz entspricht), insofern richtig.

Wie geht das mit dem Compare?
Wenn der Counter den Comparewert erreicht (also OCR0A=TCNT0) , wird TCNT auf 0 gesetzt. Dein Timer soll aber 125 Schritte machen. Von 0 auf 1, von 1 auf 2, ... von 124 auf 125 (was dann gleich 0 sein soll, und den Interrupt auslösen soll).
OCR0A=125 sollte also stimmen.

LotadaC

Von 0..125 sind es 126 Durchläufe. Im Simulator sieht man schön, daß die 0 einen Takt nach der 125 kommt.
 
eben nicht, wenn TCNT OCR0A (125) erreicht wird er gelöscht. CTC - clear Timer at compare match eben.
Ich habs jetzt extra mal durch den Simulator gejagt:
7998 Systemtakte nach dem Starten des Timers ist dieser noch 124
7998.png
einen Programmschritt weiter landest Du bei 8003:
8003.png
Über die IVT wird jetzt die ISR angesprungen, der Timer ist jetzt schon wieder 0.
Innerhalb dieser 5 Systemtakte ist der Timer also von 124 auf 0 gesprungen. Aufgrund des Prescalers kann aber nur ein regulärer Timer-Takt stattgefunden haben.
 
eben nicht, wenn TCNT OCR0A (125) erreicht wird er gelöscht. CTC - clear Timer at compare match eben.
Ich habs jetzt extra mal durch den Simulator gejagt:
7998 Systemtakte nach dem Starten des Timers ist dieser noch 124
Anhang anzeigen 4866
einen Programmschritt weiter landest Du bei 8003:
Anhang anzeigen 4865
Über die IVT wird jetzt die ISR angesprungen, der Timer ist jetzt schon wieder 0.
Innerhalb dieser 5 Systemtakte ist der Timer also von 124 auf 0 gesprungen. Aufgrund des Prescalers kann aber nur ein regulärer Timer-Takt stattgefunden haben.

Du hast doch OCR0A gar nicht mit 125 geladen, sondern mit 124.
 
Hi
In der Regel ist es so, das 125 Schritte mit einem Zähler bis 124 erreicht werden. Wenn ich 256 Werte darstellen kann ist der höchste 255, da die 0 auch einen Wert darstellt. Also immer dran denken, ein Computer fängt bei 0 an zu zählen. Wir allerdings, warum auch immer, bei 1.
Die Systemtakte kannst du vernachlässigen, denn du benutzt einen Interrupt. Und das bedeutet, der Timer arbeitet unabhängig vom Programm. Er zählt bis zum Vergleichswert, setzt ein Bit und fängt wieder bei 0 an. Da interressiert kein Sprung zur IVT oder sonstwohin. Der Interrupt wird allerdings zur Zykluszeit aufgeschlagen und da kommen die Sprünge zur IVT und zur ISR natürlich zur Geltung. Aber den Timer interressiert das nicht. Er ist weiterhin damit beschäftigt, seine eingehenden Impulse zu zählen und die eingestellte Zählgrenze zu überwachen.
Gruß oldmax
 
Das ist alles klar, ich bin fälschlicherweise davon ausgegangen, daß das OCF0A high geht, wenn TCNT0=OCR0A. Das ist aber nicht der Fall. Die Gleichheit löst zwar das entsprechende Ereignis aus, aber das Flag geht erst mit dem nächsten Timertakt high.
Datenblatt 15.5 schrieb:
Whenever TCNT0 equals OCR0A or OCR0B, the comparator signals a match. A match will set the Output Compare Flag (OCF0A or OCF0B) at the next timer clock cycle.
Insofern ist also OCR0A=TOP (steht ja auch so im Datenblatt), und 124 (in diesem Fall) der rechnerisch korrekte Wert. Genau das zeigt ja auch der Simulator.

Also ignoriert meine vorherigen Abhandlungen - es scheint dann an der Abweichung der Taktfrequenz zu liegen...
 
Als abschließende Bemerkung:

Ich habe das ganze noch einmal mit Quarz probiert und finde keine wahrnehmbare Abweichung mehr innerhalb der ursprünglich beobachteten 4 Minuten. Da wird man dann schon eher Tage warten müssen. D.h. die 2,5% sind eine Ungenauigkeit mit der man rechnen muß, obwohl die Dokumentation eher bei 1% liegt. Das ganze habe ich getestet in einer STK500 Umgebung.
 
Obacht!
Die "Factory Calibration" liegt (bei 8MHz, 3V Vcc und 25^C) bei +/-10%.
Du kannst 1% erreichen, indem Du den internen RC kalibrierst (oder hast Du das bereits getan?). Siehe Datenblatt des Controllers Seite 34ff und Seite 323.

Edit: Irgendwie ist meine Version vom Datenblatt etwas länger - im Link sind die entsprechenden Seiten dann S. 32ff und S. 309.
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)