2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Arduino Mega の Timer 割り込みについて

Last updated at Posted at 2020-07-12

概要

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);
}
2
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?