在Segger Embedded Studio中实现nRF52840双LED精准分时闪烁求助
解决方案:基于nRF52840的非阻塞双LED分时闪烁
核心思路
放弃阻塞式延时,改用nRF SDK中的APP_TIMER模块——这是基于硬件定时器实现的非阻塞定时机制,通过两个独立的周期性定时器分别控制LED翻转,既保证定时精度,又不占用CPU资源。
具体实现步骤(基于nRF SDK v17+)
1. 配置LED引脚
根据你的硬件电路定义LED对应的GPIO引脚(以常见nRF52840开发板为例):
#define LED1_PIN 13 #define LED2_PIN 14
初始化GPIO为输出模式:
static void leds_init(void) { nrf_gpio_cfg_output(LED1_PIN); nrf_gpio_cfg_output(LED2_PIN); // 初始状态熄灭LED nrf_gpio_pin_set(LED1_PIN); nrf_gpio_pin_set(LED2_PIN); }
2. 初始化APP_TIMER模块
在主函数中完成基础初始化:
int main(void) { // 初始化板载时钟(SDK默认已处理,无需手动修改) board_init(); // 初始化LED引脚 leds_init(); // 初始化APP_TIMER,采用1MHz时钟源保证精度 APP_TIMER_INIT(0, 2, NULL, false);
3. 创建定时器与回调函数
定义定时器ID和对应的翻转LED回调:
static app_timer_id_t m_led1_timer_id; static app_timer_id_t m_led2_timer_id; static void led1_timer_handler(void * p_context) { UNUSED_PARAMETER(p_context); // 翻转LED1状态 nrf_gpio_pin_toggle(LED1_PIN); } static void led2_timer_handler(void * p_context) { UNUSED_PARAMETER(p_context); // 翻转LED2状态 nrf_gpio_pin_toggle(LED2_PIN); }
在主函数中创建周期性定时器:
// 创建500ms周期的LED1定时器 APP_TIMER_CREATE(&m_led1_timer_id, APP_TIMER_MODE_REPEATED, led1_timer_handler); // 创建1s周期的LED2定时器 APP_TIMER_CREATE(&m_led2_timer_id, APP_TIMER_MODE_REPEATED, led2_timer_handler);
4. 启动定时器并进入事件循环
启动定时器后,主循环仅处理后台事件,不阻塞:
// 启动定时器,APP_TIMER_TICKS将毫秒转换为时钟 ticks APP_TIMER_START(m_led1_timer_id, APP_TIMER_TICKS(500), NULL); APP_TIMER_START(m_led2_timer_id, APP_TIMER_TICKS(1000), NULL); // 主循环:处理定时器后台事件,可同时添加其他任务 while (true) { app_timer_process(); } }
关键说明
- APP_TIMER_TICKS:自动将毫秒转换为定时器时钟周期,避免手动计算误差,保证定时精准度。
- 非阻塞逻辑:定时器回调在中断上下文执行,主循环仅需调用
app_timer_process()处理事件,CPU可同时处理其他任务。 - 若想直接操作硬件定时器(nRF_TIMER),逻辑类似,但APP_TIMER封装了底层细节,更适合新手快速上手。
学习资源
- nRF SDK内置文档:SDK包内
docs目录,重点查看APP_TIMER模块说明,理解定时器API与工作机制。 - Segger Embedded Studio示例项目:在SES中选择
File > New > nRF Connect SDK Project,搜索app_timer相关示例,直接运行并拆解代码逻辑。 - nRF52840参考手册:重点阅读TIMER和GPIO章节,掌握硬件层面的定时与引脚控制原理。
- nRF SDK教程:SDK包内
tutorials目录,包含基础外设使用的分步指导。
内容的提问来源于stack exchange,提问作者test email
相关产品推荐
相关产品推荐

