あなたの天然記念物
ホーム更新雑談Perl鉄ゲタランドナーコースガイド自転車Linuxリンク経歴連絡先

高精度タイマーを使う (2012.03.06)

26.7μsを待てばいいのに1000μsも待つのはどうかと

接続したLCDは、I2Cでコマンドを送信してから26.7μsのウエイトが必要なのです。 FreeRTOSのDelayは1ms単位(TickTime)ですしタイマーも同様です。 ですので、μs単位のDelay関数を用意してありますが、1ms未満のDelayも1msだけ待っています。 より短時間(高精度)のタイマーを使いたい時は、マイコンの仕掛けを直接使って実現することになります。 LPCXpresso(1768)の場合、マイコンの中にタイマー/カウンター兼用の装置が4組入っています。そのうちの1つを使って1μs単位のDelay機能を用意しました。 タイマーへ供給するクロックはCPUのクロック100MHzのまま使って、プリスケーラで100分の1に落とすと、ちょうど1MHzになってクロック間隔が1μsになるという具合。
static xQueueHandle pQueueTimer = NULL;
static uint32_t uTimer = 0;

//タイマー割り込み
void TIMER0_IRQHandler(void)
{
    unsigned long ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();

    //タイマー値が残っていればカウントダウン
    if (0 < uTimer)
    {
        uTimer--;
        //0で呼び出し元へダミーのデータを送信する
        if (!uTimer)
        {
            portBASE_TYPE HigherPriorityTaskWoken = pdFALSE;
            xQueueSendFromISR(pQueueTimer, "t", &HigherPriorityTaskWoken);
            if (HigherPriorityTaskWoken)
            {
                //中身はvPortYieldFromISR
                taskYIELD();
            }
        }
    }

    portCLEAR_INTERRUPT_MASK_FROM_ISR(ulDummy);
}

void timer_delay_us(uint32_t uMicroS)
{
    //入れた途端にカウントダウンする場合があるので、+1
    uTimer = uMicroS + 1;
    uint8_t ucDummy;
    if (pQueueTimer)
    {
        //カウント0でキューにダミーデータが入るのを待つ
        xQueueReceive(pQueueTimer, &ucDummy, portMAX_DELAY);
    }
}
今ソース見て気づいたけど、タイマーに時間を指定すると、時間が来た時に割り込みルーチンに制御が来るので、 わざわざプログラムでカウントダウンしなくてもいいんだ。 ここは次の機会に改善しておこう。
さて、今回の鉄ゲタコーナーは…ありません(ほっ)。

まあ、どうせ話が通じないと思うので、あとはソース見てください(^^;
yrntrlmnmnt20120214.zip (253,009 バイトをVPSから 00:05 で)