Forum: Mikrocontroller und Digitale Elektronik TIMER1 ist viel zu schnell


von Tobias R. (glasses)


Angehängte Dateien:

Lesenswert?

Hallo!
Auf meinem Atmega32 hab ich schon einige male erfolgrich mit den Timern 
gearbeitet, doch diesmal will es mir mit meinem Atmega 8 nicht gelingen 
;(

Es geht draum, eine ISR(TIMER1_COMPA_vect) einmal pro Sekunde ausführen 
zulassen. Wenn ich das richtig verstanden habe, benutzt der µC seinen 
internen 1MHz Takt??!  (Oder müssen da ncoh irgendwelche Fuses 
umgestellt werden?)

Meine Rechnung:
(Quelltakt / Vorteiler)/ OCR1A = (Anzahl der Takte/sec am Ausgang/ISQ)
(1000000Hz / 1024 )/     977 =     1/sec

Konfiguriert hab ich das Ganze daher so;
1
int main(){
2
TCCR1B |= 0b00000101;
3
TCCR1B &= 0b11111101;
4
TCCR1A |= 0b00000010;
5
TCCR1A &= 0b11111110;
6
OCR1A = 977;
7
TIMSK  |= 0b00010000;
8
sei();
9
10
while(1){}
11
return 0;}
12
13
ISR(TIMER1_COMPA_vect){
14
      //LED toogle...}

Mein Hauptproblem besteht draing, das in der Praxis die LED mehr als 
zweimal in der Sekunde geschaltet wird, obwohl ich die Obergrenze OCR1A 
schon = 65500; gesetzt habe.

Das ganze möchte ich mit GCC relisieren.
Vielen Danke für Eure Hilfe!!

: Bearbeitet durch User
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Tobias Riegner schrieb:
> Wenn ich das richtig verstanden habe, benutzt der µC seinen internen
> 1MHz Takt??!  (Oder müssen da ncoh irgendwelche Fuses umgestellt
> werden?)
Du kannst genau diese Taktquelle mit Fuses einstellen. Und dann gibt es 
noch die CLKDIV8. Wie sind deine Fuses eingestellt?

von norbi (Gast)


Lesenswert?

Schau dir mal an, welchen Timer Modus du da im TCCR1A setzt. CTC ist das 
nicht und der Timer kann auch nicht höher als 511 laufen, also auch 
nicht den im OCR1A gesetzten Wert von 977 erreichen.

von Oliver S. (oliverso)


Lesenswert?

Tausendmal schreiben: Du sollst zur Initialiserung von 
Configurationstsregistern keine Bitfelder benutzen.

Also schreib das um in eine lesbare Form (1<< Bitname), und such den 
Fehler.

Ach ja, CLKDIV8 hat ein Mega8 nicht, und weiter als bis 511 kann Timer 1 
auch zählen (gibt es überhaupt Mikrocontroller mit 9-Bit Timern?). Daran 
liegt es also nicht.

Oliver

von BattMan (Gast)


Lesenswert?

Das macht man so:
1
#define PRESCALER1    ((1 << CS12)|  (1 << CS10))  
2
3
// This is the central clock with 1 Hz (Not very stable, due to internal Clock source
4
  TCCR1B = PRESCALER1 | (1 << WGM12);// Prescaler 1024 and CTC Mode
5
  TCNT1 = 0;        // Set to zero
6
  OCR1A = (F_CPU/1024);      // 1 second value = 976

von norbi (Gast)


Lesenswert?

Oliver S. schrieb:
.... und weiter als bis 511 kann Timer 1
> auch zählen (gibt es überhaupt Mikrocontroller mit 9-Bit Timern?). Daran
> liegt es also nicht.

Ach? Noch einer, der ein Datenblatt nicht richtig lesen kann?

von Edi R. (edi_r)


Lesenswert?

Ich habe gerade nachgeschaut: Auch beim ATmega8 ist der Timer1 ein 
16-Bit-Timer.

von norbi (Gast)


Lesenswert?

Edi R. schrieb:
> Ich habe gerade nachgeschaut: Auch beim ATmega8 ist der Timer1 ein
> 16-Bit-Timer.

Und mit der vom TE erstellten Konfiguration?

von Edi R. (edi_r)


Lesenswert?

Jetzt mach doch kein Geheimnis draus und klär uns endlich auf, was Du 
meinst. Oder müssen wir alle erst die Bits in den Registern aufdröseln?

von norbi (Gast)


Lesenswert?

Edi R. schrieb:
> Jetzt mach doch kein Geheimnis draus und klär uns endlich auf, was Du
> meinst.
:)) Nein. Das würde doch dem Geist diesen Forums widersprechen. 
(Vielleicht später, wenn die Lösung nicht auftauscht oder ich doch 
falsch liegen sollte)

> Oder müssen wir alle erst die Bits in den Registern aufdröseln?
Ja, wenigstens der TE soll es tun ;-)

von lesbarer code (Gast)


Lesenswert?

Oliver S. schrieb:
> Also schreib das um in eine lesbare Form (1<< Bitname)

Dann aber bitte nicht diese << Dinger. Ab 4Bit kann das kein Mensch mehr 
vernünftig lesen.

Man nimmt entsprechende konstanten. Das wird bei allen ausser ATMEL in 
den Headern angeboten.
Und wer gar nicht ohne << kann, versteckt es in einem #define.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

lesbarer code schrieb:
> Oliver S. schrieb:
>> Also schreib das um in eine lesbare Form (1<< Bitname)
>
> Dann aber bitte nicht diese << Dinger. Ab 4Bit kann das kein Mensch mehr
> vernünftig lesen.

Also ich mag diese Dinger. Ich hab mir auch angewöhnt, alle Bits 
anzugeben, und die nicht gesetzten dann mit (0 << Bitname) 
hinzuschreiben. Dmait ist auf einen Blick klar was gesetzt ist und was 
nciht, und ich kann auch kein Bit vergessen (bzw. bin gezwungen über 
jedes Bit nachzudenken)

Wie würdest du nicht gesetzte Bits hinschreiben?

von norbi (Gast)


Lesenswert?

BattMan schrieb:
> Das macht man so:
>
>
1
> #define PRESCALER1    ((1 << CS12)|  (1 << CS10))
2
> 
3
> // This is the central clock with 1 Hz (Not very stable, due to internal 
4
> Clock source
5
>   TCCR1B = PRESCALER1 | (1 << WGM12);// Prescaler 1024 and CTC Mode
6
>   TCNT1 = 0;        // Set to zero
7
>   OCR1A = (F_CPU/1024);      // 1 second value = 976
8
>

Wenn, dann würd ich statt PRESCALER1 als Name doch lieber PRESCALER1024 
verwenden oder irgendwas, aus dem der Wert des Prescalers direkt 
ersichtlich ist ;-)

von Tobias R. (glasses)


Lesenswert?

@ lkmiller: Die Fuses sind folgendermaßen eingestellt: (SUT: 10 
CKSEL:0001 ) An dem CLKDIV8 Hab ich nicht dran rumgeschraubt, weil dir 
da ein anderer Beitrag wiedersprochen hat.

@ norbi: CTC, sprich ClearTimeronCompare soll ja aktiviert sein, damit 
der Timer nach dem erfolgreichem Vergleich mit OCR1A wieder 
zurückgesetzt wird. Das Zählregister des Timer1 sollte beim Atmega8 
16Bit groß sein, deshalb hab ich die maximale Obergrenze auch als 65535 
angenommen.

@oliverso:   Ich hoffe das ist so lesbar genug, bin bisher nur mit der " 
direkt in das 8-Bit Register reinschreib - Methode" vertraut.

TCCR1B |= 0b00000101; //   (1<<CS12)^(1<<CS13) //Vorteiler: 1024
TCCR1B &= 0b11111101; //   (0<<CS11)           //Vorteiler: 1024
TCCR1A |= 0b00000010; //   (1<<WGM10)          // CTC Modus aktiv
TCCR1A &= 0b11111110; //   (0<<WGM11)         // CTC Modus aktiv
OCR1A = 977;          //  Vergleichswert 977  Wie gesagt auch bei =65500 
immer noch viel zu schnell
TIMSK  |= 0b00010000; //  (1<<OCIE1A)      //Interrupt für Compare1A 
freigeben
TCNT1 =0;    // Sicherheitshalber auch gesetzt.

Das Problem besteht weiterhin. Inzwischen bin ich mir sicher, dass ich 
die Fuses reichtig gesetzt habe damit der interne CPU-Takt 1000000 
verwendet wird. (SUT: 10 CKSEL:0001 )

Die Obergrenze habe ich jetzt mit 65535 angegegeben, um die ISr 
möglichst langsam zu bekommen. Aus dem selben Grund ist mein gewählter 
Vorteiler 1024.

Man könnte daher bei gegeben Werten folgende Rechnung aufstellen:

(1000000Mhz/1024)/65535 = 0.0149 pro Sekude ein Interrupt. => Alle 67 
Sekunden ein Interrupt.

Dem ist aber leider nicht so, die LED blinkt einmal in der Sekunde => 
Zwei Interrupts pro Sekunde. Das ist mir immer noch viel zu schnell!

Danke für die bisherigen Antworten! Bitte entschuldigt meine späte 
Antwort, ich hab in der Nacht tatsächlich auch noch geschlafen ;)

von spess53 (Gast)


Lesenswert?

Hi

>TCCR1A |= 0b00000010; //   (1<<WGM10)          // CTC Modus aktiv
>TCCR1A &= 0b11111110; //   (0<<WGM11)         // CTC Modus aktiv

Das ist kein CTC, sondern 'PWM, Phase Correct, 9-bit'. Für CTC muss 
WGM12 in TCCR1B gesetzt werden.

MfG Spess

von Tobias R. (glasses)


Lesenswert?

Vielen Dank spess53!!!!
Das war der entscheidende Hinweis! Das Register war offenbar falsch 
eingestellt!!
Viele, Vielen Dank an Alle!!!

von spess53 (Gast)


Lesenswert?

Hi

>Das war der entscheidende Hinweis! Das Register war offenbar falsch
>eingestellt!!

Den Hinweis hättest du auch aus dem Datenblatt bekommen. Da gibt es eine 
nette Tabelle mit den einzelnen Timermodi.

MfG spess

von Cyblord -. (cyblord)


Lesenswert?

spess53 schrieb:
> Hi
>
>>Das war der entscheidende Hinweis! Das Register war offenbar falsch
>>eingestellt!!
>
> Den Hinweis hättest du auch aus dem Datenblatt bekommen. Da gibt es eine
> nette Tabelle mit den einzelnen Timermodi.

War doch auch nicht sein Fehler. Lag doch am Register. Das war doch 
falsch eingestellt...

von Dieselwolf (Gast)


Lesenswert?

Cyblord schrieb:
>War doch auch nicht sein Fehler. Lag doch am Register. Das war doch
>falsch eingestellt...

Das mit der Ironie mußt Du aber noch ein wenig üben....

von Tobias R. (glasses)


Lesenswert?

Das ist leider das einzige, was ich an diesem Forum nicht schätze die 
Überheblichkeit Einzelner. Natürlich liegt der Fehler nie an dem µC 
sondern an dem Benutzer, doch ich selbst konnte den Fehler leider nahe 
zu unmöglich alleine lösen, weil in der "AVR-Formelsammlung" meiner 
Schule scheinbar ein Fehler steckt. Wenn keine Probleme durch Menschen 
auftreten würden, wäre das ganze Forum schließlich überflüssig.

Daher möchte ich diese einzelnen Personen, welche gleich auf die 
Anfänger einhacken dazu auffordern den Neuankömmlingen mehr verständniss 
entgegen zu bringen.

von norbi (Gast)


Lesenswert?

Tobias Riegner schrieb:
> sondern an dem Benutzer, doch ich selbst konnte den Fehler leider nahe
> zu unmöglich alleine lösen, weil in der "AVR-Formelsammlung" meiner
> Schule scheinbar ein Fehler steckt. Wenn keine Probleme durch Menschen

Alles, was nicht vom Hersteller direkt kommt, kann Übertragungsfehler 
enthalten. Formelsammlungen, Bücher, Internetseiten, ...

Also immer querchecken mit dem Datenblatt des Herstellers und auch da 
können noch in ganz seltenen Fällen Fehler versteckt sein.

Also google dir das Datenblatt für den ATMega8 von ATMEL und versuche 
den Unterschied zur Formalsammlung der Schule nachzuvollziehen.

von Cyblord -. (cyblord)


Lesenswert?

Tobias Riegner schrieb:
> doch ich selbst konnte den Fehler leider nahe
> zu unmöglich alleine lösen, weil in der "AVR-Formelsammlung" meiner
> Schule scheinbar ein Fehler steckt.
Also wieder andere Schuld? Was hat dich daran gehindert selbst ins 
Datenblatt zu schauen?

> Daher möchte ich diese einzelnen Personen, welche gleich auf die
> Anfänger einhacken dazu auffordern den Neuankömmlingen mehr verständniss
> entgegen zu bringen.
Nahezu jeder Neuankömmling wird aufgefordert mal einen Blick ins DB zu 
werfen. Tuts jemand? Hab ich noch nie gesehen. Also bleiben beides wohl 
unerfüllbare Wünsche.

von Mike (Gast)


Lesenswert?

Tobias Riegner schrieb:
> @oliverso:   Ich hoffe das ist so lesbar genug, bin bisher nur mit der "
> direkt in das 8-Bit Register reinschreib - Methode" vertraut.
>
> TCCR1B |= 0b00000101; //   (1<<CS12)^(1<<CS13) //Vorteiler: 1024
> TCCR1B &= 0b11111101; //   (0<<CS11)           //Vorteiler: 1024

Das macht das Leben nicht leichter, weil todsicher irgendwann die 
Komentare nicht mitgeändert werden und nichts mehr zusammen paßt. Warum 
schreibst du nicht direkt z.B.
  TCCR1B |= (1<<CS12)|(1<<CS13) //Vorteiler: 1024
  TCCR1B &= ~(0<<CS11)

von Mike (Gast)


Lesenswert?

Tobias Riegner schrieb:
> Daher möchte ich diese einzelnen Personen, welche gleich auf die
> Anfänger einhacken dazu auffordern den Neuankömmlingen mehr verständniss
> entgegen zu bringen.

Dann solltest aber auch du "Verständniss" groß schreiben ;-)

Und jedem Neuankömmling steht es natürlich frei, hier vor seinem ersten 
Post ein bisschen im Forum zu stöbern, um um die beliebtesten 
Fettnäpfchen einen Bogen schlagen zu können.

von Rainer B. (katastrophenheinz)


Lesenswert?

Mike schrieb:
>   TCCR1B &= ~(0<<CS11)
Hi, Mike, gerade erst aufgestanden ;-)? Der Ausdruck oben ist ziemlich 
sinnfrei. Normalerweise setzt man alle 0 und 1 in einem Rutsch, also 
etwa so, wie BattMann schon vor ca 30 Stunden gepostet hat.
1
#define PRESCALER1024    ((1 << CS12) |  (1 << CS10))  
2
TCCR1B = PRESCALER1024  | (1 << WGM12);// Prescaler 1024 and CTC Mode

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.