持续创作,加速成长!这是我参与「掘金日新计划 · 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 实现单独的较为准确的毫秒级别接口。
参考: