Forum: Mikrocontroller und Digitale Elektronik Timer Anfängerfrage


von Soder D. (soderdaen)


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

: Bearbeitet durch User
von tryouts (Gast)


Lesenswert?

Hallo,
hast Du sichergestellt, dass Dein µC auch wirklich mit 16MHz läuft?
Stichwort Fusebits...

MfG

von tryouts (Gast)


Lesenswert?

kurzer Nachtrag
 OCR1A   = 62500-1;

Dein Timer ist 8Bit?

von Hubert G. (hubertg)


Lesenswert?

Beim Mega328 ist der Timer1 16Bit.
Um wieviel ist die Sekunde langsamer?

von Soder D. (soderdaen)


Lesenswert?

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.

von Hubert G. (hubertg)


Lesenswert?

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

von Wolfgang (Gast)


Lesenswert?

Soder D. schrieb:
> #define F_CPU 16000000UL

Ein paar von den vielen Nullen sind mit Sicherheit gelogen. Ich tippe 
auf mindesten drei.

von Sascha (Gast)


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.

von Sascha (Gast)


Lesenswert?

Wolfgang schrieb:
> Soder D. schrieb:
>> #define F_CPU 16000000UL
>
> Ein paar von den vielen Nullen sind mit Sicherheit gelogen. Ich tippe
> auf mindesten drei.

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

von S. Landolt (Gast)


Lesenswert?

> Der Takt ist 0,960 Sekunden? Das sind dann 4 Promille zu wenig.
??
Und selbst 4 Promille Abweichung wären für einen Quarz außerordentlich 
schlecht.

von Soder D. (soderdaen)


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.

von Hubert G. (hubertg)


Lesenswert?


von luigi (Gast)


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.

von Wolfgang (Gast)


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"

von Soder D. (soderdaen)


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?

: Bearbeitet durch User
von Gerhard (Gast)


Lesenswert?

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

Gerhard

von Paul B. (paul_baumann)


Lesenswert?

Gerhard schrieb:
> TCCR1B |= (1<<WGM12); // NICHT TCCR1A |= (1<<WGM12);

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...

MfG Paul

von Gerhard (Gast)


Lesenswert?

Nein!
Für den Compiler bedeutet WGM12 nur eine "3".

Gerhard

von Paul B. (paul_baumann)


Lesenswert?

Gerhard schrieb:
> Nein!
> Für den Compiler bedeutet WGM12 nur eine "3".

Na super...
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.

MfG Paul

von S. Landolt (Gast)


Lesenswert?

Aha, 4 %! Sind zwar rund 4.86, aber egal, da hätte man gleich drauf 
kommen müssen. Wo ist die Asche?

von Mein grosses V. (vorbild)


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.

: Bearbeitet durch User
von Paul B. (paul_baumann)


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

von luigi (Gast)


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.

von S. Landolt (Gast)


Lesenswert?

> in BASCOM mit obiger Zuweisung, WGM12 nach tccr1a ...
Und bitte auch noch mit dem Synonym CTC1; da bin ich gespannt.

von Paul B. (paul_baumann)


Angehängte Dateien:

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

von Falk B. (falk)


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ß.

;-)

von S. Landolt (Gast)


Lesenswert?

Ahja, das ist wohl korrekt, CTC1 steht zwar im Datenblatt, ist in 
m328Pdef.inc aber nicht definiert.

von Falk B. (falk)


Lesenswert?

Man kann es auch so sehen. Die Programmiersprache C ist wie ein 
Rasiermesser. Sehr scharf, aber man muss damit umgehen können, um sich 
nicht zu verletzen.

von kotzi (Gast)


Lesenswert?

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

Die Funktioniert nur wenn die Register komplett als Datentyp beschrieben 
werden.

Die AVRLIBC macht das alles über Marcos.

von Paul B. (paul_baumann)


Lesenswert?

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

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

von Falk B. (falk)


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!)

von Paul B. (paul_baumann)


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

von Falk B. (falk)


Lesenswert?

sleep(forever);

von Soder D. (soderdaen)


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
}

von Felix A. (madifaxle)


Lesenswert?

Warum ist da eigentlich ein Semikolon hinter der geschweiften Klammer 
der ISR?

von S. Landolt (Gast)


Lesenswert?

Datenblatt lesen, Table 16-4:
CTC geht nur mit OCR1A (Mode 4, derzeit) oder ICR1 (Mode 12).

von Sascha W. (sascha-w)


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

von Felix A. (madifaxle)


Lesenswert?

Scheint so, dass CTC mit nur WGM12 auf high nur für OCR1A funktioniert 
(ausgehend vom ATmega328).
Wenn du zusätzlich WGM13 setzt, dann geht das auch mit dem Register 
ICR1.

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.