nRF52实践:RTC和定时器

363 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第23天,点击查看活动详情

本文介绍 nRF52 定时器的使用。

功能介绍

nrf52832 有3个RTC,RTC0用于协议栈,应用层无法使用;RTC1 用作软件定时器,在应用层可以使用以app_timer打头的函数实现定时功能;RTC2 暂未使用。

RTC、定时器源码目录:components\libraries\timer

RTC 相关文件:drv_rtc.c/h

定时器相关文件:app_timer.c/h

软件定时器可注册多个,但底层都使用RTC1,只是按不同的定时间隔调用相应的中断函数。

使用方法

定时器

初始化:

err_code = app_timer_init();

自定义定时器,包括句柄,创建定时任务(指定回调函数)。

定义句柄:
APP_TIMER_DEF(m_app_timer_id);
// 自用的定时器
app_timer_create(&m_app_timer_id, APP_TIMER_MODE_REPEATED, timer_timeout_handler);

启动定时器::

err_code = app_timer_start(m_app_timer_id, APP_TIMER_TICKS(1000), NULL);

第二参数的APP_TIMER_TICKS为宏定义,用于将毫秒数值转换成 tick 数值。上例定时间隔为1000毫秒,即每1秒调用处理函数timer_timeout_handler

回调处理函数:

volatile static uint32_t m_ms_cnt=0;
static void timer_timeout_handler(void * p_context)
{
    m_ms_cnt++;
    printf("timer ms: %d------\r\n", m_ms_cnt);
    // 其它处理
}

停止定时器:

app_timer_stop(m_app_timer_id)

定时器可以随意启动和停止,从而完成不同的需求。比如按下按键时,开启传输数据,再次按下则停止发送,等。

RTC

将在后续文章集中介绍。

延时

和时间有关的函数,还有延时函数,SDK 提供了2函数,如下:

nrf_delay_ms
nrf_delay_us

在一些外设读写操作时,如果对精度不作要求,可以使用上面的函数实现延时。

经测试发现,延时会影响定时器的使用,具体原因待查。

提高定时器准确性

为提高定时器准确性,将定时频率系数宏定义 APP_TIMER_CONFIG_RTC_FREQUENCY 改为 0,即由默认为的 16384 Hz 改为 32768 Hz。产生 1ms 中断时,则中断周期为 1007us,误差为 7us,相对比较近。

// <o> APP_TIMER_CONFIG_RTC_FREQUENCY  - Configure RTC prescaler.
 
// <0=> 32768 Hz 
// <1=> 16384 Hz 
// <3=> 8192 Hz 
// <7=> 4096 Hz 
// <15=> 2048 Hz 
// <31=> 1024 Hz 
​
#ifndef APP_TIMER_CONFIG_RTC_FREQUENCY
#define APP_TIMER_CONFIG_RTC_FREQUENCY 0
#endif

小结

根据官方API说明,APP_TIMER_TICKS最小值为5,小于5则不精确。经测,有时的确不准,但有时却准确。

另外,如果有多个定时器,且定时器间隔时间相近(如A定时10ms,B定时13ms),会产生抖动(即不准确),笔者在测试时,最多启动了3个定时器,由于对时间要求并不十分严格,即使有抖动,也不影响测试。但是在产品时使用的话,还是追求高的精度,因此,下篇文章将介绍使用 RTC2 实现单独的较为准确的毫秒级别接口。

参考:

blog.csdn.net/wulazula/ar…

blog.csdn.net/gdut_liujia…