GPTを使用した外部パルス幅測定機能

Yamamotoです。

実現したいこと:信号Hiの時間計測

マイコン:RA6T2

FSP:5.4.0

信号をGTETRGCピンに割り当てました。ハードウェア編の21.3.12 に説明のある「外部パルス幅測定機能」を使おうとしています。FSPではこの機能を実現できるスタックは提供されていないように思えますが、その認識で正しいでしょうか?もし対応しているスタックがあるのでしたら教えてください。AB相エンコーダでGPT3、PLS/DIRカウンタでGPT2、3相PWMでGPT4/5/6は使用済みで、他のチャンネルは現在未使用です。未使用のGPTチャンネルを使って信号のゲート時間測定をしたいわけです。

よろしくお願い致します。

  • stackとしては、Timer, General PWM(通常のGPT)で良いかと思います。

    1点おまじないが必要で、

    ・(使用しなくても)r_peogスタックを追加

    ・POEGのスタンバイ解除

    のどちらかが必要です。(前者はFSPの設定で可能ですが、後者はユーザコード内に書く。以下に提示する方法では、後者としています。)

    ・タイマの追加

    ハードコピーはGPT0としていますが、GPTの空き番号なら何でも良いと思います。

    ・波形のriseエッジのイベント

    この例では、riseエッジでタイマカウンタをクリアする事にしました。

    ・波形のfallエッジのイベント

    この例では、CAPTURE Aとしています。

    ・割り込み等

    割り込みと、波形のノイズフィルタの設定(任意)です。

    ・GETERGC端子の選択

    使用する端子を選びます。

    #include "hal_data.h"
    
    FSP_CPP_HEADER
    void R_BSP_WarmStart(bsp_warm_start_event_t event);
    FSP_CPP_FOOTER
    
    /*******************************************************************************************************************//**
     * main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used.  This function
     * is called by main() when no RTOS is used.
     **********************************************************************************************************************/
    void hal_entry(void)
    {
        /* TODO: add your own code here */
        /* モジュールストップ解除 */
        R_SYSTEM->PRCR = 0xA502;
        R_MSTP->MSTPCRD_b.MSTPD11 = 0;  //POEGスタンバイ解除
        R_MSTP->MSTPCRD_b.MSTPD12 = 0;  //GTETRGx端子の読み取りに
        R_MSTP->MSTPCRD_b.MSTPD13 = 0;  //POEGを使っているので
        R_MSTP->MSTPCRD_b.MSTPD14 = 0;  //POEGをモジュール解除しておく
        R_SYSTEM->PRCR = 0xA500;
    
        (void) R_GPT_Open(&g_timer0_ctrl, &g_timer0_cfg);
    
        (void) R_GPT_Enable(&g_timer0_ctrl);    //インプットキャプチャ有効
    
        (void) R_GPT_Start(&g_timer0_ctrl);     //タイマはフリーラン
    
        while(1)
        {
            __NOP();
        }
    
    #if BSP_TZ_SECURE_BUILD
        /* Enter non-secure code */
        R_BSP_NonSecureEnter();
    #endif
    }
    
    /*******************************************************************************************************************//**
     * This function is called at various points during the startup process.  This implementation uses the event that is
     * called right before main() to set up the pins.
     *
     * @param[in]  event    Where at in the start up process the code is currently at
     **********************************************************************************************************************/
    void R_BSP_WarmStart(bsp_warm_start_event_t event)
    {
        if (BSP_WARM_START_RESET == event)
        {
    #if BSP_FEATURE_FLASH_LP_VERSION != 0
    
            /* Enable reading from data flash. */
            R_FACI_LP->DFLCTL = 1U;
    
            /* Would normally have to wait tDSTOP(6us) for data flash recovery. Placing the enable here, before clock and
             * C runtime initialization, should negate the need for a delay since the initialization will typically take more than 6us. */
    #endif
        }
    
        if (BSP_WARM_START_POST_C == event)
        {
            /* C runtime environment and system clocks are setup. */
    
            /* Configure pins. */
            R_IOPORT_Open (&IOPORT_CFG_CTRL, &IOPORT_CFG_NAME);
    
    #if BSP_CFG_SDRAM_ENABLED
    
            /* Setup SDRAM and initialize it. Must configure pins first. */
            R_BSP_SdramInit(true);
    #endif
        }
    }
    
    #if BSP_TZ_SECURE_BUILD
    
    FSP_CPP_HEADER
    BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ();
    
    /* Trustzone Secure Projects require at least one nonsecure callable function in order to build (Remove this if it is not required to build). */
    BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ()
    {
    
    }
    FSP_CPP_FOOTER
    
    #endif
    
    void gpt0_callback (timer_callback_args_t * p_args)
    {
        static volatile unsigned long count_a;
        static volatile unsigned long count_u = 0;
    
        if (TIMER_EVENT_CAPTURE_A  == p_args->event)
        {
            count_a = R_GPT0->GTCCR[0]; //GTCCRA, キャプチャAカウンタ
        }
    
        if (TIMER_EVENT_CYCLE_END == p_args->event)
        {
            //GTCCLK=120MHzの場合、37秒以上のパルス幅を計測したい場合必要、計測前にcount_uはクリア
            count_u++;
        }
    }
    

    この例では、タイマはフリーランでカウントアップを続ける状態として、GETERGC↑でタイマをリセット。GETERGC↓でキャプチャ。

    GTCCRAレジスタに、Hのパルス幅の値を取得する事としています。

    (GETERGCのエッジで、タイマをスタートしたり、ストップしたり、両エッジをキャプチャAとキャプチャBに割り当てるなど、割り当ては自由です。)

    ※FSPは、5.5.0の環境で動作を確認しました

  • 設定内容を考えると測定用の端子がONの間にGTCNTがカウントアップする動作ではないので外部パルス幅測定機能動作とは厳密には違うようですが、これなら同じことが実現できそうです。

    ご回答ありがとうございます。レジスタを直接叩くのは先のことを考えるとメンテが面倒なのでこれを利用させていただきます。

  • >測定用の端子がONの間にGTCNTがカウントアップする動作

    ・R_GPT_Start()を実行しない

    GETERGC↑でタイマスタート

    ・GETERGC↓でタイマストップ

    上記の様にすると、GTCNTレジスタでH期間の積算を算出出来ると思います(実動作は試していませんが)

  • 後者は試しましたがカウントアップするイベントを指定できなくてゼロのままでした。そしてここに質問に来ています。また、エッジスタートですと最初Hiの場合にスタートしないのでロジック切り分けが面倒です。ちなみに測定対象は信号Hiが規定時間以上でエラーという判定をするために使います。そのものの設定ができないのが残念ですが、実現できれば手段はなんでも構いません。AGTのFSPスタックではできそうですが、ピンの割り当てがGPT向けにしてしまったので時すでに遅し。

  • CountUpSourceのところで、どこにもチェックを入れない状態ですと、ソースはPCLKD/GPTCLKになりますので、↑から↓の間カウントアップさせる事は可能です(実動作を確かめました)。

    でも、エッジではなく、H期間

    に関しては、上記設定かと思いますが、この設定はざっと見る限り、FSPでは設定出来ない様です。

    (FSP5.6.0以降に期待でしょうか。)

  • R_GPT0->GTUPSR_b.USILVL = 0x0d; //これは、FSPの設定ではなくユーザが追加要

    R_GPT_Start(); //タイマスタートは実行する

    上記で、やりたい事(GTETRGC=Hの間だけ、GTCNTをカウントアップする)事が実現出来る事を、実動作で確認致しました。(エッジではなく、レベル動作)

    (GPTタイマは、結構便利ですね。RXもMTU(多機能なんでしょうけど、結構複雑なイメージ)に変わりGPTを搭載する(もしくはMTU&GPT)マイコンが増えてきた様に思えます。)