Timer0, Timer1 Vorteiler

OP #5579611
Lesenswert?

Hallo Zusammen

Ich bin etwas verwirrt über den Vorteiler vom Timer0 und Timer1 bei 
einem Atmega8. Gemäss Datenblatt wird dieser ja von beiden Timern 
geteilt. Stelle ich den Vorteiler von Timer1 ein, verstellt es mir 
allerdings auch den Takt von Timer0.
Ich verwende den internen 1MHz Takt.
Vom Code ist es folgendermassen:
Timer0 init:
TCCR0 = (1 << CS02); //clkIO wird durch 256 geteilt
TIMSK |= (1 << TOIE0);  //Aktiviert Interrupt beim Überlauf

In der ISR von Timer0 lade ich den Timer vor mit:
TCNT0 = 236;
So erhalte ich in etwa alle 5ms einen Interrupt, welchen ich dazu nutze 
verschiedene regelmässige Abfragen zu machen. Soweit läuft alles 
einwandfrei.
Timer1 init: (Timer1 möchte ich als PWM verwenden)
TCCR1B |= (1 << CS10);  //Vorteiler =1 Timertakt gleich clkIO Takt
Sobald ich hier den Vorteiler einstelle, ändert mir der Timer0, dass er 
anstatt alle 5ms alle 6.7ms ausgelöst wird.

Weiss jemand von euch an was das liegen könnte? Nur weil Timer0 und 
Timer1 den Vorteiler teilen, sollte es doch möglich sein, 
unterschiedliche Teiler zu verwenden.

Besten Dank schon mal für allfällige Tips.
Gruss Phil
#5579620
Lesenswert?

Welcher Vorgang im Vorteiler sollte das Verhältnis 5 / 6,7 bewirken?
Der teilt nur in (nicht lückenlosen) ganzzahligen 2er-Potenzen.

25% Änderung des internen Takts bekommt man weder mit Temperatur noch 
mit Spannungsänderung zustande, allerdings per OSCCAL-Register.

Wie wurden die Zeiten gemessen?
OP #5579712
Lesenswert?

Hier mal noch den Code.
@Stefan E.: Nein Timer1 hat keine ISR nur der über OCR1A/B verstellt 
wird.
@ H.Joachim S.: Das sehe ich genau so.
@ Matthias S.: Könntest du das etwas genauer erklären, wie es zu soetwas 
kommen kann? Ich messe am Pin PB0 nähmlich ein Rechteck, obwohl dieser 
ja konstant auf high sein sollte.

Hier wie gewünscht noch den Code
1
ISR(TIMER0_OVF_vect)
2
{
3
  /*Achtung ! Durch verzögerter Aufruf dieser ISR kann das Vorladen des Timers zu Jetter führen.
4
   *  Ist nicht geeignet für Anwendungen bei der ein exaktes Mittel von 5ms erreicht werden soll. 
5
   *  Theoretischer Wert = 184 da: 3686400 /256 / 200 = 72 => 256-72 = 184
6
   *                                Quarz / Vorteiler / gewünschte Frequenz = Muss noch alle 72 Takte ausgelöst werden.
7
   *  -> Messtechnisch wurde 184 überprüft, was genau 200Hz ergibt -> 5ms Interrupt (gilt nur solange keine anderen ISR, der Aufruf dieser ISR verzögern)
8
   */
9
  TCNT0 = 256- (F_CPU / 256 / 200); // Counter vorlader
10
  PORTB ^=(1<<PB3);
11
}
12

13

14

15

16
int main(void)
17
{  
18
//Pin PB0 wird eingeschaltet um einen Reset zu sehen
19
DDRB |= ((1<<PB0) | (1<<PB3));
20
PORTB |= (1<<PB0);
21

22
//Timer0
23
  TCCR0 = (1<<CS02);
24
  TIMSK |= (1 << TOIE0);
25

26
  _delay_ms(500); //Damit man auf KO den Takt von Timer0 sieht
27

28
//PWM Outputs
29
  DDRB |= (1<<PB1);
30
  DDRB |= (1<<PB2);
31
  PORTB &= ~((1 << PB1) | (1 << PB2)); //Beide Outputs auf low stellen
32
//Timer1 
33
  TIMSK |= ((1 << OCIE1A) |(1 << OCIE1B)); //Interrupts Enable von Compare A und B
34
  TCCR1A |= ((1 << COM1A1) |(1 << COM1A0) | (1 << COM1B1)| (1 << COM1B0)); //Output wird gesetzt beim Hochzählen, gelöscht beim Herunterzählen
35
  TCCR1A &= ~((1 << FOC1A) | (1 << FOC1B)); // Aus Kompatibilitätsgründen auf 0 gesetzt.
36
  TCCR1B |= (1 << WGM13); //WGM13 = 1, WGM12= 0, WGM11= 0, WGM10= 0 entspricht dem Modus 8 Phasen und Freuquenz korrekter PWM
37
  SFIOR &= ~(1<<PSR10);
38
  TCCR1B |= (1 << CS10); // CS12, CS11 und CS10 bestimmen den Vorteiler für Takt von Timer1 -> 0 = Timer gestoppt, 1 = kein Vorteiler
39
//Nachdem TCCR1B mit CS10 gesetzt wurde stimmt Timer0 nicht mehr
40

41
  OCR1A = 0x8000; // CompareWert für Kanal A
42
  OCR1B = 0x8000; // CompareWert für Kanal B
43
  ICR1 = 0xFFFF; // Legt den TOP Wert des Zählers fest (16bit)
44

45
  while(1) { }
46
  return 0;
47

48
}
OP #5580228
Lesenswert?

Problem gelöst:
- Das sei() brauchts natürlich, damit überhaupt eine ISR läuft, das war 
mir jedoch klar.
- Das Problem war (wie Matthias S. schon sehr früh vermutete), dass die 
ISR für den Timer1 nicht vorhanden waren.
1
TIMSK |= ((1 << OCIE1A) |(1 << OCIE1B)); //Interrupts Enable von Compare A und B

Ich dachte, dass man diese aktivieren muss, damit sich die Outputs bei 
einem Match umschalten. Dem ist nicht so, wie ich nun herausgefunden 
habe.

Danke euch viel mals für den Tip und die Unterstützung.
Gruss Phil
Beitrag #5580229 wurde von einem Moderator gelöscht.

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