Timer Anfängerfrage

OP #4446730
Lesenswert?

Hallo,

ich bin gerade dabei mir Timer beizubringen.
Ich habe für den Arduino Uno ein Programm geschrieben, um eine LED 
blinken zu lassen. Einse Sekunde an, eine Sekunde wieder aus. Wenn ich 
das blinken aber mit Uhren vergleiche (Windows, Online), dann ist die 
Frequenz nicht exakt die gleiche, der Arduino zieht nach. Kann mir 
jemand sagen woher das kommt bzw. was an meinem Code falsch ist?
1
#include <avr/io.h>
2
#include <stdlib.h>
3
#define F_CPU 16000000UL
4
#include <util/delay.h>
5
#include <avr/interrupt.h>
6

7

8
void setup();
9
void timer_init();
10

11
int main(void)
12
{
13
  setup();                      
14
  timer_init();
15
  PORTB &= ~(1<<DDB5);  
16
  while (1)
17
  {
18
    
19
  }
20
}
21

22
void timer_init()
23
{
24
  TCCR1A |= (1<<WGM12);
25
  TCCR1B |= (1<<CS12);
26
  OCR1A   = 62500-1;
27
  TIMSK1 |= (1<<OCIE1A);  
28
  sei();
29
}
30

31

32

33
ISR(TIMER1_COMPA_vect)
34
{
35
  PORTB = PORTB ^(1<<DDB5);
36
};
37

38

39

40
void setup()
41
{
42
  DDRB   |= (1<<DDB5);
43
}

Vielen lieben Dank
Gast #4446802
Lesenswert?

Also der Code stimmt, unter der Annahme dass der Takt 16Mhz ist.
Allerdings toggelst du den Pin bei jedem Interrupt, die LED ist also 
eine Sekunde an, eine Sekunde aus usw.

Der Takt ist 0,960 Sekunden? Das sind dann 4 Promille zu wenig. Ich 
glaube das ist die Genauigkeit die man erwarten kann.

32768kHz Uhrenquarz wäre die Antwort.

Aber wenn du nur den Timer lernen wolltest: Glückwunsch, den CTC Modus 
kannst du.

Wenn du Lust hast, kannst du ein Potentiometer an den ADC anschließen 
und darüber deinen Compare-Wert feintunen. Aber erwarte keine genau 
gehende Uhr ohne Uhrenquarz.
OP #4446889
Lesenswert?

Hubert G. schrieb:
> Hast du im Arduino einen Originalen Mega328 drin oder ist es ein neuer.
> Wenn neu, dann stimmen die Fuses nicht.

In der tat ist es ein neues Atmega328p, da er sonst allerdings 
funktioniert (wie genau hab ich da aber noch gar nicht beobachtet) habe 
ich mir gedacht die Fuses stimmen schon.

Weiß jemand was die richtigen Fuses sind? Kenn mich da leider auch nicht 
so aus.
Gast #4447191
Lesenswert?

Soder D. schrieb:
> Hubert G. schrieb:
>> Beim Mega328 ist der Timer1 16Bit.
>> Um wieviel ist die Sekunde langsamer?
>
> Ich hatte vorhin das Oszi dran und glaube, dass es 40ms waren.

Ich glaube, daß mal genau messen solltest und uns verläßliche Angaben 
machen solltest. Auch ein Oszi könnte falsch messen. Vielleicht ist eine 
Kontrollmessung mit einem anderen Gerät möglich.
Gast #4447200
Lesenswert?

Sascha schrieb:
> Kann sein dass ich auf dem Schlauch stehe, aber ich lese da 16Mhz ab:
>>> #define F_CPU 16.000.000UL

Eben, aber es sind bestimmt nicht 16,000000 Mhz.

Für eine genau gehende Uhr wird man korrigierend eingreifen müssen.

Damit hätte sich dann auch das Thema Uhrenquarz erledigt, zumindest wenn 
man versucht ist, wegen eines passenden Teilerfaktors darauf zurück zu 
greift.

Beitrag "Die genaue Sekunde / RTC"
OP #4447213
Lesenswert?

luigi schrieb:
> Soder D. schrieb:
>> Hubert G. schrieb:
>>> Beim Mega328 ist der Timer1 16Bit.
>>> Um wieviel ist die Sekunde langsamer?
>>
>> Ich hatte vorhin das Oszi dran und glaube, dass es 40ms waren.
>
> Ich glaube, daß mal genau messen solltest und uns verläßliche Angaben
> machen solltest. Auch ein Oszi könnte falsch messen. Vielleicht ist eine
> Kontrollmessung mit einem anderen Gerät möglich.

Die Fuses habe ich nun richtig eingestellt, aber keine Besserung:

Genaue Oszimessung: Tein=Taus=1,04s
Messung passt also genau zu dem Bild, was mir auch online Uhren oder die 
Windows Uhr vermitteln.


EDIT: Ich habs mal mit _delay_ms(1000); gemacht und jetzt zeigt das Oszi 
genau eine Sekunde an. Wohl doch programmierfehler?
#4447665
Lesenswert?

Paul B. schrieb:
> Merkt das dieser Kompiler nicht, wenn es ein Bit des Namens WGM12 in dem
> Register TCCR1A gar nicht gibt? Das wäre ja ganz großer Pfriem...

Nein. WGM12 ist definiert als Zahl 3. Das hat aber nichts mit dem 
Compiler zu tun.

Der Compiler rechnet 1 << 3 aus und setzt das Ergebnis da rein. Ob das 
Sinn macht, interessiert ihn nicht. Hat ihn auch ncht zu interessieren. 
Was den Inhalt der Daten angeht, ist immer noch der Programmierer der 
Chef. Du könntest auch

1
TCCR1A = 'P' | 'A' | 'U' | 'L'; 
2
TCCR1B = 'B' | 'A' | 'U' | 'M' | 'A' | 'N' | 'N' ;

schreiben.

Das geht den Compiler nichts an.
#4447670
Lesenswert?

Danke für die Erklärung.

Wenn die Bezeichnungen der jeweiligen Bits aus dem Datenblatt hier nur
Schall und Rauch sind, dann tun sich dadurch m.E.n. Stolperfallen en 
Gros auf, die die Arbeit nicht leichter machen.

Ich bin froh (und jetzt noch ein Stück froher), daß ich mich mit solch 
einem Mist nicht herumschlagen muß.

MfG Paul
Gast #4447674
Lesenswert?

Paul B. schrieb:
> Da bin ich heilfroh, daß in z.B. in Bascom die Bit- und Registernamen
> mit denen der .inf-Datei verglichen werden und so ein Fehler sofort
> auffällt, da das Programm dann nicht kompiliert wird.

€Paul: Dann mach mal eine Zeile in BASCOM mit obiger Zuweisung, WGM12 
nach tccr1a, die nicht compiliert wird. Syntax muß natürlich richtig 
sein.
#4447689
Lesenswert?

luigi schrieb:
> €Paul: Dann mach mal eine Zeile in BASCOM mit obiger Zuweisung, WGM12
> nach tccr1a, die nicht compiliert wird. Syntax muß natürlich richtig
> sein.

Das macht er komischerweise. Für TCCR1A aber auch für TCCR1B.

S. Landolt schrieb:
> Und bitte auch noch mit dem Synonym CTC1; da bin ich gespannt.


Das macht er nicht. Hustet und spuckt...

MfG Paul
Angehängte Dateien:
#4447691
Lesenswert?

@ Paul Baumann (paul_baumann)

>Wenn die Bezeichnungen der jeweiligen Bits aus dem Datenblatt hier nur
>Schall und Rauch sind, dann tun sich dadurch m.E.n. Stolperfallen en
>Gros auf, die die Arbeit nicht leichter machen.

Das ist wohl leider wahr. Man kann auch vollkommen falsche Bitnamen auf 
vollkommen falsche Register anwenden, es gibt keinen Compilerfehler!

Die Alternative dazu wäre, die Register und deren Bits als Structs mit 
Bitfeldern anzulegen. Das macht z.B. der C2000 Compiler von TI. Dort 
kann sowas nicht passieren.

>Ich bin froh (und jetzt noch ein Stück froher), daß ich mich mit solch
>einem Mist nicht herumschlagen muß.

;-)
#4447707
Lesenswert?

@Paul Baumann (paul_baumann)

>> Da wären wir bei einer strikten Typprüfung.

>Praktisch wie am Eingang einer Disco: "Du kummst hier net rein,
>weißtu!?"
>;-)

Na wenigstens kannst du über den Witz lachen. Die Typprüfung an der 
deutschen Außengrenze fehlt seit geraumer Zeit . . . (jajajajajaja, er 
hat P........ gesagt!)
#4447719
Lesenswert?

Falk B. schrieb:
> Na wenigstens kannst du über den Witz lachen. Die Typprüfung an der
> deutschen Außengrenze fehlt seit geraumer Zeit . . . (jajajajajaja, er
> hat P........ gesagt!)

Ja, das ist wohl wahr. Vor Allem fehlt der Platz, um neue Arrays 
anzulegen, die Taktfrequenzen werden immer höher und die Timer laufen 
schneller ab, als manch Einer denkt. Aber: Lassen wir das, sonst gibt es 
durch die einschlägigen Quellen gleich einen Interrupt und ich habe 
keine Lust, am
Sonnabend-Nachmittag noch eine Service-Routibne dafür zu machen.

mfG Paul
OP #4447769
Lesenswert?

Gerhard schrieb:
> Du hast NICHT den mode 4 "CTC" eingestellt!
> Mode 4:
>
1
> TCCR1B |= (1<<WGM12); // NICHT TCCR1A |= (1<<WGM12);
2
>
>
> Gerhard


Ahh, natürlich, da hätt ich natürlich auch selber drauf kommen können.
Funktioniert so wunderbar.
Hab das ganze jetzt auch mal mit OCR1B probiert und da geht die LED an 
D5 aber gar nicht mehr aus. OCRnB ist doch das gleiche wie CRnA, den ich 
mit einem anderen Wert befüllen kann....

1
#include <avr/io.h>
2
#include <stdlib.h>
3
#define F_CPU 16000000UL
4
#include <util/delay.h>
5
#include <avr/interrupt.h>
6

7

8
void setup();
9
void timer_init();
10

11
int main(void)
12
{
13
  setup();
14
  timer_init();
15
  PORTB &= ~(1<<DDB5);
16
  while (1)
17
  {
18
    
19
  }
20
}
21

22
void timer_init()
23
{
24
  TCCR1B |= (1<<WGM12);
25
  TCCR1B |= (1<<CS12);
26
  OCR1B   = 62500-1;
27
  TIMSK1 |= (1<<OCIE1B);
28
  sei();
29
}
30

31

32

33
ISR(TIMER1_COMPB_vect)
34
{
35
  PORTB = PORTB ^(1<<DDB5);
36
};
37

38

39

40
void setup()
41
{
42
  DDRB   |= (1<<DDB5);
43
}
#4447790
Lesenswert?

Soder D. schrieb:
> Hab das ganze jetzt auch mal mit OCR1B probiert und da geht die LED an
> D5 aber gar nicht mehr aus. OCRnB ist doch das gleiche wie CRnA, den ich
> mit einem anderen Wert befüllen kann....

Vom Prinzip her schon - aber...
Nur A kannst du verwenden um den Zählumfang im CTC-Mode zu begrenzen. Da 
bei deinem Test nun aber A=0 (default) wird logischer Weise dein Wert in 
B nie erreicht werden.

Sascha

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