Arduinoで遊ぶページ

Arduinoで遊んだ結果を残すページです。
garretlab
micros()

micros()

概要

micros()は、内部で保持しているArduinoを起動してからの時間をマイクロ秒単位で返します。

micros()のリファレンスはこちらをご覧ください。

ソースコード

micros()は、hardware/arduino/avr/cores/arduino/wiring.c に定義されています。以下に全ソースコードを示します。

unsigned long micros() {
	unsigned long m;
	uint8_t oldSREG = SREG, t;
	
	cli();
	m = timer0_overflow_count;
	t = TCNT0;
	t = TCNT0L;

	if ((TIFR0 & _BV(TOV0)) && (t < 255))
		m++;

	SREG = oldSREG;
	
	return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
}

micros()には、入力はありません。unsigned longを返します。

まず、状態レジスタを保存します。

unsigned long micros() {
	unsigned long m;
	uint8_t oldSREG = SREG, t;

SREGは、ATMega328Pの状態レジスタです。

次に、割り込みを禁止した後、timer0_overflow_countをmにコピーし、tにTCNT0の値を代入します。

	cli();
	m = timer0_overflow_count;
	t = TCNT0;

cli()は割り込みを禁止するアセンブラ命令を実行するマクロです。

timer0_overflow_countは、タイマ/カウンタ0がオーバーフローを起こした回数です。タイマ/カウンタ0の割り込みハンドラで設定されます。

TCNT0は、一定期間ごとにインクリメントされる8ビットのレジスタです。Arduino Unoでは、タイマ/カウンタ0の分周比を64に設定しているので、64クロックごとにTCNT0が1インクリメントされます。

TIFR0のTOV0ビットがセットされていて、かつ、TCNT0が255よりも小さいときには、mをインクリメントします。その後、状態レジスタをもとに戻します。

	if ((TIFR0 & _BV(TOV0)) && (t < 255))
		m++;

	SREG = oldSREG;

TIFR0のTOV0ビットは、タイマ/カウンタ0がオーバーフローを起こしたときに設定されるフラグです。_BV()は、1を指定したビット数だけ左シフトするマクロです。このビットが1かつtが255未満の場合は、オーバーフローを起こしているので、mをインクリメントします。micros()の最初にcli()で割り込みを禁止しているので、micros()実行中にオーバーフローを起こしても割り込みハンドラが起動されず、timer0_overflow_countがインクリメントされないためだと思われます。

最後に、今までの情報からArduinoを起動してからの時間をマイクロ秒に変換して返します。

	return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
}

mは、タイマ/カウンタ0がオーバーフローした回数で、TCNT0が256回インクリメントされるたびに1増えるので、m*256 + t = (m << 8) + t タイマクロック分の時刻が経過したことになります。

TCNT0は、64クロックに1回インクリメントされるため、(m << 8) + tに64クロックに要する時間を掛けることで、Arduinoを起動してからの時間が出てきます。

clockCyclesPerMicrosecond()は、1マイクロ秒あたりのクロック数を表すマクロなので、64/clockCyclesPerMicrosecond()は、64クロックサイクルに要する時間をマイクロ秒で表すことになります。

バージョン

Arduino 1.8.2



メニューを表示するためにJavaScriptを有効にしてください。

Arduinoで遊ぶページ
Copyright © 2016 garretlab all rights reserved.
inserted by FC2 system