Forum: Mikrocontroller und Digitale Elektronik ATmega16 8Bit-Timer Interrupt für Zeitbasis zu unpräzise


von ben91 (Gast)


Angehängte Dateien:

Lesenswert?

Hallo liebe Foren-Mitglieder!

Ich habe folgendes Problem:

Derzeit versuche ich einen Frequenzzähler mit einem ATmega16 zu 
realisieren. Meine Idee war es zu Übungszwecken, erstmal die beiden 
8-Bit Counter für das Zählen einer relativ niedrigen Frequenz zu 
verwenden.
Dabei ergab sich jedoch schon folgende Problematik:

Um eine Zeitbasis von 2.5µs zu realisieren, wollte ich den Timer0 direkt 
mit der Taktfrequenz (12MHz) des Mikrocontrollers, also mit 
Prescaling-Faktor von 0 im CTC-Modus bis auf 30 Zählen lassen (im 
Compare-Register, wurde somit 30, als maximaler Zählerstand 
eingestellt).
Wenn der Zähler nun den Wert 30 erreicht hat,
sollte er einen Interrupt auslösen,
welcher ein LED-Band (an PortC) toggelt.
Die LEDs sollten dabei mit einer theoretischen Frequenz von 200kHz 
"blinken", welches ich mit einem Oszilloskop überprüfen wollte:

Herleitung der 200kHz Toggelfrequenz    F_blink = (F_CPU/Compare-Wert)/2
                                                      |       |        |
                                    Taktfrequenz des µC       |        |
                                          maximaler Zählerstand        |
                                                      /2 (weil 
getoggelt)

Die Messung ergab jedoch eine Frequenz von 178kHz.
Ich habe die Messung zur Sicherheit noch an einem anderen µC überprüft
und es stellte sich exakt die selbe Frequenz ein.
Ich kann mir das nicht erklären!
Hat vielleicht jemand eine Idee, wie diese Frequenz-Toleranz von 11% 
zustande kommen kann??

Danke bereits im Voraus für die Antworten.

PS: Die Quarzfrequenz habe ich bereits überprüft, sie war OK  &
    im Anhang ist noch der Quelltext zu finden!!

von holger (Gast)


Lesenswert?

>Um eine Zeitbasis von 2.5µs zu realisieren, wollte ich den Timer0 direkt
>mit der Taktfrequenz (12MHz) des Mikrocontrollers, also mit

Also mit 83.3 ns pro Maschinenzyklus und damit 30 Takten
für deine 2.5us. Such dir ne andere Aufgabe.

von Michael U. (amiga)


Lesenswert?

Hallo,

ben91 schrieb:
> Um eine Zeitbasis von 2.5µs zu realisieren, wollte ich den Timer0 direkt
> mit der Taktfrequenz (12MHz) des Mikrocontrollers, also mit
> Prescaling-Faktor von 0 im CTC-Modus bis auf 30 Zählen lassen (im
> Compare-Register, wurde somit 30, als maximaler Zählerstand
> eingestellt).
> Wenn der Zähler nun den Wert 30 erreicht hat,
> sollte er einen Interrupt auslösen,
> welcher ein LED-Band (an PortC) toggelt.
> Die LEDs sollten dabei mit einer theoretischen Frequenz von 200kHz
> "blinken", welches ich mit einem Oszilloskop überprüfen wollte:
>
> Herleitung der 200kHz Toggelfrequenz    F_blink = (F_CPU/Compare-Wert)/2
>                                                       |       |        |
>                                     Taktfrequenz des µC       |        |
>                                           maximaler Zählerstand        |
>                                                       /2 (weil
> getoggelt)
Das Datenblatt sagt da (F_CPU/Compare-Wert)-1

> Die Messung ergab jedoch eine Frequenz von 178kHz.
> Ich habe die Messung zur Sicherheit noch an einem anderen µC überprüft
> und es stellte sich exakt die selbe Frequenz ein.
> Ich kann mir das nicht erklären!
> Hat vielleicht jemand eine Idee, wie diese Frequenz-Toleranz von 11%
> zustande kommen kann??

Denke mal darüber nach, wieviele Takzyklen den AVR für die 
IRQ-Bearbeitung bleiben und schau ins Datenblatt und ins ASM-Listing, 
daß der Compiler erzeugt, wieviele er braucht.

Probiere es z.B. mal mit 50kHz, ob es da passt.

Gruß aus Berlin
Michael

von spess53 (Gast)


Lesenswert?

HI

OCR=30 ist schon mal falsch. Das muss 29 sein. Wo der Restfehler 
herkommt kann ich jetzt auch nicht sagen.

MfG Spess

von Falk B. (falk)


Lesenswert?

@  ben91 (Gast)

>Um eine Zeitbasis von 2.5µs zu realisieren, wollte ich den Timer0 direkt
>mit der Taktfrequenz (12MHz) des Mikrocontrollers, also mit
>Prescaling-Faktor von 0 im CTC-Modus bis auf 30 Zählen lassen (im
>Compare-Register, wurde somit 30, als maximaler Zählerstand
>eingestellt).

Und dir ist klar, dass du damit alle 30 Takte einen Interrupt hast?
Wieviel Befehle soll denn die CPU mit diesen 30 Takten ausführen?

>Die Messung ergab jedoch eine Frequenz von 178kHz.

Tja, dann braucht dein Interrupt halt mehr als 30 Takte. Was in C auch 
fast normal ist.

Dein Konzept ist unbrauchbar.

MFG
Falk

von Andreas F. (aferber)


Lesenswert?

Zähl mal die Takte deiner Interrupt-Routine (generierten Assemblercode 
ansehen und den Sprung zur Interrupt-Routine nicht vergessen!). 
Vermutlich wird als Ergebnis rauskommen, dass das 34 oder 35 Takte 
sind...

Andreas

von ben91 (Gast)


Lesenswert?

Hallo,

erst mal danke für die Zahlreichen Antworten!

Michael U. schrieb:
> Das Datenblatt sagt da (F_CPU/Compare-Wert)-1

... dann sollte sich laut deiner Theorie bei meinem Programm eine 
Frequenz von ca. 199kHz einstellen (anstelle der gemessenen 178kHz)

Ich habe noch einen wichtigen Aspekt vergessen, zu erwähnen:

Wenn ich den Compare-Wert auf z.B. 40 erhöhe,
dann stimmt die daraus errechnete theoretische Frequenz exakt mit dem 
gemessenen Wert überein!!

von holger (Gast)


Lesenswert?

>Wenn ich den Compare-Wert auf z.B. 40 erhöhe,
>dann stimmt die daraus errechnete theoretische Frequenz exakt mit dem
>gemessenen Wert überein!!

Dann schafft dein Programm es mit 40 Takten halt gerade mal so;)

von ben91 (Gast)


Lesenswert?

Holger schrieb:
>Dann schafft dein Programm es mit 40 Takten halt gerade mal so;)

... tja, dass hab ich mir eben auch gedacht,
bis zu einem Compare-Wert von 35 stimmt die Frequenz nicht,
jedoch bei allem was darüber liegt(zB. 36),
stimmt die Frequenz plötzlich exakt mit dem errechneten Wert überein?!

von Andreas F. (aferber)


Lesenswert?

ben91 schrieb:
> jedoch bei allem was darüber liegt(zB. 36),
> stimmt die Frequenz plötzlich exakt mit dem errechneten Wert überein?!

Ist das so schwer zu kapieren? Damit hast du jetzt erfolgreich 
rausgefunden, dass die minimale Zeit zwischen zwei Aufrufen deines 
Interrupts 37 Takte beträgt. Schneller geht's nur, wenn die 
Interruptroutine kürzer wird. Ein Prozessor ist kein Mensch, der eine 
Aufgabe nach Einarbeitung irgendwann schneller erledigen könnte.

Da du aber noch andere Sachen machen willst als nur mit einem Pin 
rumzuwackeln (und dementsprechend der Code dann länger wird), ergibt 
sich die logische Folge, dass dein ganzes Konzept so nicht aufgeht, und 
du nochmal zurück ans Reissbrett musst.

Andreas

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.