Forum: Mikrocontroller und Digitale Elektronik Timer Compare


von Samuel (Gast)


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
}

von Spess53 (Gast)


Lesenswert?

Hi

>  OCR1AL = low_byte (compare_a);
>  OCR1AH = high_byte (compare_a);

Beim Schreiben immer erst das H-Byte.

MfG Spess

von Samuel (Gast)


Lesenswert?

Danke, gute Idee, Problem besteht aber leider immer noch :(

von Samuel (Gast)


Lesenswert?

Wie ist das wenn mein einen 16bit Wert mit einem 8bit vergleicht, geht 
das, gibt das Probleme?

if (rest < USB_USBTask_Frequenz)

rest = 16bit
USB_USBTask_Frequenz = 8bit

von Bennno (Gast)


Lesenswert?

Samuel schrieb:
> Leider funktioniert es
> in der Praxis nicht ganz so gut wie in der Theorie

Wie ist das Fehlverhalten? Wie überprüfst du das?

In welchem Modus läuft der Timer? Im PWM Modus wird OCR1A nur zu 
bestimmten TCNT1 Ständen upgedatet.

von Samuel (Gast)


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.

von Samuel (Gast)


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

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.