目次
前
次
ArduinoMega2560タイマー処理
ピン数の多いArduinoがないかと探していると
知人からArduinoMegaがあると、言われました。
動作確認するため、ArduinoIDEのライブラリに
いれてあるMsTimer2を使うことにしました。
基板上にあるLEDをブリンクするように仕様を
決めたのに、まったく点滅しません。
MsTimer2を使うために、次のコードをsetupに書き込み。
/* 2000ms period */
MsTimer2::set(XINTERVAL,update_trigger);
/* enable */
MsTimer2::start();
タイマー割込みが発生すると、関数update_triggerを
呼び出されます。
この関数の内容は、次のように単純。
void update_trigger()
{
tflag = ON ;
}
さらに、イベント通知フラグを利用してLEDを
点滅するために、次のコードをloop()の中に
入れてます。
#define LED_BIT 13
if ( tflag ) {
/* clear flag */
tflag = OFF ;
/* blink built-in LED */
digitalWrite( LED_BIT , bitRead( xcnt , 0 ) );
/* update */
xcnt++ ;
}
イベント通知フラグがセットされない限り
LEDの状態遷移が発生しないので、ブリンク
動作がおきないと判断しました。
調べてみると、ArduinoMega2560がMsTimer2の
ソースコードに含まれていないのが、割込み
が発生しない原因とわかりました。
具体的には、MsTimer2.cppにArduinoMega2560で
使うという指定が含まれていないと。
そこで、次のように、マクロ定義している部分を
変更しました。下線を入れてます。
#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();
}
ArduinoMega2560はArduinoMega1280とチップ内のSFRの
アドレスが同じなので、追加するだけで済みました。
マクロの一部に追加をして、改めてスケッチをコンパイル、リンクし
さらにダウンロードしたスケッチでは、LEDがブリンクできることを
確認できました。
目次
前
次