Hallo, seit langem wieder hier.
Mir wurde hier im Sommer zu einem kleinen Projekt ( Timer Interupt) geholfen.
Aufgabe: Einen 2 -er led- Schaltakt mit 500µs an zeit, und 1500µs aus Zeit. beide leds schalten im Zeitmultiplex.
hier der code auf meinem Aurduino mega( der auch funktioniert)
#include <MsTimer2.h>
int led1 = 43; // pin 43
int led2 =44; // pin 44
volatile byte counter = 0;
void setup()
{
pinMode (led1,OUTPUT);
pinMode (led2,OUTPUT);
initTimer2();
}
void loop(){
//hier mal nix
}
ISR(TIMER2_COMPA_vect) { // das ist der Richtige aufruf des "Timer Interrupt" ISR Interupt Service Routine
counter = (counter + 1) % 4;
switch(counter) {
case 0:
digitalWrite(led1,HIGH); // 500µs an
digitalWrite(led2,LOW); // 500µs aus
break;
case 1:
digitalWrite(led1,LOW); // 500µs aus
digitalWrite(led2,LOW); // 500µs aus
break;
case 2:
digitalWrite(led1,LOW); // 500µs aus
digitalWrite(led2,HIGH); // 500µs an
break;
case 3:
digitalWrite(led1,LOW); // 500µs aus
digitalWrite(led2,LOW); // 500µs aus
break;
}
}
void initTimer2()
{
// Timer 2 CTC mode, prescaler 64
TCCR2B = (1<<CS22); // CS für prescaler 64
TCCR2A = (1<<WGM21); // ctc
OCR2A = 124; // [(16Mhz/64)*500µs]-1 = 124
// enable Timer 2 interrupts
TIMSK2 = (1<<OCIE2A);
}
Nun möchte ich die selbe Funktionen auf einen Attiny85 20 pu übertragen
Eine Anleitung zum Arduino isp Programmieren gibt es ja von so ner MIT-Seite.
Nun zum Grundsätzlichen bevor ich was falsch mache:
Nach dem datenblatt zur Urteilen gibt es nur nen timer 0 und timer 1.
Ich denke ganz stark, dass ich die oben benutzte timer2 bibliothek nicht nutzen kann.
wie soll ich das problem umgehen? Über nen Denkanstoß wäre ich sehr dankbar.
Du kannst da genauso Timer1 verwenden. Das ist halt ein 8 Bit Timer. Du musst nur den Prescaler und Compare Match Wert anpassen. Und der CTC Modus wird anders aktiviert (über das CTC1 Bit im TCCR1 Register).
Aber das Prinzip ist gleich.
Bei Atmega328 wird nur gerne Timer2 verwendet, da der eine größere Auswahl an Prescaler Einstellungen hat.
Serenifly:
Du kannst da genauso Timer1 verwenden. Das ist halt ein 8 Bit Timer. Du musst nur den Prescaler und Compare Match Wert anpassen. Und der CTC Modus wird anders aktiviert (über das CTC1 Bit im TCCR1 Register).
Aber das Prinzip ist gleich.
Bei Atmega328 wird nur gerne Timer2 verwendet, da der eine größere Auswahl an Prescaler Einstellungen hat.
ok dann hätte ich folgende Änderung: ( für internal Clock 8 Mhz)
#include <Event.h>
#include <Timer.h>
int led1 =0
int led2 =1
volatile byte counter = 0;
void setup()
{
pinMode (led1,OUTPUT);
pinMode (led2,OUTPUT);
initTimer1();
}
void loop(){
//hier mal nix
}
ISR(TIMER1_COMPA_vect) { // das ist der Richtige aufruf des "Timer Interrupt" ISR Interupt Service Routine
counter = (counter + 1) % 4;
switch(counter) {
case 0:
digitalWrite(led1,HIGH); // 500µs an
digitalWrite(led2,LOW); // 500µs aus
break;
case 1:
digitalWrite(led1,LOW); // 500µs aus
digitalWrite(led2,LOW); // 500µs aus
break;
case 2:
digitalWrite(led1,LOW); // 500µs aus
digitalWrite(led2,HIGH); // 500µs an
break;
case 3:
digitalWrite(led1,LOW); // 500µs aus
digitalWrite(led2,LOW); // 500µs aus
break;
}
}
void initTimer1() // psc: 32 , internal clock 8MHz
{
// Timer 1 CTC mode, prescaler 32
TCCR1B = (1<<CS12) | (1<<CS11); // CS für prescaler 32 datenblatt s.93
TCCR1A = (1<<CTC1); // ctc
OCR1A = 124; // [(8Mhz/32)*500µs]-1 = 124
// enable Timer 2 interrupts
TIMSK1 = (1<<OCIE1A);
}
Vorsicht. Die Register heißen zum Teil anders! Zumindest bei Timer1. Timer0 ist eher wie der Timer2 beim Atmega. Da gibt es z.B. die WGM0m Bits.
Bei Timer1 ist das Control Register TCCR1! Es gibt keine 2 Control Register. Die CS Bits und das CTC1 Bit sind alle in diesem Register.
Was ich vorhin auch nicht gesehen hatte, ist dass der CTC Modus etwas anders ist. Das CTC1 Bit funktioniert anscheinend nur mit OCR1C. Nicht mir A und B. Das sorgt dafür, dass das Counter Register bei einem Compare Match wieder auf 0 gesetzt wird.
EDIT:
Was ich aber nicht verstehe ist wo dann das entsprechende Interrupt Enable Bit ist. Da gibt es in TIMSK nur Bits für A und B. Auch das Block Diagramm zeigt nur Interrupts für A und B. Seltsam.
Da ist möglich, dass man mit C dann keinen Interrupt auslösen kann wenn es kein Flag gibt. Vielleicht doch besser wenn man Timer0 verwendet. Oder Timer1 mit A oder B Register und das Counter Register per Hand zurücksetzen. Das sollte auch funktionieren.
Serenifly:
Vorsicht. Die Register heißen zum Teil anders! Zumindest bei Timer1. Timer0 ist eher wie der Timer2 beim Atmega. Da gibt es z.B. die WGM0m Bits.
Bei Timer1 ist das Control Register TCCR1! Es gibt keine 2 Control Register. Die CS Bits und das CTC1 Bit sind alle in diesem Register.
Was ich vorhin auch nicht gesehen hatte, ist dass der CTC Modus etwas anders ist. Das CTC1 Bit funktioniert anscheinend nur mit OCR1C. Nicht mir A und B. Das sorgt dafür, dass das Counter Register bei einem Compare Match wieder auf 0 gesetzt wird.
EDIT:
Was ich aber nicht verstehe ist wo dann das entsprechende Interrupt Enable Bit ist. Da gibt es in TIMSK nur Bits für A und B. Auch das Block Diagramm zeigt nur Interrupts für A und B. Seltsam.
Da ist möglich, dass man mit C dann keinen Interrupt auslösen kann wenn es kein Flag gibt. Vielleicht doch besser wenn man Timer0 verwendet. Oder Timer1 mit A oder B Register und das Counter Register per Hand zurücksetzen. Das sollte auch funktionieren.
ISR(TIMER1_COMPA_vect)
{
TCNT1 = 0;
....
}
void initTimer1()
{
TCCR1 = (1<<CS12) | (1<<CS11)
OCR1A = 124;
TIMSK = (1<<OCIE1A); //auch das Register heißt anders
}
Ob es geht musst du selbst testen. Habe das Ding nicht hier.
Herzlichen Dank läuft eins A!!!
hab zwar ca 20µs mehr, aber dat stört mich nicht. ist an ja beiden Ausgängen kongruent. Danke nochmal
Ich denke ganz stark, dass ich die oben benutzte timer2 bibliothek nicht nutzen kann.
Das ist ein Relikt als dir am Anfang mal jemand vorgeschlagen hat MsTimer2 zu nehmen, obwohl du µs gebraucht hast. Diese Bibliothek wird gar nicht verwendet. Statt dessen wird der Timer direkt programiert. Das include kannst du also entfernen.