Forum: Mikrocontroller und Digitale Elektronik Timer0 Atmega328P löst im CTC Mode kein interrupt aus


von Marcel F. (marcellobs)


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?

von jo mei (Gast)


Lesenswert?

Marcel F. schrieb:
> volatile uint8_t InterruptCounter = 0;

Marcel F. schrieb:
> Warum?

Dein Counter kann nur bis 255 zählen, wird also nie die geplanten
1000 erreichen.

von Andreas B. (bitverdreher)


Lesenswert?

Weiter: OC0A geht auf Port D6, nicht D0, wenn ich da richtig gelesen 
habe.

Edit: Beim Mega328PB auf PB3. Da ist wirklich nichts kompatibel...

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

> Counter kann nur bis 255 zählen
Was sogar der Compiler (zumindest meiner) anmerkt:
"Comparison is always false due to limited range of data type ..."

von S. Landolt (Gast)


Lesenswert?

> OC0A ... Edit: Beim Mega328PB auf PB3. Da ist wirklich nichts kompatibel...

Nanu? Also in meinem Datenblatt ist es PD6 wie beim ATmega328P.

von Andreas B. (bitverdreher)


Lesenswert?

S. Landolt schrieb:
> Was sogar der Compiler (zumindest meiner) anmerkt:
> "Comparison is always false due to limited range of data type ..."
Compiler Warnungen sind was für Warmduscher.

S. Landolt schrieb:
> Nanu? Also in meinem Datenblatt ist es PD6 wie beim ATmega328P.
Stimmt, da habe ich mich verguckt. Also doch alles gut.

: Bearbeitet durch User
von S. Landolt (Gast)


Lesenswert?

"Hey, ich bin doch de Iron-Män! Nöd gwüsst?"

von jo mei (Gast)


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.

von Eberhard H. (sepic) Benutzerseite


Lesenswert?

Marcel F. schrieb:
> Timer0 im CTC Mode

Mit TCNT1 (16 Bit) schaffst du die eine (bzw. halbe) Sekunde ganz ohne 
Softwarezähler (wo der Hund begraben liegt).

von Marcel F. (marcellobs)


Lesenswert?

@all: 10000000000x Danke, ihr habt mir den Arsch gerettet. Jetzt läuft 
es, lag an dem zu kleinen Datentyp und dem falschen Pin!

von jo mei (Gast)


Lesenswert?

Marcel F. schrieb:
> Danke, ihr habt mir den Arsch gerettet.

Was wäre - im Negativ-Fall - mit deinem Arsch passiert?

von Marcel F. (marcellobs)


Lesenswert?

jo mei schrieb:
> Marcel F. schrieb:
>> Danke, ihr habt mir den Arsch gerettet.
>
> Was wäre - im Negativ-Fall - mit deinem Arsch passiert?

Der hätte den Controller samt Programmer auf die Straße geworfen (vor 
Frust) :D

: Bearbeitet durch User
von Andreas B. (bitverdreher)


Lesenswert?

Marcel F. schrieb:
> Jetzt läuft
> es, lag an dem zu kleinen Datentyp und dem falschen Pin!
Hmm, mit den "falschen" Pin hätte das noch laufen müssen. Du hast die 
LED ja manuell umgeschaltet. Ich bin nur davon ausgegangen, daß es 
letztendlich eine PWM werden soll. Nur dann muß Du das auf PD6 umlegen.

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.