PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Timer geht nicht?



donald_dack
09.12.2009, 22:48
Hallo
Ich habe ein Programm geschrieben das vor kurzem noch Funktioniert hat
Ich möchte das die LED’s in einem takt von 1 sec Blicken
Ich benutze 10MHz und das STK500 Atmega16.



#include <avr/io.h>
#include <avr/interrupt.h>

#define DURCHLEUFE 9
volatile unsigned int wert=0;
ISR(TIMER0_OVF_vect)
{
wert++;
TCNT0 = 256 -DURCHLEUFE;
}
int main(void)
{
TCNT0 = 256 -DURCHLEUFE;
TCCR0 = (1 << CS02)|(1 << CS00);
TIMSK = (1 << TOIE0);
sei();

DDRD = 0xFF;
PORTD = 0x00;
while(1)
{
if(wert == 100)
{
PORTD = ~PORTD;
wert = 0;

}


}
return 0;
}


by Donald

Hubert.G
10.12.2009, 10:12
Was funktioniert nicht? In der Simulation klappt es.

donald_dack
10.12.2009, 13:50
Das mit der Genauigkeit von 1 sec haut nicht so ganz hin.

Danke
by Donald

BurningWave
10.12.2009, 13:53
Das funktioniert nur genau, wenn du einen externen Quarz benutzt und das Programm für diese Frequenz anpasst.

donald_dack
10.12.2009, 14:36
Das habe ich ja
10 MHz, TCNT0 = 247;

das ist 1 mSec und davon jetzt auf 100 zählen mit

if ( wert == 100)
{
secunde++;
wert = 0;
}

if (secunde == 60)
{
minute++;
secunde = 0;
}

usw ...

Damit komme ich aber nicht mal annähernd in den genauigkeits- bereich
mit einer Ungenauigkeit von 1 Minute in 1 Monat kann man gut leben
aber derzeit geht’s überhaupt nicht woran liegt das ?

Danke
by Donald

BurningWave
10.12.2009, 14:48
Fusebits auf externen Quarz eingestellt? Ich mache das so:


#define F_CPU 3686400ul
#define COUNT F_CPU/(8ul*256ul)
#define DIVIDER 0x2
...
int takt = COUNT;
int sec = 0;
...
SIGNAL (SIG_OVERFLOW0)
{
takt--;
if(takt == 0)
{
takt=COUNT;
sec++;
...
}
}
...
void main()
{
... // Interrupt und Timer einstellen
TCCR0 |= DIVIDER; // Timer aktivieren
...
}

Das funktioniert mit einem 3,6864MHz Quarz perfekt. Bei einem 10MHz Quarz wirst du den Timer nicht ganz genau einstellen können, da COUNTER nicht ganzzahlig wird und somit gerundet werden muss.

Ceos
10.12.2009, 14:58
wenn dann solltest du statt == besser >= verwenden, wenn du mal aus welchen gründen auch immer den moment verpasst, wo wert == 100 ist zählt er sich dusselig ^^

also anch meiner rechnung, läuft dein timer 39.53694332 mal in der sekunde über, d.h. dein wert wird knapp 40 mal in der sekunde inkrementiert, d.h. wenn ud wartest, bis wert 100 erreicht sind mehr als 2 sekunden vergangen!

irgendetwas stimmt mit deiner berechnung nicht!

PS: 10Mhz ist ne wirklich ungünstige Frequenz

10Mhz / 1024 = 9765.625 Takte / Sekunde
10Mhz / 265 = 39062,5 (könnte gehen)
10 / 64 = 156250 (ginge aber das werden viiiiele überläufe werden)

156250 / 256 = 610.35156... (zu krumm)
156250 / 250 = 625 (exakt, aber 16bit wert nicht mehr 8bit)

und statt den counter immer vorzuladen, würde ich besser (falls du den output-compare nicht brauchst) den CTC modus mit dem OCR0 register als TOP nehmen und in das OCR0 einfach 250 schreiben, so sparst dir die rechenzeit für das laden des counters

donald_dack
10.12.2009, 15:10
Bei deinem Code verstehe ich manches nicht
#define COUNT F_CPU/(8ul*256ul) was wirt hier gemacht ?

SIGNAL (SIG_OVERFLOW0) das müsste glaube ich die alte Bezeichnung sein ist das das gleiche wie ISR(TIMER0_OVF_vect) ?

takt--;
if(takt == 0)
{
takt=COUNT;
sec++;
...
} diese Prozedur kann ich nicht nachvollziehen was ereichst du damit ?

#define DIVIDER 0x2 was ist das für ein wert und wie kommst du darauf ?

TCCR0 |= DIVIDER; // Timer aktivieren, Du verknüpfst das mit einem ODER und der Timer soll ab dem 0x2; beginnen zu zahlen warum machst du das auf diese art ?

welche unterschiede siehst du in meinem Code zu deinem Code ?

sorry wen ich so plump frage aber ich muss noch ne menge lernen und ihr Profis wendet immer so (für mich ) komplexe Wege der Programmierung an.

Danke
by Donald

KingTobi
10.12.2009, 15:40
das ist 1 mSec und davon jetzt auf 100 zählen mit

if ( wert == 100)
{
secunde++;
wert = 0;
}

Eine Sekunde hat nicht 100ms!

donald_dack
10.12.2009, 15:50
ok ich dachte es sind 100 dan sind das eben 1000mSec

Danke
by Donald

BurningWave
10.12.2009, 16:01
Bei deinem Code verstehe ich manches nicht
#define COUNT F_CPU/(8ul*256ul) was wirt hier gemacht ?

Hier wird ausgerechnet, nach wie vielen Timerüberläufen eine Sekunde vergangen ist.



SIGNAL (SIG_OVERFLOW0) das müsste glaube ich die alte Bezeichnung sein ist das das gleiche wie ISR(TIMER0_OVF_vect) ?

Ich nehme immer SIGNAL(...) und das funktioniert, ich sehe keinen Grund darin, das mit ISR(...) zu machen, da mir diese Interruptbezeichnungen nicht gefallen. Aber sonst bewirkt beides das gleiche.



#define DIVIDER 0x2 was ist das für ein wert und wie kommst du darauf ?

TCCR0 |= DIVIDER; // Timer aktivieren, Du verknüpfst das mit einem ODER und der Timer soll ab dem 0x2; beginnen zu zahlen warum machst du das auf diese art ?

Der Teiler des Timers wird auf 64 gesetzt, um ihn zu starten. DIVIDER ist nur ein Symbol, das ich verwende, um bei einer Änderung nicht jede Codestelle einzeln ersetzen zu müssen.



welche unterschiede siehst du in meinem Code zu deinem Code ?

Ich verstehe in deinem Code deine Berechnungen nicht und denke, dass sie nicht ganz richtig sind. In meinem Code sind sie auf jeden Fall richtig, da er bei mir funktioniert.



takt--;
if(takt == 0)
{
takt=COUNT;
sec++;
...
} diese Prozedur kann ich nicht nachvollziehen was ereichst du damit ?

Damit erreiche ich, dass bei jedem Timerüberlauf takt dekrementiert wird. Wenn takt 0 ist, ist eine Sekunde vergangen, da dies durch COUNT festgelegt wurde (nach wie vielen Überläufen eine Sekunde vergangen ist). Wenn takt nun 0 ist, wird die wieder Variable auf COUNT gesetzt, damit das ganze wieder von vorne beginnen kann und sec wird um eins erhöht, da eine weitere Sekunde verangen ist.

donald_dack
10.12.2009, 16:37
wie geht den das mit der Berechnung,
( F_CPU / Prescaler = Frequenz mit der gezählt wirt )*(TCCRx bis 256) = ISR

ich glaube ich habe das noch nicht ganz verstanden?

KingTobi
10.12.2009, 18:40
http://www.avr-praxis.de/forum/showthread.php?t=74
Guck dir den Timer Calculator mal an, der is echt top!

BurningWave
10.12.2009, 19:13
#define COUNT F_CPU/(8ul*256ul)
F_CPU = Systemtakt
8 = Prescaler
256 = 0x100 = 0b100000000 (wegen 8 Bit Timer, bei 256 gibt es einen Überlauf)

Formel
Anzahl der Überläufe, bis eine Sekunde vergangen ist = Systemtakt / (Prescaler * 256)