Forum: Mikrocontroller und Digitale Elektronik Atmega 16 ctc Modus


von terminator (Gast)


Lesenswert?

Hi,

ich habe einen Atmega 16 und möchte den Timer0 im CTC Modus laufen 
lassen. Ich habe mir auf sämtlichen Internetseiten durch gelesen wie man 
den Timer0 im CTC Modus laufen lässt und hab alles beachtet was dort 
steht, aber trotzdem funktioniert der unten stehende code nicht. Kurz 
zur Erklärung was der code tun sollte: Also es wird wie gesagt der 
Timer0(8 bit Timer) verwendet den ich aber mit dem OCR0 nur bis 100 
zählen lassen will und bei jedem Overflow wird die ISR ausgeführt. Die 
If befehle und die Zählvariable sind dafür da das die LED's die an den 
PINs angeschlossen sind ganz langsam blinken, damit ich die Zeit stoppen 
und überprüfen kann, ob alle Zeiten  richtig sind. Ich hoffe mir kann 
jemand sagen was ich falsch gemacht habe. Danke schon mal im Voraus.


#include <avr/io.h>
#include <avr/interrupt.h>

//Zählvariable deklarieren
int i=0;

ISR(TIMER0_COMP_vect) {
  //Bei jedem Overflow Zählvariable um eins erhöhen
  i++;
  //Nach 10.000 Overflows PINs auf high setzen entsprich einer sekunde
  if(i == 10000) {
    PORTD = 0b01100000;
  }
  //10.000 overflows später PINs auf low setzen entspricht einer sekunde
  if(i == 20000) {
    PORTD = 0b00000000;
    //Zählvariable auf null setzen damit das ganze von vorn beginnt
    i=0;
  }
}

int main() {
  //Datenrichtung definieren
  DDRD = 0b01100000;
  //Timer 0 initialisieren
  TCCR0 = (1<<CS01), (1<<WGM00);
  //Interrupts aktivieren
  TIMSK |= (1<<TOIE0);
  //Überlaufwert bei 100
  OCR0 = 100;
  //Globale Interrupts aktivieren
  sei();
  while(1) {
  //hier könnte ihr programm stehn!!!
  }
}

von Stefan E. (sternst)


Lesenswert?

terminator schrieb:
> Ich habe mir auf sämtlichen Internetseiten durch gelesen wie man
> den Timer0 im CTC Modus laufen lässt

Aber die beiden tatsächlich maßgebenden Dokumente hast du dabei außer 
Acht gelassen, nämlich das Datenblatt und dein C-Buch.

1
  TCCR0 = (1<<CS01), (1<<WGM00);
Nein, diese Zeile setzt nicht die beiden Bits in dem Register.

Und selbst wenn sie es tun würde: nein, WGM00 aktiviert nicht den 
CTC-Modus bei Timer0 beim Mega16.

Und als Ergänzung:
Nein, "TOIE0" und "TIMER0_COMP_vect" passen nicht zusammen.

von terminator (Gast)


Lesenswert?

Hi Stefan,

erst mal danke für die schnelle Antwort. Ich hab den Timer vorher im 
normalen Modus laufen lassen, also das er immer bis 256 zählt und dann 
die ISR aufgerufen wird und der Timer von vorne beginnt. Das hat auch 
wunderbar funktioniert. Erst als ich probiert hab den Overflow Wert 
herab zu setzen mit hilfe des OCR0 Registers hat es nicht mehr 
funktioniert. Also das die Register falsch gesetzt sind und das ganze 
nicht zusammen passt weis ich selbst, denn sonst würde der 
Mikrocontroller ja das tun was ich will. Ich hatte eher gehofft mir 
könnte jemand sagen wie ich es besser machen kann.

Außerdem besitze ich leider kein C-Buch und kann somit nur mit den 
Internetseiten arbeiten. Mithilfe dieser Seiten bekomm ich es aber 
einfach nicht hin.

von Schiko (Gast)


Lesenswert?

Ich meine mich zu erinnern, es den Compareinterrupt beim Mega8/16 nur 
beim 16bit Timer.

von JOY (Gast)


Lesenswert?

Schiko schrieb:
> Ich meine mich zu erinnern, es den Compareinterrupt beim Mega8/16 nur
> beim 16bit Timer.

Das stimmt nicht siehe Datenblatt TIMER/COUNTER0:

TIMSK Bit 1 – OCIE0: Timer/Counter0 Output Compare Match Interrupt 
Enable

TIFR Bit 1 – OCF0: Output Compare Flag 0

von Michael (Gast)


Lesenswert?

Ist dein Simulator in der Entwicklungsumgebung kaputt? Damit kannst du 
den Programmablauf Schritt für Schritt simulieren und dabei alle 
Register verfolgen.

von Stefan E. (sternst)


Lesenswert?

terminator schrieb:
> Ich hatte eher gehofft mir
> könnte jemand sagen wie ich es besser machen kann.

Die drei Probleme deines Codes hatte ich dir genannt. Jetzt musst du 
dich daran machen diese zu lösen. Klar könnte ich dir eben auf die 
Schnelle den richtigen Code hinschreiben, aber der Lerneffekt für dich 
wäre dabei nahe Null.

terminator schrieb:
> Außerdem besitze ich leider kein C-Buch

Du kannst eine Programmiersprache aber nicht durch Anschauen von 
Beispielen und Raten erlernen. Denn dann kommen genau solche Unsinnigen 
Zeilen dabei raus:
1
  TCCR0 = (1<<CS01), (1<<WGM00);
Wenn du dir kein Buch anschaffen möchtest, kannst du dir auch eines in 
der nächsten Bibliothek ausleihen. Oder zumindest ein Tutorial im 
Internet suchen und durcharbeiten.

terminator schrieb:
> kann somit nur mit den
> Internetseiten arbeiten. Mithilfe dieser Seiten bekomm ich es aber
> einfach nicht hin.

Die Internetseiten mit ihren Beispielen sind nicht relevant. Die 
vermitteln dir höchstens ein paar Grundlagen. Wenn es darum geht, ein 
konkretes Programm für einen konkreten Controller zu schreiben, ist das 
Datenblatt zu genau diesem Controller die maßgebende Instanz. Dort musst 
du schauen, wie der CTC-Modus aktiviert wird.

von JOY (Gast)


Lesenswert?

So sollte es gehen, habe es auch getestet :-)
Gruß JOY

#include <avr/io.h>
#include <avr/interrupt.h>

//Zählvariable deklarieren
volatile int i=0;

ISR(TIMER0_COMP_vect) {
  //Bei jedem Overflow Zählvariable um eins erhöhen
  i++;
  //Nach 10.000 Overflows PINs auf high setzen entsprich einer sekunde
  if(i == 10000) {
    PORTD = 0b01100000;
  }
  //10.000 overflows später PINs auf low setzen entspricht einer sekunde
  if(i == 20000) {
    PORTD = 0b00000000;
    //Zählvariable auf null setzen damit das ganze von vorn beginnt
    i=0;
  }
}

int main() {
  //Datenrichtung definieren
  DDRD = 0b01100000;
  //Timer 0 initialisieren
  TCCR0 = (1<<CS01)|(1<<WGM01);
  //Interrupts aktivieren
  TIMSK |= (1<<OCIE0);
  //Überlaufwert bei 100
  OCR0 = 100;
  //Globale Interrupts aktivieren
  sei();
  while(1) {
  //hier könnte ihr programm stehen!!!
  }
}

von terminator (Gast)


Lesenswert?

Hey JOY,

Ein großes DANKESCHÖN an dich. Der Code funktioniert wunderbar. Ich seh 
auch schon was falsch war. Da Schiko geschrieben hat das es den 
Compareinterrupt nur beim 16bit timer gibt hab ich den CTC-Modus beim 
timer1 programmiert. Der geht aber auch. Aber trotzdem bin ich jetzt 
froh das es auch beim timer 0 geht.

Nochmals vielen Dank für die Hilfe.

von Uwe (de0508)


Lesenswert?

Hallo Gast(terminator),

ich habe noch eine Frage, warum lässt Du den
1
OCR0 = 100;
 bis 101 zählen ?

von terminator (Gast)


Lesenswert?

Hi Uwe,

wird zu dem eingegebenen Wert immer noch 1 dazu gezählt? Ich hab mich 
nämlich schon gewundert warum bei vielen Beispiel Codes im Internet z.b
OCR0 = 125-1 steht. Ich schätze jetzt weis ich warum. Aber wieso heißt 
100 eingentlich 101. Naja wenn mans weis kann man es ja berücksichtigen 
und immer -1 dahinter schreiben. Auf jeden Fall danke für den Hinweis.

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.