Forum: Mikrocontroller und Digitale Elektronik Mal wieder Timer (Forum-Suche nicht Lösungsgleich!)


von Diplomand_A (Gast)


Lesenswert?

Hallo Mikrocontroller-Gemeinde,

ich bin gerade auf der Suche nach einem vermutlich banalen Fehler. GGf. 
könnt ihr mir ja weiter helfen. Ich versuche derweil für eine weitere 
Funktion einen Timer einzubinden. Hierzu gebe ich zum testen eine LED 
zum Blinken am PORTC aus. Der Code sieht aus wie folgt:
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
4
#define QRGFREQ 8    //Angabe in Mhz
5
#define IRQT 100    // IRQ in t=x sec. (IRQTIME *10ms) (also eig. 1s!)
6
7
8
volatile unsigned int get_ADC =1,tenhsec=0;    
9
10
void main(void)
11
{
12
13
DDRC = 0xFF,
14
PORTC = 0xff;
15
// initialisation of timer and interrupts
16
17
18
TCCR1A = 0;  //Timer innerhalb des uC, keine externe Hardware
19
20
21
TCCR1B =0x01;   // Kein Prescaler  (Freq/1)
22
23
//Vergleichswert
24
OCR1AH = (QRGFREQ *1000) >>8;    // 10ms
25
OCR1AL = (QRGFREQ *1000) & 0xff;  // 10ms
26
27
28
// IRQ Enable
29
TIMSK1  = (1<<OCIE1A);//|(1<<TOIE3);
30
31
//Global freigeben
32
sei();    
33
  while(1)
34
    {
35
    
36
    }
37
}
38
39
//-------------------------------------------------------
40
ISR (TIMER1_COMPA_vect) 
41
{//Jede 10ms aufgerufen
42
43
tenhsec++;
44
if (tenhsec ==IRQT) 
45
  {tenhsec =0;
46
  get_ADC ^= 1;
47
  PORTC = get_ADC;
48
  }
49
}

Eigentlich sollte ja nach 1s der CompareValue erreicht sein und die LED 
entsprechend blinken. Dies macht sie ja auch! Allerdings ändere ich den

//Vergleichswert
OCR1AH = (QRGFREQ *1000) >>8;    // 10ms
OCR1AL = (QRGFREQ *1000) & 0xff;  // 10ms

auf andere Werte so ergibt sich die gleiche Geschwindigkeit des Taktes 
der LED. Das heißt also, dass der Compare-Wert woandersraus gebildet 
wird?
(Forum etc schon nachgestöbert!)

Ggf. banale Lösung ??

Danke schonmal

von Karl H. (kbuchegg)


Lesenswert?

Diplomand_A wrote:

> auf andere Werte so ergibt sich die gleiche Geschwindigkeit des Taktes
> der LED.

Das wundert mich nicht weiter.
Du hast keinen Timer Modus eingestellt. Das bedeutet so viel wie der 
Timer zählt munter vor sich hin. Immer von 0 bis 65536

Das eine mal kriegst du halt deinen Interrupt, wenn der Timer bei 300 
angelangt ist, das andere mal kriegst du ihn wenn er bei 28000 angelangt 
ist. Aber immer noch braucht der Timer exakt 65536 Zyklen bis er die 300 
bis 28000 das nächste mal wieder erreicht.

Nur weil du den OCIE1A Interrupt eingeschaltet hast, fängt der Timer ja 
nicht beim Auslösen des Interrupts wieder bei 0 an zu zählen. Der 
Interrupt macht genau das was er aussagt: Eine Information darüber, dass 
der Zählerstand einen bestimmten Wert erreicht hat. Nicht mehr und nicht 
weniger. Und wenn du sonst nichts tust, dann dauert es genau 65536 
Timerticks bis dieser Wert wieder erreicht wird.

von Benedikt K. (benedikt)


Lesenswert?

Diplomand_A wrote:

> Ggf. banale Lösung ??

Ja, Timer auf CTC Modus einstellen.

von Johannes M. (johnny-m)


Lesenswert?

Übrigens kann man in C sehr komfortabel auf 16-Bit-I/O-Register als 
ganzes zugreifen, ohne den ganzen Rotz mit (z.B.) OCR1AH und OCR1AL und 
Bitgeschiebe. Schreib einfach den Wert in OCR1A und sei glücklich, dass 
der Compiler sich höchstselbst um die Zugriffsreihenfolge und das 
Bitgepfriemel kümmert.

von Diplomand_A (Gast)


Lesenswert?

Hallo Jungs,

ich danke auch bestens für die Antwort von allen :-)

der Vollständigkeithalber für ggf. weiter hilfesuchende Personen:
1
TCCR1B =(1<<CS10)|(1<<WGM12);

Manchmal kann es so einfach sein :-)

gruß

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.