ATTiny 85 20PU programmieren ( UNO) mit timer interrupt. Fragen

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:

  1. 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.

Buttman01:
Eine Anleitung zum Arduino isp Programmieren gibt es ja von so ner MIT-Seite.

Hallo,

sorry, ich bin wieder doof :blush:, aber was ist denn eine MIT-Seite?

Gruß,
Ralf

Schachmann:

Buttman01:
Eine Anleitung zum Arduino isp Programmieren gibt es ja von so ner MIT-Seite.

Hallo,

sorry, ich bin wieder doof :blush:, aber was ist denn eine MIT-Seite?

Gruß,
Ralf

http://hlt.media.mit.edu/?p=1695

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.

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.

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

:slight_smile:

Du kannst den Wert von OCR1A etwas verringern um das anzupaasen.

Serenifly:
:slight_smile:

Du kannst den Wert von OCR1A etwas verringern um das anzupaasen.

Hab ich mir schon gedacht und grad angepasst! ( mit presc. 16)

void initTimer1() 
{
  TCCR1 = (1<<CS12) | (1<<CS10);  
  OCR1A = 255;
  TIMSK = (1<<OCIE1A);       //auch das Register heißt anders
}

so sind die an und aus Zeiten ( 500µs an, 1500µs aus) exakt eingestellt.

Vielen Dank für die Mühe!

Noch ne Kleinigkeit:

#include <MsTimer2.h>

und

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.

Ahh, vielen Dank.