Forum: Mikrocontroller und Digitale Elektronik Probleme mit Timer beim AtMega88


von Markus B. (wolframator)


Lesenswert?

Hallo,

ich versuche gerade für eine Funkuhr dem Timer auf 1 Sekunde 
einzustellen... Allerdings rennt mir der Timer davon %(

Hier mal die passenden Auszüge:
1
SIGNAL (SIG_OVERFLOW1)
2
{  
3
  //Zurücksetzen des Timers
4
  TCNT1 = 65535 - (F_CPU / 64);
5
6
  --- bla bla bla - led blinken etc ---
7
}
8
9
int main(void)
10
{
11
  //Interrupt Overfolw enable
12
  TIMSK1 |= (1 << TOIE1);
13
  //Setzen des Prescaler auf 64
14
  TCCR1B |= (0<<CS12 | 1<<CS11 | 1<<CS10); 
15
  //F_CPU wie definiert
16
  TCNT1 = 65535 - (F_CPU / 64);
17
18
  for(;;){}
19
}

Hab ich irgendwas übersehen? Ich find meinen Fehler ned :/

F_CPU = 1000000 (Ist ja der Werkszustand vom AtMega88)

von spess53 (Gast)


Lesenswert?

HI

Für solche Sachen ist der Output-Compare-Interrupt günstiger. Du lädst 
Das OC-Register in deinem Fall mit $3D08 und stellst den CTC-Modus ein. 
Und nicht wie oben vergessen Interrupts freigeben (sei() oder so 
ahnlich).

MfG Spess

von Markus B. (wolframator)


Lesenswert?

Die Interrupts hatte ich mit sei() freigegeben, aber nicht hier in den 
Code gepackt. Werd ich hier jedoch direkt nachholen...

Den Rest hab ich mal auf die Schnelle umgestellt. Müßte dann so aussehen 
denk ich mal:
1
SIGNAL (SIG_OUTPUT_COMPARE1A) {
2
{  
3
  OCR1A = 1000000 / 256 - 1;
4
5
  --- bla bla bla - led blinken etc ---
6
}
7
8
int main(void)
9
{
10
  TCCR1B = 1<<WGM12^1<<CS10;
11
  OCR1A = 1000000 / 256 - 1;
12
  TCNT1 = 0;
13
  TIMSK = 1<<OCIE1A;
14
15
  sei();
16
17
  for(;;){}
18
}

von spess53 (Gast)


Lesenswert?

Hi

Zu einem Interrupt gehört aber auch eine entsprechende ISR. In der wird 
festgelegt, was bei einem Interrupt passieren soll.

MfG Spess

von Johannes M. (johnny-m)


Lesenswert?

Markus B. wrote:
> Die Interrupts hatte ich mit sei() freigegeben, aber nicht hier in den
> Code gepackt. Werd ich hier jedoch direkt nachholen...
>
> Den Rest hab ich mal auf die Schnelle umgestellt. Müßte dann so aussehen
> denk ich mal:
>
>
1
> SIGNAL (SIG_OUTPUT_COMPARE1A) {
2
> {
3
>   OCR1A = 1000000 / 256 - 1;
4
> 
5
>   --- bla bla bla - led blinken etc ---
6
> }
7
>
Du hast das Prinzip der Compare-Geschichte offensichtlich nicht 
verstanden. Der Wert in OCR1A ändert sich nicht und muss deshalb auch 
nicht jedes Mal neu geladen werden (genau das ist ja der Vorteil 
gegenüber dem Timer-Nachladen!). Nur wenn die Zeit bis zum nächsten 
Compare geändert werden soll, muss in OCR1A ein neuer Wert rein.

Wenn Du nur den der Compare-Einheit zugehörigen Pin (OC1A) umschalten 
willst, dann kannst Du Dir das komplette Interrupt-Zeugs übrigens 
schenken und den Timer das in Hardware erledigen lassen => Einmal OCR1A 
schreiben, Timer starten, den Rest macht er selber...

Abgesehen davon sind SIGNAL und die damit zusammenhängenden Vektornamen 
mit SIG_XXX veraltet und sollten nicht mehr verwendet werden. Schau 
bitte im AVR-GCC-Tutorial nach, wie es richtig geht.

von Markus B. (wolframator)


Lesenswert?

Johannes M. wrote:
> Du hast das Prinzip der Compare-Geschichte offensichtlich nicht
> verstanden.

Richtig ;) Damit hab ich noch nie was gemacht... Bisher habe ich den 
Timer immer nur wie ganz oben benötigt. Das war jetzt einfach mal auf 
die Schnelle überlegt wie es funktionieren könnte. Naja... Werd ich mir 
nochmal durchlesen müssen. Hab da zwar gesucht aber wohl übersehen. 
Vielleicht sollte ich das besser auf morgen vertagen - Nach einem langen 
Schlaf g

von Lutz (Gast)


Lesenswert?

OCR1A = 1000000 / 256 - 1;

=> Klammern ???

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.