[产品应用] CW32L010 实战:打造 6uA 超低功耗 433MHz 无线红外探测器

[复制链接]
43|2
Puchou 发表于 2026-11-4 12:02 | 显示全部楼层 |阅读模式
前言
在智能家居与安防领域,电池供电的无线红外探测器(PIR)对功耗和抗误报能力有着极其苛刻的要求。近年来,国产 32 位微控制器(MCU)飞速发展,武汉芯源的 CW32L010(基于 Cortex-M0+ 内核)凭借极高的性价比和优秀的低功耗特性,成为这类电池供电设备的理想选择。

本文将完整分享基于 CW32L010 设计的一款 433MHz 无线双元红外探测器的软硬件架构,重点剖析双元 PIR 的检测算法、433 无线编码模拟,以及如何通过软硬件协同将待机功耗硬核压缩至 6μA 以内。

一、 核心原理:双元 PIR 人体检测
很多初学者认为 PIR 传感器是直接输出人体信号的,其实不然。它本质上是一个热释电红外传感器。

人体会发出特定波长(约 10μm)的红外线。

通过外部的菲涅尔透镜,将红外线聚焦在探头内部的两个(或四个)感应元上。

当人体移动时,红外线交替穿过透镜,导致两个感应元产生差分电压脉冲(一正一负)。

经过外部处理芯片(如 BISS0001 或 MD7039)放大并转换为数字电平输出。

为什么要做方向与多脉冲判断?
如果单纯判断“引脚变高就报警”,稍微有点热气流、强光干扰,探测器就会疯狂误报。
为了达到工业级抗误报标准,我们在软件中设计了多脉冲状态机:

方向识别:判断是 PIR1 先触发,还是 PIR2 先触发,以确定人体的移动方向。

脉宽检测:要求第一个脉冲必须持续 50ms 以上,过滤掉瞬间的高频电磁干扰。

间隔与反向脉冲:第一路触发后,必须等待两路都恢复低电平 10ms,然后在 5秒 内第二路出现有效脉冲。

抖动过滤:最后再用 250ms 确认信号稳定,才最终判定为一次人体移动。

二、 系统功能与硬件架构
本产品基于 CW32L010F8P6(TSSOP20封装)设计,具备完整的安防防护功能:

双元人体检测:1P(单脉冲高灵敏)/ 2P(双脉冲抗误报)模式可切换。

防拆报警:外壳被打开时,立即上报防拆码(0x07)。

低电检测:电池电压低于阈值时,上报低电码(0x0A)且 LED 慢闪提示。

对码/学习:支持按键对码(上报 0x03)。

自适应预热:上电后屏蔽报警 60 秒,让 PIR 探头稳定,期间 LED 每 2 秒闪烁指示。

引脚分配(避开烧录口与晶振口)
为了不占用 SWD 烧录口,引脚分配如下:

PA00、PA01:双元 PIR 信号输入(浮空)。

PA02:防拆输入(外部 1M 上拉至 3V,开关接地)。

PA03:灵敏度拨码(接地为 2P,悬空为 1P)。

PA04:电池低电检测(配置为模拟输入,外部电阻分压)。

PA06:工作模式拨码(接地区分省电/普通/测试模式)。

PB00:对码按键(外部 1M 上拉,按键接地)。

PB02:LED 指示灯。

PB03:433 射频发送模块。

三、 软件架构:非阻塞 10ms 状态机
如果把 delay() 写在主循环里,按键和 PIR 检测就会卡顿。本系统采用 LPTIM(低功耗定时器)提供 10ms 基础节拍,所有业务逻辑 均采用非阻塞状态机实现。




// 主循环框架
while (1)
{
    if (gLPTIMWakeUpIrq == 1) // 10ms 到
    {
        gLPTIMWakeUpIrq = 0;

        // 5 * 10ms = 50ms 进一次慢任务(防拆、低电、对码)
        if (++g_tick_5ms_count >= 5) {
            g_tick_5ms_count = 0;
            SlowTask_25ms();

            // 20 * 50ms = 1s 进一次秒级任务(报警封锁倒计时)
            if (++g_tick_1s_count >= 20) {
                g_tick_1s_count = 0;
                Check_Mask_Timeout();
            }
        }
        PIRTEST(); // 10ms 检测一次红外状态机
    }

    // 433 发送由事件触发
    Handle_Send_Events();

    // 进入深度睡眠,等待 LPTIM 唤醒
    SYSCTRL_GotoDeepSleep();
}
PIR 状态机核心代码(时间已按 10ms 节拍缩放)


static void PIR_StateMachine_Normal(void)
{
    switch (g_r_pir)
    {
    case 0: g_pir_time = 0; g_r_pir1 = 5; g_r_pir = 1; break; // 等待脉冲
    case 1:
        if (PIR2_IS_HIGH()) {
            g_r_pir1--;
            if (g_r_pir1 == 0) { // 5 * 10ms = 50ms 确认高电平
                if (!(g_mask_state & MASK_ANALYS_1P)) goto RESET1; // 1P模式直接报警
                g_r_pir = 2;
            }
        } else goto RESET2;
        break;
    case 2:
        if (PIR2_IS_HIGH()) {
            if (g_pir_time >= 200) goto RESET2; // 高电平超过 2s 视为异常
        } else {
            g_r_pir = 3; g_r_pir1 = 1; // 要求低电平间隔至少 10ms
        }
        break;
    // ... 后面继续等待反向脉冲及 250ms 抖动过滤
    }
}
四、 433MHz 无线编码:SysTick 精准延时
软件模拟 433MHz OOK 编码对时间精度的要求极高(微秒级)。如果用普通的 while() 循环,极易受编译器优化的影响导致波形变形,接收端无法解码。

最佳方案:使用 ARM  内核自带的 SysTick 硬件定时器进行精准延时。




__STATIC_INLINE void Delay_Us(uint32_t us)
{
    uint32_t target_ticks = us << 2; // 主频4MHz,1us=4个tick
    uint32_t told = SysTick->VAL;
    uint32_t tnow = told;
    uint32_t tcnt = 0;

    while (1) {
        tnow = SysTick->VAL;
        if (tnow != told) {
            if (tnow < told) tcnt += told - tnow;
            else             tcnt += (SysTick->LOAD - tnow) + told;
            told = tnow;
            if (tcnt >= target_ticks) break;
        }
    }
}
在发送同步码时(SEND_HIGH(); Delay_Us(200); SEND_LOW(); Delay_Us(6400);),能够保证极低误差,确保接收主机稳定配对。

五、 极致低功耗实战:如何把电流干到 6μA?
这是本文最核心的部分。很多开发者发现单片机进了 DeepSleep 还是耗电上百微安,究其原因,90% 是引脚漏电。

1. 血泪踩坑:内部上拉 VS  外部接地
我们在调试初期,将防拆引脚配置为 GPIO_MODE_INPUT_PULLUP(内部上拉),结果测得整板电流高达 250μA!
原因:防拆开关在平时是闭合接地的。内部上拉电阻(约 60kΩ)与外部地线形成短路,3V / 60kΩ = 50μA,多个引脚加起来直接让电池报废。

黄金法则:外部有强拉,内部必浮空。

传感器(PIR)、拨码开关、对码按键、防拆:软件全部配置为 GPIO_MODE_INPUT(浮空输入)。硬件上,开关类引脚必须外部加 1MΩ 上拉电阻,这样即便开关短接,漏电流也只有 3V / 1MΩ = 3μA。

电池检测(ADC 采样):配置为 GPIO_MODE_ANALOG(模拟输入),彻底切断数字电路漏电。

2. 悬空引脚的“天线效应”
单片机上没用到的引脚,千万别在代码里不管它!悬空的 CMOS 引脚像天线一样,感应到外界微弱电场就会在 0 和 1 之间反复翻转,导致内部晶体管频繁“穿通”漏电。
处理方案:将未使用的引脚全部配置为 GPIO_MODE_ANALOG。




// 低功耗 GPIO 配置精髓
static void GPIO_Configuration(void)
{
    GPIO_InitTypeDef st = {0};

    // 输出脚
    st.Mode = GPIO_MODE_OUTPUT_PP;
    st.Pins = LED_PIN | SEND_PIN;
    GPIO_Init(CW_GPIOB, &st);
    LED_LOW(); SEND_LOW();

    // 输入脚 (由于外部全都有上拉/下拉,MCU内部全开浮空)
    st.Mode = GPIO_MODE_INPUT;
    st.Pins = PIR1_PIN | PIR2_PIN | TAMPER_PIN | MODE_PIN | ANALYS_PIN | ENROLL_PIN;
    GPIO_Init(CW_GPIOA, &st);
    GPIO_Init(CW_GPIOB, &st);

    // 低电检测必须用模拟输入
    st.Mode = GPIO_MODE_ANALOG;
    st.Pins = BAT_PIN;            
    GPIO_Init(BAT_PORT, &st);

    // 悬空脚处理
    st.Mode = GPIO_MODE_ANALOG;
    st.Pins = GPIO_PIN_12 | GPIO_PIN_13; // 把没用的脚设为模拟
    GPIO_Init(CW_GPIOA, &st);
}
3. 降低唤醒频率
最初代码采用 5ms 唤醒一次 LPTIM,整机功耗在 10μA 左右。
考虑到人体移动的 PIR 信号是几百毫秒级的慢速信号,10ms 的采样率完全足够。我们将 LPTIM_Period 调整为 164 - 1(10ms 周期),唤醒频率减半,功耗直接降到了 6μA。

六、 总结
通过 CW32L010 的非阻塞状态机架构、SysTick 精准波形模拟、以及严苛的 GPIO 防漏电配置,这款无线红外探测器成功实现了 6μA 的超低待机电流(不含 433 发射瞬间)。按两节 5 号电池 2000mAh 计算,理论待机寿命可达 10 年以上(实际受电池自放电和 PIR 模块静态电流影响,通常在 2-3 年)。

对于电池供电的物联网设备,低功耗设计绝不是写一句 __WFI() 那么简单,它是一场硬件电路与软件底层的完美协同战。希望本文的踩坑经验能为各位道友在国产 MCU 的低功耗开发路上提供帮助!


————————————————
版权声明:本文为CSDN博主「殷忆枫」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_38807927/article/details/169431564

stormwind123 发表于 2026-11-4 12:16 | 显示全部楼层
内部上拉配外部接地开关那个坑,很多做低功耗的人都踩过。60kΩ 内部上拉和地短接,单个引脚就是 50μA,几个引脚加起来电池撑不住。文章里“外部有强拉、内部必浮空”这条规则值得记下来。
海滨消消 发表于 2026-11-4 12:20 | 显示全部楼层
上电预热 60 秒屏蔽报警,期间 LED 每 2 秒闪一次,这个设计考虑了 PIR 探头稳定时间。热释电传感器上电后需要时间稳定,不屏蔽的话头一分钟可能反复误报,用户体验会很差。
七毛钱 发表于 2026-11-4 13:10 | 显示全部楼层
未使用引脚配成模拟输入这个做法是对的。悬空 CMOS 引脚会当小天线用,电平来回翻转导致内部晶体管穿通漏电。把没用的脚全设成 GPIO_MODE_ANALOG,是低功耗设计里常被忽略的一步。
今天会画卧蚕吗 发表于 2026-11-4 13:49 | 显示全部楼层
LPTIM 唤醒周期从 5ms 改成 10ms,功耗从 10μA 降到 6μA,说明唤醒频率对平均功耗影响很大。PIR 信号本身就是几百毫秒级的慢信号,10ms 采样率完全够用,没必要为了“更灵敏”去牺牲功耗。
内政奇才 发表于 2026-11-4 14:19 | 显示全部楼层
电池检测引脚配成 GPIO_MODE_ANALOG 而不是普通输入,这一点很关键。ADC 采样脚如果留在数字输入模式,分压电阻上会一直有漏电流,改成模拟模式彻底切断数字电路那条漏电路径。
又见江南雨 发表于 2026-11-4 19:25 | 显示全部楼层
文章里 433 编码用 SysTick 做微秒级延时,不用 while 循环,这个选择合理。编译器优化等级一变,while 循环的延时就不准了,OOK 波形变形接收端就解不出来。SysTick 是硬件计数器,延时精度不受编译优化影响。
在海边聆听 发表于 2026-11-4 20:18 | 显示全部楼层
双元 PIR 的方向识别加多脉冲判断,比单脉冲直接报警靠谱得多。热气流、强光这些干扰很难同时满足“第一路 50ms 以上、间隔 10ms、5 秒内第二路有效、再等 250ms 稳定”这一串条件,误报率会明显下降。
才没有脸红 发表于 2026-11-4 21:26 | 显示全部楼层
理论待机 10 年、实际 2 到 3 年,这个差距主要来自电池自放电和 PIR 模块本身的静态电流。6μA 是 MCU 加外围电路的数,PIR 探头和 433 模块的静态功耗也要算进去,整机功耗才是决定电池寿命的数。
故里说长安 发表于 2026-11-4 21:58 | 显示全部楼层
非阻塞状态机加 LPTIM 节拍的架构,比在主循环里塞 delay 强。按键、PIR、低电检测、对码这些任务都在 10ms 节拍里按状态推进,任何一个任务都不会把别的任务卡住,响应也及时。
没有太阳的晴天 发表于 2026-11-4 22:20 | 显示全部楼层
防拆、拨码、对码按键全部用外部 1MΩ 上拉,软件配浮空输入,这个硬件设计思路是主动把漏电流压到 3μA 级别。1MΩ 上拉在开关闭合时漏电只有 3μA,比内部上拉的 50μA 小一个数量级。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

284

主题

709

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部