はじめに
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] に収められている。
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 |
サンプルコードのオリジナルは、下記の様になっている。(重要な部分のみ)
#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秒後に点灯することには変わりがない
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 を点滅させることが出来る。
この時は、設定をコメントアウトさせる
//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 も入れることが出来る。
この時 それぞれに対する設定は、下記の通り
//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秒後とに点滅させる様に下記の様に修正した
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 - 記述を追加