Timer0 Atmega328P löst im CTC Mode kein interrupt aus

OP #6657849
Lesenswert?

Alsooo ich bin zur Zeit dabei mir die AVR Programmierung in C bei zu 
bringen und bin bei dem Thema Timer/Counter am verzweifeln.

Das Ziel:
Wie so oft Standartmäßig, auch in vielen Tutorials zu sehen, eine LED im 
Sekundentakt toggeln zu lassen an einem ATmega328P-PU unter verwendung 
des Timer0 im CTC-Mode.

Herangehensweise:

-Schritt1: Hardwaretest:
Atmega328 in Minimalbeschaltung auf Breadboard aufgebaut, LED an PIN PD0 
mit passendem Vorwiderstand angehängt. Minimalbeschaltung, d.h. 
Verwendung des internen RC bei 8MHz ohne vorteiler.Erstmal mit delay die 
LED zum Blinken gebracht um den Breadboardaufbau auf seine Richtigkeit 
überprüfen - passt.

-Schritt2: Vorüberlegung Timer0 einstellungen:
Wenn ich das Richtig verstanden habe, würde, ohne Prescale, der Timer 
bei einem Takt von 8MHz 8 Millionen mal pro Sekunde erhöht werden. 
Deshalb entschloss ich mich für einen Prescale von 64 -> Damit würde er 
nur noch 125000 mal die Sekunde oder 125 mal die Millisekunde erhöht 
werden. D.h. nach 1 ms wäre er bei 124 (von Null an gezählt). Wenn ich 
also in das Register in OCR0A einen Wert 124 als Match übergebe, habe 
ich jede Millisekunde einen Interrupt? Diese Interrupts kann ich zählen, 
nach 1000 gezählten Interrupts habe ich meine sekunde Voll und kann die 
LED Toggeln und den Zähler zurücksetzten.

-Schritt 3: Register einstellungen (gesamter Code folgt am Ende):
Zu erst im Register TCCR0A WGM01 setzten um dem Controller mitzuteilen, 
dass ich gerne Timer0 im CTC Mode-hätte und den CTC-Match auf 124 
setzten.
1
TCCR0A |= (1 << WGM01);
2
OCR0A = 0x7C;
Dann im  Timer/Counter Interrupt Mask Register den compare match A 
interrupt erlauben und alle Interrupts aktivieren.
1
TIMSK0 |= (1 << OCIE0A);    
2
sei();
Den Prescale einstelen auf 64:
1
 TCCR0B |= (1 << CS01) | (1 << CS00);
Abschließend in der ISR das LED toggeln nach 1000 gezählten Interrupts 
einfügen
1
ISR(TIMER0_COMPA_vect)
2
{
3
  InterruptCounter++;
4
  if (InterruptCounter >= 1000) //8MHz mit 64 Prescale, Interrupt Wert 124 -> ca. alle 1ms ein Interrupt.
5
  {
6
    InterruptCounter=0;
7
    PORTD ^= (1<<PD0);
8
  } 
9
}
-Gesamter Code:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3

4
volatile uint8_t InterruptCounter = 0;
5

6
int main(void)
7
{
8
   DDRD |= (1<<PD0);  //LED an PD0
9
   PORTD |= (1<<PD0);  //Port auf HIGH initialisieren.
10
   
11
   TCCR0A |= (1 << WGM01);//Timer im CTC Mode.
12
   OCR0A = 0x7C;      //CTC Match bei 124.
13

14
   TIMSK0 |= (1 << OCIE0A);    //ISR auf COMPA vect setzten.
15
   sei();         //Interrupts aktivieren.
16

17
   TCCR0B |= (1 << CS01) | (1 << CS00); //Prescale mit 64.
18

19
   
20
    while (1) 
21
    {
22
    //NetflixAndChill
23
    }
24
}
25
ISR(TIMER0_COMPA_vect)
26
{
27
  InterruptCounter++;
28
  if (InterruptCounter >= 1000) //8MHz mit 64 Prescale, Interrupt Wert 124 -> ca. alle 1ms ein Interrupt.
29
  {
30
    InterruptCounter=0;
31
    PORTD ^= (1<<PD0);
32
  } 
33
}

->Beobachtung: LED blinkt nicht, sonder leuchtet const. Warum?
Gast #6657899
Lesenswert?

Marcel F. schrieb:
> Atmega328 in Minimalbeschaltung auf Breadboard aufgebaut, LED an PIN PD0
> mit passendem Vorwiderstand angehängt. Minimalbeschaltung, d.h.
> Verwendung des internen RC bei 8MHz ohne vorteiler.

Dann noch das Übliche für Anfänger:
- Abblock-Kondensatoren nicht vergessen!
- Alle Vcc Pins (Vcc und AVcc) versorgen, nicht nur einen!

Denkst du braucht es nicht? Na gut, wir sprechen uns dann
später wieder.

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