micros()

概要

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

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

ソースコード

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
unsigned long micros() {
    unsigned long m;
    uint8_t oldSREG = SREG, t;
     
    cli();
    m = timer0_overflow_count;
    t = TCNT0;
 
    if ((TIFR0 & _BV(TOV0)) && (t < 255))
        m++;
 
    SREG = oldSREG;
     
    return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
}

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

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

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

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

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

5
6
7
8
    cli();
    m = timer0_overflow_count;
    t = TCNT0;
}

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

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

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

 9
10
11
12
    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を起動してからの時間をマイクロ秒に変換して返します。

14
15
    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 AVR Boards 1.8.6

最終更新日

March 21, 2023

inserted by FC2 system