CTC-Verständnis: OCR1A scheint (!) ein Eigenleben zu führen

OP #3987991
Lesenswert?
• ▲
▼
Hallo allerseits,

ich verwende den Timer1 meines ATmega88PA mit CTC, um eine LED mit 180 
bpm (3 Hz) blinken zu lassen. Ohne die Taster zu bedienen dachte ich, 
dass folgendes passieren müsste: Die LED an PB0 ist am Anfang an und 
wechselt dann eben mit 3 Hz zwischen an und aus, weil der Timer immer 
bis 5207 (Inhalt von OCR1A) zählt. Nun geht sie aber nach ner 
Drittelsekunde aus (soweit also richtig), danach wechselt sie aber nur 
noch ungefähr alle vier Sekunden. Zurückgerechnet wäre eine Erklärung 
dafür, dass der Timer einmal bis 5207 zählt, danach aber bis 
65535=0xFFFF, also OCR1A ignoriert oder zurücksetzt.

Was hab ich da falsch verstanden bzw. müsste ich anders machen, damit 
der Timer immer zum gleichen Wert zählt?
1
#define F_CPU  1000000UL // 1 MHz
2

3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
#include <util/delay.h>
6

7
#define LED (1 << PB0)
8
#define D_LED DDRB
9
#define P_LED PORTB
10
#define TASTER1_AUS (PINC & (1 << PC5))
11
#define TASTER2_AUS (PINC & (1 << PC4))
12

13
#define PRESCALER_LOG 6
14
#define PRESCALER_BITS ((1 << CS11) | (1 << CS10))
15

16
volatile int8_t blinken = 1;
17

18
ISR (TIMER1_COMPA_vect) {
19

20
  if (blinken) {
21
    P_LED ^= LED;
22
  } else {
23
    P_LED &= ~LED;
24
  }
25
  
26
}
27

28
// muss das int sein?
29
int main(void) {
30

31
  // Datenrichtungsregister setzen, LED an
32
  D_LED |= LED;
33
  P_LED |= LED;
34

35
  // Timer 1:
36
  // CTC (TOP = OCR1A), Prescaler setzen
37
  TCCR1A |= (1 << WGM12);
38
  TCCR1B |= PRESCALER_BITS;
39

40
  uint16_t bpm = 180;
41

42
  // Rundungsfehler beim Shift, wenn F_CPU nicht durch den Prescaler teilbar ist:
43
  // PRESCALER_LOG =  8 => 6*10^-5
44
  // PRESCALER_LOG = 10 => 6*10^-4
45
  // -1 am Ende, weil ja von 0 gezählt wird (?, TODO: nochmal nachlesen)
46
  OCR1A = 60 * (F_CPU >> PRESCALER_LOG) / bpm - 1;
47

48
  // Compare-Interrupt erlauben
49
  TIMSK1 |= (1 << OCIE1A);
50
  // Global Interrupts aktivieren
51
  sei();
52

53
  int8_t entpr_taster1 = 0;
54
  int8_t entpr_taster2 = 0;
55

56
  while (1) {
57

58
    _delay_ms(10);
59

60
    // TASTER1
61
    if (TASTER1_AUS) {
62
      entpr_taster1 = 0;
63
    } else if (entpr_taster1 < 4) {
64
      entpr_taster1++;
65
    } else if (entpr_taster1 == 4) {
66
      entpr_taster1++;
67
      // AKTION:
68
      blinken = !blinken;
69
    }
70

71
    // TASTER2
72
    if (TASTER2_AUS) {
73
      entpr_taster2 = 0;
74
    } else if (entpr_taster2 < 4) {
75
      entpr_taster2++;
76
    } else if (entpr_taster2 == 4) {
77
      entpr_taster2++;
78
      // AKTION:
79
      bpm += 10;
80
      cli(); // TODO: nötig? Denke schon wg. 16bit.
81
      OCR1A = 60 * (F_CPU >> PRESCALER_LOG) / bpm - 1;
82
      sei();
83
    }
84

85
  }
86

87
  return 0;
88

89
}

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.