Forum: Compiler & IDEs Timerprobleme


von Alex (Gast)


Lesenswert?

Hallo zusammen!

Ich habe erst angefangen Mikrocontroller zu bedienen und habe meine 
ersten Erfahrungen gemacht. Ich programmiere in C mit dem AVR Studio.
Nun mein Problem:
Ich will einen Timer programmieren mit dem mega 8. Mit dem steuere ich 
eine LED an die im Sekundentakt ein- und ausschalten soll. Die Frequenz 
habe ich bei den Configuration Options auf 8000000 Hz gestellt.
Doch statt nach einer Sekunde zu blinken benötigt er etwa 8 Sekunden. 
Was habe ich falsch?
Hier der Code:
#include <avr/interrupt.h>
#include <stdlib.h>
#include <avr/io.h>

volatile static uint32_t count = 0;

ISR(TIMER1_OVF_vect)
{
  count++;
}

int main (void)
{
  TCCR1B |= (1<<CS10);
  TIMSK |= (1<<TOIE1);
  sei();
  DDRC |= (1<<2);
  PORTC |= (1<<2);

  while(1)
  {
    if (count < 122) PORTC &= ~(1<<2);
    if (count >= 122) PORTC |= (1<<2);
    if (count > 244) count = 0;
  }return 1;
}

Diese 122 errechnen sich aus 8000000 Hz Taktfrequenz / 65536(da 16-Bit 
Timer) = ca. 122.


Was habe ich mir falsch überlegt?

Grüsse Alex

von Peter D. (pdiener) Benutzerseite


Lesenswert?

Vielleicht hast du die Fuses des Controllers beim Programmieren falsch 
gesetzt und er läuft entgegen deine Annahme mit dem internen RC 
Oszillator, der hat etwa 1 MHz. Das würde den Faktor 8 erklären können.

Grüße,

Peter

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Wie gesagt, Fuses kontrollieren.

Für sowas ist eigentlich der CTC-Mode besser geeignet:
1
#define F_CPU           8000000
2
#define IRQS_PER_SECOND 100
3
#define PRESCALE        8
4
5
void timer1_init(void)
6
{
7
  // Mode #4 für Timer1 (Manual S. 97)
8
  // und Prescale=8
9
  TCCR1A = 0;
10
  TCCR1B = (1 << WGM12) | (1 << CS11);
11
12
  // PoutputCompare für gewünschte Timer1 Frequenz
13
  OCR1A = (unsigned short) ((unsigned long) F_CPU / IRQS_PER_SECOND / PRESCALE -1);
14
15
  // OutputCompare-Interrupt A für Timer 1
16
  TIMSK |= (1 << OCIE1A);
17
}

Dann reicht auch eine 8-Bit Variable zum Zählen die immer von 1 bis 100 
(oder 0 bis 99) läuft.

Mit einer 32-Bit Variablen musst du sicherstellen, daß der Zugriffe 
darauf atomar sind, d.h. nicht von einem Interrupt unterbrochen werden 
können.

Mit einem PRESCALE von 256 bekommt man auch 1 IRQ/Sekunde hin, aber für 
viele Anwendungen sind 100 IRQs/s genehm (Taster entprellen, etc)

von Karl H. (kbuchegg)


Lesenswert?

> Die Frequenz habe ich bei den Configuration Options auf
> 8000000 Hz gestellt.

Andere haben ja schon auf dein Problem hingewiesen.
Möchte das nur etwas vertiefen.

Es gibt nur eine Möglichkeit beim Mega8 die Taktfrequenz zu verändern 
und das ist über die Fuses. Die werden aber vom Programmer nicht 
eigenmächtig angerührt, sondern die Umstellung musst du explizit machen. 
Aber sei vorsichtig, es passiert ganz schnell, dass man sich da aus dem 
Controller aussperrt. Lieber alles 3-mal kontrollieren, ehe man die 
Fuses neu stellt.

http://www.mikrocontroller.net/articles/AVR_Fuses

Die Angabe in den Configuration Options hat informellen Charakter. Du 
informierst die Entwicklungsumgebung, und damit auch dein Program, 
darüber, wie schnell dein µC getaktet ist.

von Alex (Gast)


Lesenswert?

Das verwirrt mich jetzt aber ein bisschen. Ich verwende schon den 
internen Takt, aber ich habe gemeint, dass er bei 16Mh liegt?! Oder ist 
das der höchstwert mitdem man ihn takten darf oder wie soll ich das 
verstehen?

Danke für die vielen und schnellen Antworten! Denke das wird es sein. 
Werde es jetzt testen.
Grüsse Alex

von Karl H. (kbuchegg)


Lesenswert?

Alex wrote:
> Das verwirrt mich jetzt aber ein bisschen. Ich verwende schon den
> internen Takt, aber ich habe gemeint, dass er bei 16Mh liegt?!

Wo hast du denn diesen Wert her?

Auslieferungszustand ist: 1Mhz, interner Takt
so wie es im Datenblatt des Prozessors beschrieben ist.

Und dein Testprogramm bestätigt das ja auch eindrucksvoll.

> Oder ist
> das der höchstwert mitdem man ihn takten darf oder wie soll ich das
> verstehen?

Atmel sichert zu, dass bei 16Mhz der Prozessor noch einwandfrei 
funktioniert. Man kann auch höher gehen, nur kann es dann sein, dass 
einige Teile des Chips nicht mehr mitspielen. Zb. das EEPROM.

von Alex (Gast)


Lesenswert?

Aha, danke.

Das habe ich z.B. von hier:
http://www.roboternetz.de/wissen/index.php/Atmel_Controller_Mega8

Da habe ich einfach angenommen, dass das der interne Takt ist...

Grüsse Alex

von Karl H. (kbuchegg)


Lesenswert?

Alex wrote:
>
> Da habe ich einfach angenommen, dass das der interne Takt ist...

Hol dir von Atmel das Datenblatt deines Prozessors. Das wirst du sowieso 
brauchen. Und im Zweifel gilt immer das Datenblatt und nicht das was 
auf einigen Webseiten steht.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

> Das habe ich z.B. von hier:
> http://www.roboternetz.de/wissen/index.php/Atmel_Controller_Mega8
>
> Da habe ich einfach angenommen, dass das der interne Takt ist...

Was da steht ist der maximale Taktrate, für den der ATmega8 spezifiziert 
ist. Akkerdingst steht nicht dabei, was die Angabe aussagt. Ist also 
nutzlos, wenn man nicht eh schon weiß, was das steht...

Werksseitig kommt der ATmega8 mit 1MHz inernem RC-Oszillator.

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.