概要
Arduino Mega では Timer2 がうまく機能しません。
一度躓いたので、他の方へメモを残します。
Timer3
download : https://github.com/PaulStoffregen/TimerThree
# include <TimerThree.h>
volatile int n = 0;
void function(){
n++;
}
void setup() {
Serial.begin(115200);
Timer3.initialize(100000); //マイクロ秒単位で設定
Timer3.attachInterrupt(function);
}
void loop() {
Serial.println(n);
}
Timer1
Arduino micro を使っていたときに入れたのでどこでダウンロードしたか忘れましたが、Arudino UNO用がそのまま動きます。
# include <TimerOne.h>
volatile int n = 0;
void function(){
n++;
}
void setup() {
Serial.begin(115200);
Timer1.initialize(100000); //マイクロ秒単位で設定
Timer1.attachInterrupt(function);
}
void loop() {
Serial.println(n);
}
Timer2
この方を参考にライブラリに変更を加えました。
http://mironal-memo.blogspot.com/2012/02/arduinoarduino-mega-adk-or-arduino-mega.html
MsTimer2.cppに少し変更を加えれば動きます。
MsTimer2.cpp
# include <MsTimer2.h>
unsigned long MsTimer2::msecs;
void (*MsTimer2::func)();
volatile unsigned long MsTimer2::count;
volatile char MsTimer2::overflowing;
volatile unsigned int MsTimer2::tcnt2;
void MsTimer2::set(unsigned long ms, void (*f)()) {
float prescaler = 0.0;
# if defined(__AVR_ATmega168__) || defined(__AVR_ATmega48__) || defined(__AVR_ATmega88__) || defined(__AVR_ATmega328P__) || (__AVR_ATmega1280__) || (__AVR_ATmega2560__)
TIMSK2 &= ~(1<<TOIE2);
TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
TCCR2B &= ~(1<<WGM22);
ASSR &= ~(1<<AS2);
TIMSK2 &= ~(1<<OCIE2A);
if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) { // prescaler set to 64
TCCR2B |= (1<<CS22);
TCCR2B &= ~((1<<CS21) | (1<<CS20));
prescaler = 64.0;
} else if (F_CPU < 1000000UL) { // prescaler set to 8
TCCR2B |= (1<<CS21);
TCCR2B &= ~((1<<CS22) | (1<<CS20));
prescaler = 8.0;
} else { // F_CPU > 16Mhz, prescaler set to 128
TCCR2B |= ((1<<CS22) | (1<<CS20));
TCCR2B &= ~(1<<CS21);
prescaler = 128.0;
}
# elif defined (__AVR_ATmega8__)
TIMSK &= ~(1<<TOIE2);
TCCR2 &= ~((1<<WGM21) | (1<<WGM20));
TIMSK &= ~(1<<OCIE2);
ASSR &= ~(1<<AS2);
if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) { // prescaler set to 64
TCCR2 |= (1<<CS22);
TCCR2 &= ~((1<<CS21) | (1<<CS20));
prescaler = 64.0;
} else if (F_CPU < 1000000UL) { // prescaler set to 8
TCCR2 |= (1<<CS21);
TCCR2 &= ~((1<<CS22) | (1<<CS20));
prescaler = 8.0;
} else { // F_CPU > 16Mhz, prescaler set to 128
TCCR2 |= ((1<<CS22) && (1<<CS20));
TCCR2 &= ~(1<<CS21);
prescaler = 128.0;
}
# elif defined (__AVR_ATmega128__)
TIMSK &= ~(1<<TOIE2);
TCCR2 &= ~((1<<WGM21) | (1<<WGM20));
TIMSK &= ~(1<<OCIE2);
if ((F_CPU >= 1000000UL) && (F_CPU <= 16000000UL)) { // prescaler set to 64
TCCR2 |= ((1<<CS21) | (1<<CS20));
TCCR2 &= ~(1<<CS22);
prescaler = 64.0;
} else if (F_CPU < 1000000UL) { // prescaler set to 8
TCCR2 |= (1<<CS21);
TCCR2 &= ~((1<<CS22) | (1<<CS20));
prescaler = 8.0;
} else { // F_CPU > 16Mhz, prescaler set to 256
TCCR2 |= (1<<CS22);
TCCR2 &= ~((1<<CS21) | (1<<CS20));
prescaler = 256.0;
}
# endif
tcnt2 = 256 - (int)((float)F_CPU * 0.001 / prescaler);
if (ms == 0)
msecs = 1;
else
msecs = ms;
func = f;
}
void MsTimer2::start() {
count = 0;
overflowing = 0;
# if defined(__AVR_ATmega168__) || defined(__AVR_ATmega48__) || defined(__AVR_ATmega88__) || defined(__AVR_ATmega328P__) || (__AVR_ATmega1280__) || (__AVR_ATmega2560__)
TCNT2 = tcnt2;
TIMSK2 |= (1<<TOIE2);
# elif defined (__AVR_ATmega128__)
TCNT2 = tcnt2;
TIMSK |= (1<<TOIE2);
# elif defined (__AVR_ATmega8__)
TCNT2 = tcnt2;
TIMSK |= (1<<TOIE2);
# endif
}
void MsTimer2::stop() {
# if defined(__AVR_ATmega168__) || defined(__AVR_ATmega48__) || defined(__AVR_ATmega88__) || defined(__AVR_ATmega328P__) || (__AVR_ATmega1280__) || (__AVR_ATmega2560__)
TIMSK2 &= ~(1<<TOIE2);
# elif defined (__AVR_ATmega128__)
TIMSK &= ~(1<<TOIE2);
# elif defined (__AVR_ATmega8__)
TIMSK &= ~(1<<TOIE2);
# endif
}
void MsTimer2::_overflow() {
count += 1;
if (count >= msecs && !overflowing) {
overflowing = 1;
count = 0;
(*func)();
overflowing = 0;
}
}
ISR(TIMER2_OVF_vect) {
# if defined(__AVR_ATmega168__) || defined(__AVR_ATmega48__) || defined(__AVR_ATmega88__) || defined(__AVR_ATmega328P__) || (__AVR_ATmega1280__) || (__AVR_ATmega2560__)
TCNT2 = MsTimer2::tcnt2;
# elif defined (__AVR_ATmega128__)
TCNT2 = MsTimer2::tcnt2;
# elif defined (__AVR_ATmega8__)
TCNT2 = MsTimer2::tcnt2;
# endif
MsTimer2::_overflow();
}
後は、いつもの通り書けば動きます。
MsTimer2_Test
# include <MsTimer2.h>
volatile int n = 0;
void function(){
n++;
}
void setup() {
Serial.begin(115200);
MsTimer2::set(100, function);
MsTimer2::start();
}
void loop() {
Serial.println(n);
}