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看起来舒服一些.