STM32 实战:用 AS312 人体红外传感器实现「有人/无人」检测
STM32 实战:用 AS312 人体红外传感器实现「有人/无人」检测
物联网传感器技术课程实验手记 · 人体红外(热释电 PIR)传感器篇
最近在嵌入式实验箱上做了一个人体红外检测实验:用一颗指甲盖大小的 AS312 热释电传感器,让 STM32 判断"屋里有没有人",把结果实时显示在 LCD 上,同时通过串口打印出来。
一、实验要做什么
一句话:检测人体活动,并实时显示"有人 / 无人"。
硬件上就四样东西:
| 器件 | 型号/规格 | 作用 |
|---|---|---|
| 主控板 | STM32L431VCTx(IoTV2_MainBoard) | 系统核心,读取传感器状态 |
| 人体红外传感器 | AS312(热释电红外模块) | 检测人体活动,输出数字电平 |
| 显示屏 | 240×320 TFT-LCD | 显示"有人/无人"状态 |
| 上位机 | PC 串口调试助手(115200) | 查看程序运行日志 |
软件上基于 STM32 HAL 库开发,整个系统的数据流是:
AS312 检测人体 → PC8 引脚读电平 → 主控判断 → LCD 显示 + 串口打印 + LED 指示
二、主角:AS312 热释电人体红外传感器
AS312 是一颗数字智能型热释电(PIR)探测器,和传统的模拟 PIR 方案不同,它把信号调理、滤波、DSP 处理、施密特触发输出全部集成进了探测器外壳,外围几乎不需要任何电路,直接输出稳定的 TTL 电平,非常省事。
它的核心原理是利用热释电效应:人体体温约 37 ℃,会不断向外辐射红外线。当人进入传感器视场并发生移动时,照射到热释电探测元上的红外辐射量发生变化,引起探测元表面温度变化,进而在晶体两端产生微弱的电荷信号。这个信号经过内部电路处理后,就变成了"有人"的判断依据。
关键点在于,它只能检测"运动的人体"——因为热释电效应依赖红外辐射的变化,人完全静止不动时,输出会慢慢回到无人状态。这也是后面踩坑的重点。
几个值得记的参数(来自 AS312 规格书):
| 参数 | 数值 | 备注 |
|---|---|---|
| 工作电压 | 2.7 ~ 3.3 V(典型 3 V) | 低功耗设计 |
| 工作电流 | 12 ~ 20 μA | 微安级,适合电池供电 |
| 输出 | 施密特触发数字电平 | 无需外围放大电路 |
| 导通时间 / 锁定时间 | 约 2.3 s | 检测到人体后保持高电平约 2.3 s |
| 内部滤波 | 带通 0.44 Hz ~ 7 Hz | 滤除环境与干扰成分 |
三、硬件接线:三根线搞定
AS312 模块采用三线制引出:VCC 接 3.3 V 电源正极,GND 接地,OUT 是数字信号输出线。本实验中 OUT 接到主控板的 PC8 引脚,PC8 在初始化时配置为下拉输入:无人时 OUT 输出低电平(逻辑 0),检测到人体活动时 OUT 输出高电平(逻辑 1)。
传感器内部的处理链路是这样的:
菲涅尔透镜 + 双元热释电探测 → 信号调理(带通滤波)→ 内置 DSP 处理(温度补偿 / 抗干扰)→ 施密特触发器输出
图 2 AS312 接线与输出原理示意
菲涅尔透镜的作用是把视场分成明暗交替的区域,人体移动时会让红外辐射在探测元上产生"变化",这正是热释电探测器需要的信号;双元探测则用来抑制环境温度缓慢变化引起的共模干扰。这些细节做产品时很关键,实验阶段能理解到"检测变化、抑制静止"这个层面就够用了。
四、软件实现:HAL 库三步走
工程基于 STM32L4 系列 HAL 库,主要源文件有 main.c(主函数与时钟)、as312.c/.h(传感器驱动)、handle.c/.h(用户处理逻辑)、lcd.c/gui.c(显示驱动)、gpio.c/usart.c(底层外设)。
1. 主函数 main.c:初始化 + 死循环
int main(void)
{
HAL_Init();
SystemClock_Config(); // HSI 16MHz 经 PLL 倍频作系统时钟
LCD_Display_Init(); // 屏幕初始化,显示实验标题
gpio_module_open(LEDS); // 打开 LED 指示灯模块
uart_open(uart2, 115200); // 串口初始化
printf("\r\n 人体红外检测实验 \r\n");
printf("开始本实验:\r\n\r\n");
AS312_Init(); // 初始化人体红外检测引脚
while(1)
{
Body_Handle(); // 检测人体状态并显示
}
}
2. 传感器驱动 as312.c:PC8 下拉输入
void AS312_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_GPIOC_CLK_ENABLE(); // 使能 GPIOC 时钟
GPIO_InitStruct.Pin = GPIO_PIN_8; // PC8 引脚
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; // 输入模式
GPIO_InitStruct.Pull = GPIO_PULLDOWN; // 下拉
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}
uint8_t Infrared_Read_State(void)
{
return AS312_STATE(); // 返回 0:无人运动;返回 1:有人运动
}
3. 检测逻辑 Body_Handle():每秒轮询一次
void Body_Handle(void)
{
uint8_t as312_state = 0;
static uint32_t tickstart;
if((HAL_GetTick() - tickstart) >= 1000) // 1000ms 检测一次
{
tickstart = HAL_GetTick();
as312_state = Infrared_Read_State();
if(as312_state == 1)
{
LCD_draw_bmp(96,120,48,gImage_Body); // 有人图标
Show_Str(96,178,BLUE,WHITE,"有人",16,1); // 显示"有人"
}
else if(as312_state == 0)
{
LCD_draw_bmp(96,120,48,gImage_Body_hui); // 无人图标
Show_Str(96,178,BLUE,WHITE,"无人",16,1); // 显示"无人"
}
if(as312_state != as312_state_rev) // 状态变化才打印
{
printf("** 读取人体红外传感数据\r\n");
printf("** 人体红外传感数据:%s\r\n\r\n",
as312_state == 1 ? "有人" : "无人");
as312_state_rev = as312_state;
}
led_toggle(LED1_PORT); // LED 每秒翻转,运行指示
}
}
几个设计细节值得学习:
- 定时轮询:用
HAL_GetTick()做 1000 ms 定时,而不是粗暴的延时阻塞,主循环还能干别的事; - 状态变化才打印:用
as312_state_rev记录上一次状态,只有状态翻转时才输出日志,避免串口被刷屏; - LED 每秒翻转:作为"系统还活着"的运行指示,排查问题非常有用。
五、实验现象
上电后 LCD 先显示"人体红外检测实验"标题界面;手靠近传感器时,LCD 显示"有人"并出现彩色人体图标,串口打印 ** 人体红外传感数据:有人;手移开后,LCD 显示"无人"并切换为灰色图标,串口打印 ** 人体红外传感数据:无人。LED1 每秒翻转一次,指示系统正常运行。


实验结果:LCD 显示"有人"与串口输出日志*
实验结果与预期完全一致。
六、踩坑与心得
实验顺利,但原理层面的坑还是值得记一笔:
- 轮询周期限制实时性:程序每 1 s 才采样一次,人快速走过时有可能漏检或延迟显示。更优的做法是改成外部中断 + 软件消抖,传感器电平一变化立刻响应。
- 2.3 s 的固有延时:AS312 检测到人体后导通时间约 2.3 s,这是传感器本身的特性,无法通过软件调整,做门禁、计数类应用时要预留这个时间。
- 静止人体检测不到:热释电传感器只对"运动"敏感,人坐着不动几分钟后输出就会恢复低电平。要检测"是否有人在"(而非"是否在动"),需要配合毫米波雷达或者摄像头方案。
- 环境温度影响:夏天环境温度接近人体温度时,红外辐射对比度下降,检测距离会变短,这是热释电方案的天然短板。
七、还能怎么玩
实验做完了,思路可以继续延伸:
- 人体计数:统计"有人→无人"的状态变化沿,配合消抖做成客流计数器;
- 智能照明:结合光敏传感器实现"人来灯亮、人走灯灭";
- 联网上报:利用主控板上的 NB-IoT 模块(BC35G)把状态上传云端,远程看家里有没有人;
- 多传感器融合:人体红外 + 光电开关 + 温湿度组成环境感知系统;
- 鸿蒙生态联动:配合 HarmonyOS 分布式能力,让手机 App 实时查看检测结果。
小结
一个"有没有人"的检测,背后是热释电效应的物理原理、传感器内部信号处理的精巧设计,以及嵌入式里轮询、显示、串口、GPIO 的综合编程。
更多推荐


所有评论(0)