Forum: Mikrocontroller und Digitale Elektronik Seltsames verhalten Timer0


von Ralf S. (schepperle)


Lesenswert?

Hallo Zusammen,

ich hab eine Routine geschrieben, die einen uint16 bei TCNT0 > 230 um 
eins hoch zählt. TCNT0 läuft mit 2304 KHz. Ziel ist es die uint16 
Variable als 100us-Timer zu verwenden. Die Hochzählroutine wird zyklich 
im main() aufgerufen.

Das komische ist, dass die uint16 Variable ca. 6 mal langsamer zählt als 
angedacht. Testweises pintoggeln läuft mit 6 Sek Periodendauer, nicht 
1sek. wie durch die Tesroutine vorgegeben.

und jetzt der Knaller: Wenn ich mitten im Code in der main() die Zeile

t = TCNT0 / 3;

einfüge läufts wie gewollt mit einer Sekunde Periodendauer, wobei t eine 
uchar ist und sonst nirgends auftaucht als in dieser Zeile. es ist auch 
egal ob ich "/3" oder "/10" oder "/100" schreibe, das Ergebnis ist das 
selbe.

Die Frage ist nun: wie kann diese eine Zeile den Programmablauf so 
massiv beeinflussen? Es ist nur ein Lesezugriff auf den TCNT0 und t wird 
auch nicht weiter verarbeitet.

Seh ich den Wald vor lauter Bäumen nicht mehr oder ist das wirklich 
strange? Vermutlich fehlt hier einiges an Info für ne Analyse... also 
bitte melden

Gruß,
Ralf

von Walter S. (avatar)


Lesenswert?

Ralf S. schrieb:
> Vermutlich fehlt hier einiges an Info für ne Analyse

gut erkannt

von Floh (Gast)


Lesenswert?

Ralf S. schrieb:
> Vermutlich fehlt hier einiges an Info für ne Analyse
Dein Code als Anhang.

von spess53 (Gast)


Lesenswert?

Hi

>Das komische ist, dass die uint16 Variable ca. 6 mal langsamer zählt als
>angedacht. Testweises pintoggeln läuft mit 6 Sek Periodendauer, nicht
>1sek. wie durch die Tesroutine vorgegeben.

Sicher, das es nicht 8x langsamer ist? das würde auf die CKDIF-Fuse 
hinweisen.

MfG Spess

von Ralf S. (schepperle)


Lesenswert?

bin mal neugierig ob der code euch schlauer macht.

die Routine inkrementiert die 10 counter. die if-Abfrage erkennt ein 
Overflow

void timers (void){
unsigned char i;
static char oldtim;


    // 0,1ms intervalle
    if (TCNT0 < oldtim) {
        for (i = 0; i < 10; i++){
            counter[i]++;
        }
        TCNT0 = 0;
        oldtim = 0;
    }
    oldtim = TCNT0;
}

Konfig von Timer0:

TCCR0A=0x02;
TCCR0B=0x02;
TCNT0=0x00;
OCR0A=230;
OCR0B=0x00;

So sollte er imo mit 2,3MHz takten was bei OCR0A = 230 alle 100us ein 
Overflow erfährt.

Hinweis: Ich habs jetzt mal mit nem Interrupt versucht und alle Aufrufe 
auskommentiert. Der Chip macht jetzt also nichts mehr anderes als auf 
das ov zu warten. Innerhalb vom if-Statement lass ich einen Pin toggeln. 
Verhalten bleibt identisch.

btw: die UART z.b. rennt gut. die Bitbreite passt einwandfrei!

so und jetzt? überseh ich was essentielles?

von Sascha W. (sascha-w)


Lesenswert?

Hallo,

dein Zeitfelher entsteht, weil du TCNT0 in der Schleife in Main wieder 
auf Null setzt - das wird vom Timer auutomatisch gemacht.
Im übrigen ist diese Auswertung des Timerüberlaufs - nimm's mir nicht 
krumm - völlig vermurkst. Nimm die ISR des Timers setzte dort ein Flag 
und werte dieses in der Main Schleife aus.

Sascha

von Thomas E. (thomase)


Lesenswert?

Ralf S. schrieb:
> überseh ich was essentielles?
Ja.
Du hast nicht die geringste Ahnung, wie man einen Timer benutzt. Dein 
Thread sollte die Überschrift "Seltsames Benutzen..." tragen.
Arbeite erstmal die Grundlagen durch:

http://www.mikrocontroller.net/articles/AVR-Tutorial:_Timer

mfg.

von Ralf S. (schepperle)


Lesenswert?

ja schön ist es nicht, das weis ich... aber die isr will ich nicht 
nehmen, weil ich allgemein auf Interrupts verzichten will. Der 
Programmablauf sollte so deterministisch wie möglich sein und eine ISR 
kommt eben wann sie will.

das setzen von TCNT0 = 0; ist an der Stelle tatsächlich unnötig.. 
stimmt.. mach ich raus... aber das führt doch noch lange nicht dazu, 
dass die Routine 6 mal langsamer läuft als sie soll und vor Allem diese 
eigentlich sinnlose Zeile mit der Teilung das Programm zum wuppen 
bringt...

btw, kleiner Rückzieher: Der Programmablauf mit der ISR haut hin... 
(nicht wie oben beschrieben), war ein sehfehler...

von Ralf S. (schepperle)


Lesenswert?

Danke Thomas für Deinen konstruktiven Beitrag. Du hast mir wirklich 
weiter geholfen! Jetzt weiß ich endlich wofür Timer da sind.

von Sascha W. (sascha-w)


Lesenswert?

Ralf S. schrieb:
> ja schön ist es nicht, das weis ich... aber die isr will ich nicht
> nehmen, weil ich allgemein auf Interrupts verzichten will. Der
> Programmablauf sollte so deterministisch wie möglich sein und eine ISR
> kommt eben wann sie will.
wenn du meinst

> das setzen von TCNT0 = 0; ist an der Stelle tatsächlich unnötig..
> stimmt.. mach ich raus... aber das führt doch noch lange nicht dazu,
> dass die Routine 6 mal langsamer läuft als sie soll
doch, der Timer läuft und zählt TCNT0 kontinuierlich hoch und setzt den 
bei erreichen von OCR0A auf Null. Nun kommt deine Routine zum Zug und 
erhöht erst mal gemütlich deine 10 Counter, in der Zeit ist TCNT0 schon 
weitergelaufen. Dann setzt du TCNT0=0 und der Timer muss wieder bei Null 
beginnen was die Zeit natürlich erhöht.

> und vor Allem diese
> eigentlich sinnlose Zeile mit der Teilung das Programm zum wuppen
> bringt...
dann solltest du mal dein ganzes Programm zeigen

Sascha

von Thomas E. (thomase)


Lesenswert?

Ralf S. schrieb:
> Danke Thomas für Deinen konstruktiven Beitrag. Du hast mir wirklich
> weiter geholfen! Jetzt weiß ich endlich wofür Timer da sind.
Na' das freut mich doch. Dann ist dein Zähler ja in 5 Minuten fertig. 
Mehr braucht man für so einen Piffelkram nämlich nicht.

mfg.

von Ralf S. (schepperle)


Lesenswert?

Spätestens nach dem Text brauchst Du ne Kippe danach, oder Thomas?

von Thomas E. (thomase)


Lesenswert?

Ralf S. schrieb:
> Spätestens nach dem Text brauchst Du ne Kippe danach, oder Thomas?
Irgendwie findest du dich dich witzig, oder?
Aber du bist der Trottel, der einen kleinen Zähler nicht zum Laufen 
bekommt. Und das finde ich wieder witzig.

mfg.

von Ralf S. (schepperle)


Lesenswert?

nun ich bitte in diesem Forum um Hilfe, weil ich bei meinem Problem an 
meine fachlichen Grenzen gekommen bin. Da Du mir mit diesem Problem 
nicht weiter geholfen hast, scheinen Deine Grenzen <= den Meinen zu 
sein. Fragt sich nun wer der größere Trottel ist.
Anders gefragt: inwiefern bereichert es Dich anderen ihr fachliches 
Defizit vorzuhalten anstatt einen konkreten Lösungsanstz zu suchen? Die 
anderen haben das doch auch geschafft...

von Thomas E. (thomase)


Lesenswert?

Ralf S. schrieb:
> Da Du mir mit diesem Problem nicht weiter geholfen hast
Doch, das habe ich schon lange getan:

Thomas Eckmann schrieb:
> Arbeite erstmal die Grundlagen durch:
> http://www.mikrocontroller.net/articles/AVR-Tutorial:_Timer

Wenn du das nicht annimmst und stattdessen hier rumheulst, ist das dein 
Problem.
Genauso wie dein Zähler, der nicht funktioniert. Aber in dem Artikel 
findest du die Grundlagen dazu, das zu lösen.

mfg.

von Ingo (Gast)


Lesenswert?

Wie kleine Kinder...

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.