1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

nRF52 シリーズ SDK RTCのサンプルコードの考察

Last updated at Posted at 2022-02-20

はじめに
Nordic nRF5x シリーズにて SDK に収められている RTC サンプルコードについての覚書

ここで用いた開発環境は、nRF5 SDK であり下記からダウンロード出来る。
https://www.nordicsemi.com/Products/Development-software/nRF5-SDK/Download

用いた サンプルコードは、[C:\nRF5_SDK_17.1.0_ddde560\examples\peripheral\rtc] に収められている。

参考:https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Frtc.html


Counter increment frequency:
fRTC [kHz] = 32.768 / (PRESCALER + 1)

Prescaler Counter resolution Overflow
0 30.517μs 512 seconds  
2^8-1 =256 7812.5μs 131072 seconds
2^12-1=4095 125ms 582.542 hours

サンプルコードのオリジナルは、下記の様になっている。(重要な部分のみ)

main.c
#define COMPARE_COUNTERTIME  (3UL) /**< Get Compare event COMPARE_TIME seconds after the counter starts from 0. */

/** @brief: Function for handling the RTC0 interrupts.
 * Triggered on TICK and COMPARE0 match.
 * config.prescaler = 4095 なので 125ms毎に割り込みが入って来る
 * 
 */
static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
{
    if (int_type == NRF_DRV_RTC_INT_COMPARE0)
    {
        nrf_gpio_pin_toggle(COMPARE_EVENT_OUTPUT);
    }
    else if (int_type == NRF_DRV_RTC_INT_TICK)
    {
        nrf_gpio_pin_toggle(TICK_EVENT_OUTPUT);
    }
}

static void rtc_config(void)
{
    uint32_t err_code;

    //Initialize RTC instance
    nrf_drv_rtc_config_t config = NRF_DRV_RTC_DEFAULT_CONFIG;
    config.prescaler = 4095; //★重要!! 125msの設定
    err_code = nrf_drv_rtc_init(&rtc, &config, rtc_handler);
    APP_ERROR_CHECK(err_code);

    //Enable tick event & interrupt
    nrf_drv_rtc_tick_enable(&rtc,true);

    //Set compare channel to trigger interrupt after COMPARE_COUNTERTIME seconds
    //125ms毎に割り込みが入ってくるので X8 をすることで 1秒を設定
    err_code = nrf_drv_rtc_cc_set(&rtc,0,COMPARE_COUNTERTIME * 8,true);
    APP_ERROR_CHECK(err_code);

    //Power on RTC instance
    nrf_drv_rtc_enable(&rtc);
}

オリジナルのサンプルでは、125ms毎に LED1 が点滅すると同時に
起動後 3秒後に LED2 が点灯するコードになっている。

そこで 1秒後とに LED1が点滅する様に変更した。
LED2は、起動後 3秒後に点灯することには変わりがない

main.c
uint8_t Rtc_Count = 0;
/** @brief: Function for handling the RTC0 interrupts.
 * Triggered on TICK and COMPARE0 match.
 */
static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
{
    Rtc_Count ++;
    if (int_type == NRF_DRV_RTC_INT_COMPARE0)
    {
        nrf_gpio_pin_toggle(COMPARE_EVENT_OUTPUT);
    }
    else { // >= 8 にしたのがポイント!!
           if (Rtc_Count >=8 && int_type == NRF_DRV_RTC_INT_TICK)
           {
             nrf_gpio_pin_toggle(TICK_EVENT_OUTPUT);
             Rtc_Count = 0;
           }
    }
}
/**
 * @brief Function for application main entry.
 */
int main(void)
{
    leds_config();

    lfclk_config();

    //点灯から始まる様に追加
    nrf_gpio_pin_toggle(TICK_EVENT_OUTPUT);

    rtc_config();

    while (true)
    {
        __SEV();
        __WFE();
        __WFE();
    }
}

125ms x 8 = 1秒に設定するため Rtc_Count ==8 としたところ 3秒以後 LED1 が消灯せずに 点滅した状態になる。
何故か不思議に思い rtc_handler() の引数int_type と Rtc_Count の時系列を調べると

time(ms) int_type Rtc_Count LED1 LED2
125 NRF_DRV_RTC_INT_TICK 0 -> 1 点灯 消灯
250 NRF_DRV_RTC_INT_TICK 1 -> 2 点灯 消灯
375 NRF_DRV_RTC_INT_TICK 2 -> 3 点灯 消灯
500 NRF_DRV_RTC_INT_TICK 3 -> 4 点灯 消灯
625 NRF_DRV_RTC_INT_TICK 4 -> 5 点灯 消灯
750 NRF_DRV_RTC_INT_TICK 5 -> 6 点灯 消灯
875 NRF_DRV_RTC_INT_TICK 6 -> 7 点灯 消灯
1000 NRF_DRV_RTC_INT_TICK 7 -> 8 ->0 点灯 消灯
1125 NRF_DRV_RTC_INT_TICK 0 -> 1 消灯 消灯
1250 NRF_DRV_RTC_INT_TICK 1 -> 2 消灯 消灯
1375 NRF_DRV_RTC_INT_TICK 2 -> 3 消灯 消灯
1500 NRF_DRV_RTC_INT_TICK 3 -> 4 消灯 消灯
1625 NRF_DRV_RTC_INT_TICK 4 -> 5 消灯 消灯
1750 NRF_DRV_RTC_INT_TICK 5 -> 6 消灯 消灯
1875 NRF_DRV_RTC_INT_TICK 6 -> 7 消灯 消灯
2000 NRF_DRV_RTC_INT_TICK 7 -> 8 ->0 点灯 消灯
2125 NRF_DRV_RTC_INT_TICK 0 -> 1 点灯 消灯
2250 NRF_DRV_RTC_INT_TICK 1 -> 2 点灯 消灯
2375 NRF_DRV_RTC_INT_TICK 2 -> 3 点灯 消灯
2500 NRF_DRV_RTC_INT_TICK 3 -> 4 点灯 消灯
2625 NRF_DRV_RTC_INT_TICK 4 -> 5 点灯 消灯
2750 NRF_DRV_RTC_INT_TICK 5 -> 6 点灯 消灯
2875 NRF_DRV_RTC_INT_TICK 6 -> 7 点灯 消灯
3000 NRF_DRV_RTC_INT_COMPARE0 7 -> 8 点灯 点灯
3125 NRF_DRV_RTC_INT_TICK 8 -> 9 点灯 点灯
3250 NRF_DRV_RTC_INT_TICK 9 -> 10 点灯 点灯
3375 NRF_DRV_RTC_INT_TICK 10 -> 11 点灯 点灯

上記の表の様に 3秒後は、 int_type = NRF_DRV_RTC_INT_COMPARE0 となり
int_type = NRF_DRV_RTC_INT_TICK とならないので
Rtc_Count ==8 の条件が飛ばされるのである。

故に Rtc_Count >=8 として回避した。
これが意味するのは、LED1は 起動直後 点灯 -> 1秒後に消灯 -> 2秒後に点灯 -> 3秒125msで消灯
なので、3秒後以後 125ms ズレることになる。

ちなみに Rtc_Count ==8 とした時
LED1 は、長い沈黙(点灯) の後 再び点滅を開始する。理由は、uint8_t Rtc_Count と定義しているので
256までカウントアップした後 0に戻る。沈黙時間を計測すると約30秒で
(125ms X 256) ÷ (125ms X 8) = 32(s) で計算通り。

また、
LED2 を考えなければ、1秒後とにLED1 を点滅させることが出来る。
この時は、設定をコメントアウトさせる

main.c
//Set compare channel to trigger interrupt after COMPARE_COUNTERTIME seconds
//125ms毎に割り込みが入ってくるので X8 をすることで 1秒を設定
//err_code = nrf_drv_rtc_cc_set(&rtc,0,COMPARE_COUNTERTIME * 8,true);
//APP_ERROR_CHECK(err_code);

rtc_handler() には、NRF_DRV_RTC_INT_COMPARE0 の他に
NRF_DRV_RTC_INT_COMPARE1, NRF_DRV_RTC_INT_COMPARE2, NRF_DRV_RTC_INT_COMPARE3 も入れることが出来る。

この時 それぞれに対する設定は、下記の通り

main.c
    //For NRF_DRV_RTC_INT_COMPARE0
    //125ms毎に割り込みが入ってくるので X8 をすることで 1秒を設定
    err_code = nrf_drv_rtc_cc_set(&rtc,0,COMPARE_COUNTERTIME * 8,true);
    APP_ERROR_CHECK(err_code);

    //For NRF_DRV_RTC_INT_COMPARE1
    //125ms毎に割り込みが入ってくるので X16 をすることで 2秒を設定
    err_code = nrf_drv_rtc_cc_set(&rtc,1,COMPARE_COUNTERTIME * 16,true);
    APP_ERROR_CHECK(err_code);

    //For NRF_DRV_RTC_INT_COMPARE2
    //125ms毎に割り込みが入ってくるので X24 をすることで 3秒を設定
    err_code = nrf_drv_rtc_cc_set(&rtc,2,COMPARE_COUNTERTIME * 24,true);
    APP_ERROR_CHECK(err_code);

    //For NRF_DRV_RTC_INT_COMPARE3
    //125ms毎に割り込みが入ってくるので X32 をすることで 4秒を設定
    err_code = nrf_drv_rtc_cc_set(&rtc,3,COMPARE_COUNTERTIME * 32,true);
    APP_ERROR_CHECK(err_code);

【Ver 1.20で追記】
LED2を活かしつつ、またLED1を 125ms ずらすことなく 1秒後とに点滅させる様に下記の様に修正した

main.c
uint8_t Rtc_Count = 0;

/** @brief: Function for handling the RTC0 interrupts.
 * Triggered on TICK and COMPARE0 match.
 */
static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
{
    Rtc_Count ++;
    if (int_type == NRF_DRV_RTC_INT_COMPARE0)
    {
        nrf_gpio_pin_toggle(COMPARE_EVENT_OUTPUT);
        //以下2行を追加
        nrf_gpio_pin_toggle(TICK_EVENT_OUTPUT);
        Rtc_Count = 0;
    }
    else {
           if (Rtc_Count ==8 && int_type == NRF_DRV_RTC_INT_TICK)
           {
             nrf_gpio_pin_toggle(TICK_EVENT_OUTPUT);
             Rtc_Count = 0;
           }
    }
}

☆2022年 2月20日(日) 午前10時40分 初版(Ver1.00) 作成
2022年 2月20日(日) 午後 1時40分 Ver1.10 - 間違いを修正
2022年 2月20日(日) 午後 2時45分 Ver1.20 - 記述を追加

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?