Seltsames verhalten Timer0

OP #2588570
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
Gast #2588613
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
OP #2588633
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?
#2588658
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
OP #2588690
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...
#2588707
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
OP #2588782
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...
#2588802
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren