nRF52840含有3个RTC模块,如果使用官方FreeRTOS适配,则只能使用RTC0和RTC2.
RTC其中一个功能用于定时.此处RTC全称Real Timer Counter,不是我们说的走时间的那个RTC.
为了便于理解,最简化模型如此.
/* 用哪一个RTC. */
#define BLINK_RTC 0
/* 用这个RTC哪一个比较通道. */
#define BLINK_RTC_CC 1
/* 定义多少TICKS一次中断,这个计算公式可以算出1秒一次中断所需TICKS数. */
#define BLINK_RTC_TICKS (RTC_US_TO_TICKS( 1 * 1000 * 1000ULL, RTC_DEFAULT_CONFIG_FREQUENCY ) )
/* 中断传递的信号量 */
static SemaphoreHandle_t m_led_semaphore;
/* RTC配置 */
static nrf_drv_rtc_config_t const m_rtc_config = NRF_DRV_RTC_DEFAULT_CONFIG;
/* RTC实例 */
static nrf_drv_rtc_t const m_rtc = NRF_DRV_RTC_INSTANCE( BLINK_RTC );
static void blink_rtc_handler( nrf_drv_rtc_int_type_t int_type )
{
BaseType_t yield_req = pdFALSE;
if ( int_type == NRFX_RTC_INT_COMPARE1 )
{
/* 每次需要加时间,因为是绝对时间定时的. */
nrf_drv_rtc_cc_set( &m_rtc, BLINK_RTC_CC, (nrf_rtc_cc_get( m_rtc.p_reg, BLINK_RTC_CC ) + BLINK_RTC_TICKS) & RTC_COUNTER_COUNTER_Msk, true );
}
portYIELD_FROM_ISR( yield_req );
}
static void led_toggle_task_function( void * pvParameter )
{
/* blink_rtc_handler => 指定回调函数 */
nrf_drv_rtc_init( &m_rtc, &m_rtc_config, blink_rtc_handler );
/* m_rtc => 实例,BLINK_RTC_CC => 通道,BLINK_RTC_TICKS => 绝对间隔,true => 使能中断 */
nrf_drv_rtc_cc_set( &m_rtc, BLINK_RTC_CC, BLINK_RTC_TICKS, true );
nrf_drv_rtc_enable( &m_rtc );
m_led_semaphore = xSemaphoreCreateBinary();
while ( true )
{
nrf_gpio_pin_toggle( 13 );
xSemaphoreTake( m_led_semaphore, portMAX_DELAY )
}
}
这里的关键就那么几个,中断源的判断.

每次进去都要增加,到OVR的时候,肯定会产生一次误差,就看误差影响大不大,不大可以忽略.
计数器是24Bit的,0x8000一秒(32768分频),溢出需要511秒.当然愿意的话,你寄存器实现也是没人管你的.只是有API看起来舒服一些.