前言
在智能家居与安防领域,电池供电的无线红外探测器(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
|