Forum: Mikrocontroller und Digitale Elektronik Timer erzeugt die 3fache Frequenz


von Chris (Gast)


Lesenswert?

Hallo Leute, ich stehe vor einem sehr komischen Problem.
Ich will mit zwei Timern im Mega 8 zwei Frequenzen erzeugen. Das hat 
bisher auch immer gut funktioniert.
Seit ein paar Tagen aber spuckt er mir immer die DREIFACHE Frequenz aus, 
im vergleich zur Berechneten.
Dabei macht es keinen Unterschied ob ich Timer1 oder Timer2 verwende.

Initialisiert wird so:
1
void timer1_init (uint16_t freq) 
2
{ 
3
    // Prescaler auf 1 
4
    TCCR1A = 0; 
5
    TCCR1B = (1 << WGM12) | (1 << CS10); 
6
7
    // OutputCompare1A Register setzen 
8
    OCR1A = (uint16_t) ((uint32_t) F_CPU / (2*freq) -1); 
9
  
10
    // OutputCompare1A Interrupt aktivieren 
11
    TIMSK |= (1 << OCIE1A); 
12
}
Rufe ich jetzt timer1_init(10000) auf, erzeugt er mir eine Frequenz von 
30kHz statt eine mit 10kHz. Die Formel habe ich in gleicher Form auch 
sonst verwendet, da hat es Problemlos funktioniert.
An der Formel liegt es meines Erachtens nicht, denn wenn ich den OCR 
wert von hand berechne (für 30000 OCR auf 121) erhalte ich die 3Fache 
Frequenz

Ich kann zwar damit Leben aber ich finde es doch sehr verwunderlich.

Die Fuse Bits sind richtig gesetzt auf externes Quarz, die F_CPU im 
Makefile stimmt auch.

Hat einer von euch eine Idee an was das liegen könnte?
Vielen Dank für eure Hilfe
Christian

von Karl H. (kbuchegg)


Lesenswert?

Was machst du im Output Compare Interrupt ?

von Chris (Gast)


Lesenswert?

Hallo Karl heinz!
Danke für die schnelle Rückmeldung.

Im Interrupt toggle ich nur nen Ausgang:
1
SIGNAL(SIG_OUTPUT_COMPARE1A) 
2
{ 
3
    PORTD ^= (1<<PD7); 
4
}

auch im main lass ich die Finger von irgendwelchen Registern die den 
Timer beeinflussen könnten. main besteht momentan nur aus einer endlos - 
Schleife...

Für weitere Ideen wäre ich sehr dankbar.

von Marvin M. (Gast)


Lesenswert?

Hast Du irgendeine Möglichkeit, Dir den Inhalt von OCR1A ausgeben zu 
lassen? Wenn der richtig berechnet ist, dann gibts noch die Möglichkeit, 
dass doch irgendetwas an den Fuses nicht stimmt.
Oder der Quarz hat einen Schuß, den würde ich mal tauschen, 
Kondensatoren am Quarz checken, Abblockkondensatoren an der 
Spannungsversorgung checken.

von Chris (Gast)


Lesenswert?

Okay also ich habe mir gerade OCR1AH und OCR1AL (16Bit register) 
nacheinander an der seriellen schnittstelle ausgeben lassen:

in dezimal:
OCR1AH = 1
OCR1AL = 111
das macht zusammen meines erachtens 256 + 111 = 367

Für 367 als OCR-Wert sollte damit laut Datenblatt eine Frequenz von 
10.017Hz rauskommen:

(FCPU = 7372800)
f_oc = FCPU / (2  1  (1+367)) = 10,017 Hz
                   ^-Prescaler = 1

Gemessen mit dem Frequenzzähler sinds aber genau 30,053 Hz(also fast 
exakt das 3 fache)

Wenn ich den OCR manuell auf 121 setze, bekomme ich umgekehrt statt 
30.216 Hz  wieder 10.0xx Hz raus... komische sache.

Denkst du an irgendwelche speziellen FuseBits die nicht passen?
Der CPU Takt läuft richtig, da sonst die serielle Übertragung sonst ja 
auch nicht funktionieren würde...

von Karl H. (kbuchegg)


Lesenswert?

Sehr eigenartig das Ganze:
* Fakt: Der Timer kann nicht schneller laufen als der
  Systemtakt d.h. ich glaube nicht, dass das irgendwas
  mit den Fusebits zu tun hat.
* Ein Faktor von 3 ist ungewöhnlich. Wenns wenigstens irgendeine
  2-er Potenz wäre.

Hast du schon mal mit anderen Zahlenwerten für OCR probiert?
Ich denke da zb. an 255 und 256 (OCR1H == 0 und OCR1H == 1).
Dass vielleicht beim Beschreiben von OCR irgendwas passiert.

Hast du dir schon mal den Ausgangspin am Oszi angesehen?

von Johannes M. (johnny-m)


Lesenswert?

10.017 und 10,017 sind zwei völlig unterschiedliche Dinge. Bitte 
entscheide Dich für die in Deutschland gebräuchliche ODER die im 
angelsächsischen Raum verbreitete Schreibweise, aber nicht beides 
durcheinander...

Und damit man Dir konkret helfen kann, schicke bitte mal etwas mehr von 
Deinem Programm. Hast Du mal ein "UL" hinter die 7372800 in der 
Frequenzdefinition geschrieben?

von Chris (Gast)


Angehängte Dateien:

Lesenswert?

Auch ein neuer ATMEGA8 bringt nix. Gleiches verhalten wie zuvor. Fuses 
wurden  auf externes Quarz mit 3-8 MHZ , slowly rising power gesetzt 
(siehe Screenshot).
Takt läuft definitiv richtig, ein _delay_ms funktioniert nämlich 
korrekt.
Nur die Timer wollen nicht. sehr komisch..

von Karl H. (kbuchegg)


Lesenswert?

Johannes M. wrote:
> 10.017 und 10,017 sind zwei völlig unterschiedliche Dinge. Bitte
> entscheide Dich für die in Deutschland gebräuchliche ODER die im
> angelsächsischen Raum verbreitete Schreibweise, aber nicht beides
> durcheinander...

Meine Meinung:
Am besten überlässt man die Tausenderpunkte den Kaufleuten.
Stiften nur Verwirrung.

von Johannes M. (johnny-m)


Lesenswert?

Karl heinz Buchegger wrote:
> Meine Meinung:
> Am besten überlässt man die Tausenderpunkte den Kaufleuten.
> Stiften nur Verwirrung.
Richtig. Ich verwende sie im deutschen auch nicht. Allerdings lese und 
schreibe ich viel auf englisch, wo dann das 1000er-Komma und der 
Dezimalpunkt angesagt sind. Und der OP hat beide Schreibweisen gründlich 
durcheinandergewürfelt. Ist ja nicht so, dass ich es nicht auch so 
kapiert hätte, nur wenn man einmal so schludrig anfängt, dann nimmt das 
i.d.R. kein gutes Ende. "Wehret den Anfänge(r)n" heißt es doch so 
schön...

von Chris (Gast)


Lesenswert?

@ Johannes M.:
-Entschuldigung für die Schreibweise, ich habe nicht alle Werte 
umgeändert (Copy-Paste aus zwei verschiedenen Programmen) der 
Unterschied ist mir aber völlig bewusst, von Hand wäre das nicht 
passiert...
-Im Makefile ist F_CPU wie folgt definiert:
1
F_CPU = 7372800
also OHNE UL (was meiner Meinung nach auch korrekt ist)


Ich habe jetzt folgende Testreihe aufgestellt:

OCR  | f-Berechnet | (f-berechnet * 3) | f-gemessen
-----+-------------+-------------------+-----------
255  | 14,400kHz   | 43,200kHz         | 43,203kHz
256  | 14,343kHz   | 43,029kHz         | 43,035kHz
511  |  7,200kHz   | 21,600kHz         | 21,602kHz
512  |  7,185kHz   | 21,555kHz         | 21,559kHz

Meine Beobachtungen:
* Die Register OCR1AH und OCR1AL enthalten immer die richtigen 
OCR-Werte.
* Die Abweichung von (f-berechnet * 3) und f-gemessen ist so gering dass 
es  sich dabei um keinen Zufall handeln kann.

Habe mein Programm jetzt auf das wesentliche reduziert und im Anhang 
beigefügt. Vielleicht kann sich das ja mal jemand von euch anschauen...
Ich wäre für jeden weitern Tipp dankbar!

von Chris (Gast)


Angehängte Dateien:

Lesenswert?

Tut mir leid das mit dem Anhang hat wohl nicht geklappt. Noch ein 
Versuch.

von Benedikt K. (benedikt)


Lesenswert?

Die Software sieht OK aus, bis du sicher, dass der Quarz nicht auf der 
3x Frequenz schwingt ?

von Johannes M. (johnny-m)


Lesenswert?

Benedikt K. wrote:
> Die Software sieht OK aus, bis du sicher, dass der Quarz nicht auf der
> 3x Frequenz schwingt ?
Das wäre so oder so ähnlich jetzt auch meine Vermutung gewesen. Das 
Programm an sich lässt so etwas nicht zu, und wenn F_CPU im makefile 
angegeben ist, ist das auch OK. Ein Faktor 3 kann dann eigentlich nur 
von außen kommen. Und ein Quarz, der auf dem 3. Oberton schwingt, ist 
nicht ungewöhnlich. Quarze ab 20 MHz arbeiten praktisch alle auf dem 3. 
bzw. 5. Oberton, und bei entsprechender Fehlanpassung der 
Oszillatorbeschaltung kann sowas durchaus passieren.

von Chris (Gast)


Lesenswert?

Ja da bin ich definitiv sicher, habe gerade nochmal mit dem 
Frequenzzähler nachgemessen. Das Quarz schwingt mit 7372800 Hz.
ausserdem würde bei falsch eingestelltem takt die serielle übertragung 
wohl auch nicht funktionieren.
ich habe diesen codeschnipsel schon in zig anderen Programmen verwendet 
in denen sie anstandsloß gelaufen sind.
naja ich werde jetzt doch mal die kondensatoren und das quarz 
austauschen, sonst hab ich ja schon so gut wie alles probiert... danke 
trotzdem

von Johannes M. (johnny-m)


Lesenswert?

Chris wrote:
> Ja da bin ich definitiv sicher, habe gerade nochmal mit dem
> Frequenzzähler nachgemessen. Das Quarz schwingt mit 7372800 Hz.
Na dann...

> ausserdem würde bei falsch eingestelltem takt die serielle übertragung
> wohl auch nicht funktionieren.
Da in Deinem Code nichts von einer seriellen Übertragung steht, hättest 
Du das vielleicht mal eher sagen können...

> ich habe diesen codeschnipsel schon in zig anderen Programmen verwendet
> in denen sie anstandsloß gelaufen sind.
> naja ich werde jetzt doch mal die kondensatoren und das quarz
> austauschen,...
Wenn er doch mit 7,3728 MHz läuft, bringt das auch nichts.

EDIT:
Sehe grad, dass Du tatsächlich die serielle Übertragung in dem Posting 
von 12:53 erwähnt hattest. Hab ich übersehen.

von Benedikt K. (benedikt)


Lesenswert?

Mach mal folgendes:
    TCCR1A = 0;
    TCCR1B = (1 << WGM12) | 5;

    // OutputCompare1A Register setzen
    OCR1A = 3599;

    // OutputCompare1A Interrupt aktivieren
    TIMSK |= (1 << OCIE1A);


Und hänge eine LED an den Pin. Die müsste jetzt mit 1Hz blinken. Damit 
kann man ausschließen, dass dein Frequenzzähler Mist misst.
Mit dem UART hast du rechnt, also bleibt nur das als Fehlermöglichkeit.

von Εrnst B. (ernst)


Lesenswert?

Überprüf mal in deinem HEX-File, ob die ISR-Vektoren vor dem 
Output-Compare1A auch alle richtig gesetzt sind, bzw die anderen 
Interrupts auch sicher ausgeschaltet sind.

Einen Faktor von drei könnt ich mir nur so erklären, dass auch zwei 
andere IRQs von dem Timer ausgelöst werden (Compare1B und Overflow), und 
diese eben fälschlicherweise auch dieselbe ISR ausführen...

von Johannes M. (johnny-m)


Lesenswert?

@Ernst:
Naja, das trau ich dem AVR-GCC nicht zu, dass er solchen Mist macht. 
Außerdem ist das OCR1B-Register nicht initialisiert, hat also den Wert 
0, was ganz andere Effekte hätte, wenn dem so wäre.

@Chris:
Ist das Signal am Pin denn ein gleichmäßiges Rechteck-Signal (50% 
Einschaltdauer)? Ansonsten folge mal Benedikts Vorschlag und mach es mit 
einer sehr niedrigen Frequenz, bei der man selbst erkennen kann, ob das 
Tastverhältnis stimmt.

von Chris (Gast)


Angehängte Dateien:

Lesenswert?

Die LED blinkt - das ist allerdings schneller als 1 Hz ->  3Hz kommen 
wohl eher hin!! sowas langsames kann ich aber leider nichtmehr mit dem 
Frequenzzähler messen.
Habe jetzt neue 22pF Kondensatoren und ein neues Quarz eingebaut, 
allerdings ohne wirkung. Faktor 3 bleibt da.

Das mit den ISR Vektoren klingt interessant, allerdings weiss ich nicht 
wo ich aus dem hex file was rauslesen sollte... ich hab mal das hex file 
angehängt, kann mir vllt jemand sagen wie ich das interpretieren kann?
Gibt es dazu irgendwo Hinweise`?

ein lss file habe ich auch, da steht überall ausser bei nummer 6 etwas 
von "bad vector" ...

von Johannes M. (johnny-m)


Lesenswert?

Das Hex-File sieht in Sachen Interrupt-Vektoren OK aus. Allerdings ist 
das Hex-File definitiv nicht von dem oben geposteten Quellcode. Hast Du 
mit dem gekürzten Programm auch das ganze ausprobiert? Wenn nicht, dann 
tu das, oder schick den KOMPLETTEN Quellcode, der zu dem Hexfile gehört.

von Chris (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe mit dem gekürzten Quellcode alles oben genannte ausprobiert. 
Hier das komplette übersetzte Projekt, passend zum oben geposteten 
c-code als zip File.
Vielen Dank für eure rege Beteiligung und Unterstützung. Ich kann es 
einfach nicht glauben. Es ist ja nicht so dass ich das zum ersten mal 
mit timern arbeite aber ich bin langsam echt am (ver)zweifeln.. Aber mit 
Hex files und assembler kenne ich mich nicht aus.

von Johannes M. (johnny-m)


Lesenswert?

Hab das Hex-File mal durch den Simulator laufen lassen. Da sieht 
zumindest alles OK aus. Hast ja anscheinend den Prescaler jetzt auf 1024 
und OCR1A auf 3800 stehen. Müssten dann ja eigentlich knapp unter 1 Hz 
rauskommen...

von Chris (Gast)


Lesenswert?

ja ich habe es so angepasst weil ich das 7,37Mhz Quarz durch ein 8MHz 
Quarz ersetzt habe (hatte kein 7er mehr). deshalb der OCR1A auf 3800 
damit ich 1.03 Hz bekomme. Aber es ist einfach immernoch das 3fache.

Nungut, da die Software anscheinend völlig i.O. ist habe ich wohl keine 
andere Möglichkeit als eine Neue Platine aufzubauen.

Dass der uC kaputt ist ist auch ausgeschlossen da ich einen nigel nagel 
neuen aus der OVP eingesetzt habe.

Vielen Dank trotzdem für eure Wertvollen Tips und die geopferte Zeit, 
hoffe mich gelegentlich revanchieren zu können.

von Benedikt K. (benedikt)


Lesenswert?

Wenn du rausfindest an was es lag, teile es uns mit.

Es muss irgendein dummer Fehler sein, denn eigentlich haben wir schon 
ziemlich alles ausgeschlossen.

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.