Hallo,
ich habe ein kleines Programm geschrieben, welches prinzipiell später in
ein größeres eingefügt wird.
Das Programm soll folgendes machen:
Atmega 8, Timer1 16-bit im Compare Match Mode (nicht CTC möglich, da ich
den Timer später durchlaufen lassen muss, entfällt diese Möglichkeit).
Das Programm soll alle 1024 Timerticks ein Compare Match auslösen und
eine LED damit toggeln. Hierzu lade ich OCR1A mit TCNT+1024 vor, also
dem aktuellen Zählerstand + die 1024 Timerticks.
Nun leider toggelt die LED unregelmäßig, sie blinkt etwa 3x in gleicher
Frequenz, dann 1x eine andere, dann wieder 3x gleich, eigentlich soweit
ich beurteilen kann periodisch.
Dennoch sollte die LED ja in einem konsanten Takt blinken und nicht ein
Ausreißer dazwischen.
Zunächst dachte ich, dass es evtl. daran liegt, dass OCR1A und TCNT1 das
gleiche temp Register verwenden zum Auslesen. Deshalb habe ich eine
Variable eingefügt, die als temp Register dient, das funktionierte aber
auch nicht.
Wo ist mein Denkfehler in dem Programm oder der Programmierfehler?
Hier ist der Sourcecode:
1 | #include <stdint.h>
|
2 | #include <avr/io.h>
|
3 | #include <avr/interrupt.h>
|
4 |
|
5 | #ifndef F_CPU
|
6 | #define F_CPU 8000000UL // Prozessortakt
|
7 | #endif
|
8 |
|
9 | #define LED PB1 // Pin LED active low
|
10 |
|
11 | ISR (TIMER1_COMPA_vect){
|
12 | PORTB ^= (1 << LED); // LED teoggeln
|
13 | OCR1A = TCNT1+1024; // Compare Match 1024 Timerticks später
|
14 | /* auf folgendes geht nicht:
|
15 | uint16_t temp = TCNT1
|
16 | temp += 1024;
|
17 | OCR1A = temp;
|
18 | */
|
19 | }
|
20 |
|
21 |
|
22 | // main programm
|
23 | int main()
|
24 | {
|
25 |
|
26 | DDRB = 0x00;
|
27 | DDRB |= (1 << DDB1);
|
28 | PORTB |= (1 << LED);
|
29 |
|
30 | OCR1A = 1024; // erstes Compare Match bei 1024 Timerticks, dann alle weitere 1024
|
31 | TCCR1B = (1 << CS00) | (1 << CS01); // Prescaler 64
|
32 | TIMSK |= (1 << OCIE1A); // Compare Match A enable
|
33 | sei(); // globales Interrupt enable
|
34 |
|
35 | while(1){
|
36 | // do nothing interruptgesteuert
|
37 | }
|
38 | }
|
Desweiteren habe ich noch eine Frage: Welche Werte haben die Register im
AVR allgemein nach Reset des µC?
Im Datenblatt steht, dass für den normalen Betrieb im Compare Match
(ohne dass Pin OC1A geschaltet wird) im TCCR1A das Bit COM1A0 und COM1A1
gelöscht sein muss (0).
Muss man diese vorher explizit löschen?
1 | TCCR1A &= ~ ((1 << COM1A0) | (1 << COM1A1))
|
oder sind alle Registerbits standardmäßig gelöscht?
Ich habe das auch ausprobiert beim Initialisieren, jedoch auch kein
Unterschied im Programm.
Bin ratlos, gestern 4h damit verbacht :(