Problem mit Interrupt Prescaler

OP #2273902
Lesenswert?

Hallo,

aus dem Datenblatt werde ich nicht so richtig schlau.... Meine Frage:

Ich habe einen Atmega 644 mit 16Mhz am laufen, nu will ich einen 
Timerinterrupt alle 1ms auslösen.
Ich muss den Timer 1 nehmen da Timer 0 schon belegt ist.

Meine Konfig sieht so aus:
1
    TCCR1B |= (1<<CS10) | (1<<CS11) | (1<<WGM12);   // Prescaler 64   
2
    TCNT1   = 0;
3
    OCR1AH   = 256;                     // Load register Ist das richtig so  
4
    OCR1AL   = 256;                     // Load register   
5
    TIMSK1 |= (1<<OCIE1A);             // Interrupt nach Overflow

Ich weiss garnicht wie ich den OCR1AH lade Im Datenblatt steht halt 
OCR1AH  / OCR1AL , high und low.
Aber wie muss ich das Handhaben, das ist bestimmt falsch.

Nach meiner Berechnung müsste ca. 1 ms rauskommen.
Prescaler 64 also:

16.000.000Hz/64/256 = 976 = 0,001s = 1ms ca.

Wenn ich aber einen counter in der ISR erhöhe und ich den counter bei 
1000 in der main Abfrage sind das nie und nimmer 1 Sekunde. Diese 1000 
werden viel heufiger erreicht. Bei ca. 100000 habe ich eine Sekunde.

Kann mir einer helfen ?
#2273925
Lesenswert?

Also bei mir sieht das so aus und funktioniert:
1
//******************
2
// Timer1: Zeittakt 1ms
3
//******************
4

5
//TIMER1 initialize - prescale:1
6
// WGM: 0) Normal, TOP=0xFFFF
7
// desired value: 1mSec
8
// actual value:  1,000mSec (0,0%)
9
void timer1_init(void)
10
{
11
  TCCR1B = 0x00; //stop
12
  TCNT1L = (0xFFFF - F_CPU/1000 +1) & 0x0FF;
13
  TCNT1H = ((0xFFFF - F_CPU/1000 +1)>>8) & 0x0FF;
14
  OCR1AH = 0x39;  // does not matter
15
  OCR1AL = 0x99;  // does not matter
16
  OCR1BH = 0x39;  // does not matter
17
  OCR1BL = 0x99;  // does not matter
18
  OCR1CH = 0x00;  // does not matter
19
  OCR1CL = 0x00;  // does not matter
20
  ICR1H  = 0x39;  // does not matter
21
  ICR1L  = 0x99;  // does not matter
22
  TCCR1A = 0x00;
23
  TCCR1C = 0x00;
24
  TCCR1B = 0x01; //start Timer, no prescale
25
}
Ich verwende den OverflowInterrupt
Gast #2273959
Lesenswert?

Hi

>Was tut denn daran weh?

Wozu dieses Vorgelade? Timer1 hat CTC. Außerdem hast du vergessen zu 
sagen, das man das Vorladen bei jedem Interrupt machen muss. Nur in der 
Init bringt nichts.

Und 'TCCR1B = 0x01;' ist alles andere als aussagekräftig.

MfG Spess
Gast #2273981
Lesenswert?

Hi

>Ausserdem ist der Compiler bei den weitaus meisten 16-Bit Werten in
>IO-Registern in der Lage,....

Und außerdem sind diese Register nach einem Reset mit 0x00 
initialisiert.

Z.B. 'TCCR1A = 0x00;' ist also unnötig.

MfG Spess
#2273987
Lesenswert?

Wow, jetzt habt ihrs mir aber gegeben :-=

Aber:
"TCCR1B = (1<<CS10)" ist für mich jetzt auch nicht ausagekräftiger, weil 
ich auch erstmal nachschauen muss, wass denn nun "CS10" ist.
Und ausserdem ist das Ganze eine Initialisierungsroutine, die den Timer 
auf die Anfangswerte setzen soll. Egal, wie die Werte vorher gestanden 
haben.

Schön, dass ihr das anders macht.
OP #2275999
Lesenswert?

Also,
ich habe jetzt diese Einstellungen:
1
  TCCR1B = 0x00; //stop
2
  TCNT1L = (0xFFFF - F_CPU/1000 +1) & 0x0FF;
3
  TCNT1H = ((0xFFFF - F_CPU/1000 +1)>>8) & 0x0FF;
4
  TCCR1A = 0x00;
5
  TCCR1C = 0x00;
6
  TCCR1B = 0x01; //start Timer, no prescale
7
  OCR1A   = 256;  
8
  TIMSK1 |= (1<<OCIE1A);             // Interrupt nach Overflow

und das mache ich in der ISR:
1
ISR (TIMER1_COMPA_vect)
2
{
3
counter++;
4
}

Wenn ich den Counter so Abfrage:
1
if (counter >= 1000)
2
{
3
USART_Transmit('1');
4
counter=0;
5
}

Warum wird alle 4 Sekunden nur eine 1 ausgegeben ?
Verstehe das nicht....

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