NRF52832填坑日记-------定时器创建

本文介绍如何在nRF SDK17中利用app_timer库实现软件定时器,包括定时器的创建、启动、停止及回调函数的设置。详细解释了app_timer的特性与使用注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本帖子参考https://blog.csdn.net/qq_36347513/article/details/103584388?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-7.add_param_isCf&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-7.add_param_isCf

https://www.cnblogs.com/iini/p/9347460.html

本代码是基于nrfSDK17进行操作的。

/*********************************************************************
 * INCLUDES
 */
#include "app_timer.h"
#include "bsp_timer.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
static void timer_testCallback(void *arg);

/*********************************************************************
 * LOCAL VARIABLES
 */
APP_TIMER_DEF(s_testTimer);    // LED闪烁开的定时器

/*********************************************************************
 * PUBLIC FUNCTIONS
 */
/**
 @brief 创建测试的定时器
 @param 无
 @return 无
*/
void CreateTestTimer(void)
{
    app_timer_create(&s_testTimer, APP_TIMER_MODE_REPEATED, timer_testCallback);
}

/**
 @brief 开启测试的定时器
 @param 无
 @return 无
*/
void StartTestTimer(void)
{
    app_timer_start(s_testTimer, TEST_PERIOD, NULL);
}

/**
 @brief 关闭测试的定时器
 @param 无
 @return 无
*/
void StopTestTimer(void)
{
    app_timer_stop(s_testTimer);
}


/*********************************************************************
 * LOCAL FUNCTIONS
 */
/**
 @brief 测试定时器的回调函数
 @param 无
 @return 无
*/
static void timer_testCallback(void *arg)
{
    UNUSED_PARAMETER(arg);
    // 在这里加入自己的应用处理
    NRF_LOG_INFO("Template TIMER_CP.");
}

定时器的创建函数我们需要在timer_init函数中创建定时器。

static void timers_init(void)
{
    // Initialize timer module.
    ret_code_t err_code = app_timer_init();
    APP_ERROR_CHECK(err_code);

    // Create timers.

    /* YOUR_JOB: Create any timers to be used by the application.
                 Below is an example of how to create a timer.
                 For every new timer needed, increase the value of the macro APP_TIMER_MAX_TIMERS by
                 one.
       ret_code_t err_code;
       err_code = app_timer_create(&m_app_timer_id, APP_TIMER_MODE_REPEATED, timer_timeout_handler);
       APP_ERROR_CHECK(err_code); */
    CreateTestTimer();
}

还需要在application_timers_start函数中开启定时器:

static void application_timers_start(void)
{
    /* YOUR_JOB: Start your timers. below is an example of how to start a timer.
       ret_code_t err_code;
       err_code = app_timer_start(m_app_timer_id, TIMER_INTERVAL, NULL);
       APP_ERROR_CHECK(err_code); */
    StartTestTimer();
}

经过以上的操作我们的定时器就做好了,不过我们需要在main.c文件中将我们创建的bsp_timer.c加进工程中,具体的操作就不一一阐述了,不会的请百度。经过以上的操作我们的定时器就创建成功了,我i们可以通过UART打印来进行判断。

bsp_timer.c文件创建了一个定时器,此定时器用的是软件定时器RTC1

CreateTestTimer()创建一个定时器,

app_timer是大家经常用到的一个库,app_timer的功能就是定时,也就是说,你在某一时刻启动一个app timer并设定超时时间,超时时间一到,app_timer就会回调timeout handler,然后执行你需要的工作。使用app_timer时有如下几点需要注意:

  • app_timer底层使用的是RTC1,而不是timer1/2/3/4,所以app_timer的功耗非常低:0.1uA左右。
  • app_timer计时精度为1ms,也就是说,app_timer只能计时毫秒的倍数,如果你的计时精度小于1ms,请使用传统timer1/2/3/4来做。
  • app_timer计时不是很准确。app_timer库可以创建几十甚至上百个app timer,每次start或者stop这些timer,都会对其他timer计时精度产生一些影响。而且app_timer的中断优先级也不高,所以timeout handler经常会被推迟执行。
  • 启动或者停止app_timer都是异步的,也就是说,当调用app_timer_start或者app_timer_stop时,系统只是把start或者stop操作入队,然后触发一个软中断,如果此时上下文环境的中断优先级高于软中断,那么只有等退出了当前上下文环境后才会真正去执行软中断handler然后启动或者停止timer,这也是为什么app_timer模块需要一个operation queue,并通过APP_TIMER_CONFIG_OP_QUEUE_SIZE来配置其大小;如果此时上下文环境的优先级低于软中断,那么立即触发软中断handler并启动或者停止timer。
  • 创建app_timer。创建app timer时,先定义一个timer ID,用来表示这个timer,然后选择app timer模式:single shot或者repeated。Single shot模式app timer只运行一次,timeout后执行timeout handler然后自动停止app timer。Repeated模式app timer自动循环执行,每次timeout后执行timeout handler,然后继续计时,直到下一个timeout然后再次执行timeout handler,如此循环往复。创建app timer的时候,还需要定义timeout handler。

注意事项:

  1. 没有按照使用说明来使用app_timer,比如定义app timer ID的时候不使用宏APP_TIMER_DEF,超时时间不使用宏APP_TIMER_TICKS来计算。
  2. 多次重复调用同一个app_timer_create。app_timer_create用于创建一个timer,多次调用同一个app_timer_create,会让系统产生多个相同ID的app timer,以致于系统出现不可知的行为。
  3. Stop没有start的timer。当一个timer没有通过app_timer_start启动时,使用app_timer_stop停止它时,或者使用app_timer_stop停止一个不存在的timer时,会打乱app timer的正常行为,产生不可预测的结果。
  4. Operation queue溢出。这个需要具体问题具体分析,有时候operation queue溢出不一定是因为queue size设置太小导致的,而是系统某个地方,确切说某个中断例程,执行时间太久,导致start和stop操作积累太多,从而产生queue溢出,这个时候就必须找出这个中断例程执行时间太久的原因,才能从根本上解决这个问题。

以上的几点建议为一个大佬的总结希望对大家有帮助,本帖子仅为自己备忘使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值