Timer Compare

Gast #2958516
Lesenswert?

Hallo zusammen,
ich möchte auf einem ATmega32U2 den Compare A Interrupt von Timer1 
verwenden. Dabei soll die Zeit zwischen zwei Compare Interrupt's immer 
konstant sein und der Timer darf nicht auf 0 zurück gesetzt werden. Nun 
meine Idee war einfach immer das Compare Register um den Wert zu erhöhe 
der mir die entsprechende Zeitdifferenz ergibt. Leider funktioniert es 
in der Praxis nicht ganz so gut wie in der Theorie, kann mir jemand 
helfen meinen Fehler zu finden oder gibt es vielleicht sogar eine 
"schönere" Lösung?
1
//16Bit verwaltung
2
#define low_byte(x) (x & 0xff)
3
#define high_byte(x) ((x >> 8) & 0xff)
4

5
void init_USBTask (void) {
6
  OCR0A = 0b00000000; //Kein Output Compare
7
  
8
  switch (Timer1_Prescaler) { //Frequenzteiler auswählen
9
    case 0: TCCR1B = 0;
10
    case 1: TCCR1B = 1;
11
    case 8: TCCR1B = 2;
12
    case 64: TCCR1B = 3;
13
    case 256: TCCR1B = 4;
14
    case 1024: TCCR1B = 5;
15
  }
16
  
17
  OCR1AL = low_byte (USB_USBTask_Frequenz);
18
  OCR1AH = high_byte (USB_USBTask_Frequenz);
19
  set_bit (TIMSK1,1); //Aktiviert Compare A
20
}
21

22
ISR (TIMER1_COMPA_vect) {
23
  USB_USBTask_interrupt ();
24
}
25

26
void USB_USBTask_interrupt (void) {
27
  USB_USBTask();
28
  uint16_t compare_a = OCR1AH;
29
  compare_a << 8;
30
  compare_a &= OCR1AL;
31
  
32
  uint16_t rest = 65536 - compare_a;
33
  
34
  if (rest < USB_USBTask_Frequenz) compare_a = USB_USBTask_Frequenz - rest;
35
  else compare_a += USB_USBTask_Frequenz;
36
  
37
  OCR1AL = low_byte (compare_a);
38
  OCR1AH = high_byte (compare_a);
39
}
Gast #2958632
Lesenswert?

Bei einem Interrupt wird "USB_USBTask();" ausgeführt, als ich anfangs 
noch den Timer bei einem compare zurück gesetzt habe hat es tadellos 
funktioniert, nun tritt der Interrupt nur noch sehr stark verzögert auf. 
Normal meldet sich das USB Device sovort an, nun erst nach ca. 20sec.
Gast #2958644
Lesenswert?

Der Timer läuft im Standard Modus, also ohne PWM oder sonstiges, habe 
jetzt eine LED angeschlossen und eine Zeit von ca. 5sec gemessen. 
Scheint also irgendwie an dem Wert zu liegen?! Hier meine Berechnung:
1
//Einstellungen für die Frequenzen
2
#define USBTask_Frequenz 33 //Frequenz für USB_USBTask in Hz
3
#define Timer1_Prescaler 1024 //Wert für den Prescaler von Timer1 (0, 1, 8, 64, 256, 1024)
4

5
//Frequenzen werden berechnet
6
#define Timer1_Frequenz (F_CPU / Timer1_Prescaler)
7
#define USB_USBTask_Frequenz (Timer1_Frequenz / USBTask_Frequenz)
8

9
//Fehlermeldung für falsche Werte
10
#if USB_USBTask_Frequenz > 65535
11
  #error "Der Frequenzteiler ist zu klein"
12
#endif

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