Go Down

Topic: ATTiny 85 20PU programmieren ( UNO) mit timer interrupt. Fragen (Read 724 times) previous topic - next topic

die_Diode

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)
Code: [Select]
#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.
my biggest Arduino -Project: http://blog.arduino.cc/2014/07/15/diy-pulsoximeter-developed-with-two-arduino/

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.


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


Hallo,

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

Gruß,
Ralf
Es gibt 10 Arten von Menschen, die einen verstehen Binär, die anderen nicht...

die_Diode



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


Hallo,

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

Gruß,
Ralf


http://hlt.media.mit.edu/?p=1695
my biggest Arduino -Project: http://blog.arduino.cc/2014/07/15/diy-pulsoximeter-developed-with-two-arduino/

die_Diode

#4
Oct 25, 2013, 05:42 pm Last Edit: Oct 25, 2013, 05:58 pm by Buttman01 Reason: 1

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)
Code: [Select]
#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);
}
my biggest Arduino -Project: http://blog.arduino.cc/2014/07/15/diy-pulsoximeter-developed-with-two-arduino/

Serenifly

#5
Oct 25, 2013, 06:07 pm Last Edit: Oct 25, 2013, 06:23 pm by Serenifly Reason: 1
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.

Code: [Select]

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.

die_Diode


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.

Code: [Select]

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
my biggest Arduino -Project: http://blog.arduino.cc/2014/07/15/diy-pulsoximeter-developed-with-two-arduino/

Serenifly

:)

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

die_Diode


:)

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


Hab ich mir schon gedacht und grad angepasst! ( mit presc. 16)
Code: [Select]
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!
my biggest Arduino -Project: http://blog.arduino.cc/2014/07/15/diy-pulsoximeter-developed-with-two-arduino/

Serenifly

Noch ne Kleinigkeit:

Code: [Select]

#include <MsTimer2.h>


und

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

die_Diode

my biggest Arduino -Project: http://blog.arduino.cc/2014/07/15/diy-pulsoximeter-developed-with-two-arduino/

Go Up