0

マイクロコントローラ:Arduino UnoのATmega328P
クロック周波数:16MHz

void timeDelay_CTC(float sec, unsigned char times)          //0.1 <= sec <= 4
{
    OCR1A = (sec / 0.000064f) - 1;
    TCCR1A = 0b00000000;
    TCCR1B = 0b00001101;
    for( unsigned char i = 1; i <= times; i++ )
    {
        while( (TIFR1 & (1<<OCF1A)) == 0 );
        TIFR1 |= (1<<OCF1A);
    }
    TCCR1A = 0;
    TCCR1B = 0;
}

上記の関数は、時間遅延サイクル数を計算するために使用され、CTC モードで実装されます。それはうまくいきます。さて、通常モードで同様の関数を書きたいと思います。以下がコードです。

void timeDelay_NORM(float sec, unsigned char times)
{
    unsigned int cycle = (sec / 0.000064f);
    TCNT1 = 65534 - cycle;
    TCNT1 = 49910;
    TCCR1A = 0b00000000;
    TCCR1B = 0b00000101;
    for( unsigned char x = 1; x <= 2; x++ )
    {
        while( (TIFR1 & (1<<TOV1)) == 0 );
        TIFR1 |= (1<<TOV1);
    }
    TCCR1A = 0;
    TCCR1B = 0;
}

ただし、引数 "times" > 1 を指定したノーマル モード関数では、時間遅延が予想よりもはるかに長くなります。というわけで、以下のコードを試してみました。

void timeDelay_NORM(float sec, unsigned char times)
{
    //unsigned int cycle = (sec / 0.000064f);
    //TCNT1 = 65534 - cycle;
    TCNT1 = 49910;                              //Cycles for 0.5sec
    TCCR1A = 0b00000000;
    TCCR1B = 0b00000101;
    //for( unsigned char x = 1; x <= 2; x++ )
    //{
        while( (TIFR1 & (1<<TOV1)) == 0 );      //Run 0.5sec two times to delay 1sec
        TIFR1 |= (1<<TOV1);
        while( (TIFR1 & (1<<TOV1)) == 0 );
        TIFR1 |= (1<<TOV1);
    //}
    TCCR1A = 0;
    TCCR1B = 0;
}

次の命令を 2 回実行すると、時間遅延が予想よりもはるかに長くなることがわかりました。遅延は 1 秒ではなく 5 秒程度です。

while( (TIFR1 & (1<<TOV1)) == 0 );
TIFR1 |= (1<<TOV1);

うまくいく方法を教えてもらえますか?またはヒントを教えてください。

ご協力ありがとうございました!

4

1 に答える 1

1

ループの反復間で TCNT1 をリセットしません。

最初のループでは、(UINT16_MAX - 49910) サイクルをカウントします。TOV1 が設定された後、TCNT1 は 0 にロールオーバー (オーバーフロー) し、UINT16_MAX までカウントアップします。これにより、遅延が長くなります。

于 2014-11-13T09:52:47.100 に答える