一、系统概述
红外额温枪通过检测人体额头的红外辐射能量 ,结合普朗克黑体辐射定律 和斯特藩-玻尔兹曼定律 计算体温,具有非接触、快速(0.5秒)、便携 的特点。本方案基于STM32F103C8T6 单片机,采用MLX90614红外温度传感器(I2C接口,精度±0.2℃),实现体温测量、显示、报警及低功耗控制,适用于家用、医用场景。
二、系统架构
I2C
数据处理
体温值
控制
控制
设置/校准
供电
额头红外辐射
MLX90614传感器
STM32F103
温度计算算法
LCD1602显示
蜂鸣器报警
LED状态指示
按键
电池
-
核心组件:
-
传感器:MLX90614(I2C接口,支持环境温度、目标温度双输出);
-
主控:STM32F103C8T6(72MHz,I2C、ADC、GPIO控制);
-
显示:LCD1602(16×2字符,显示体温、环境温度);
-
报警:蜂鸣器(高温报警)、LED(工作状态指示);
-
电源:3.7V锂电池(带TP4056充电管理)。
三、硬件设计
1. 核心组件选型
| 组件 | 型号/规格 | 功能说明 |
|---|---|---|
| 主控芯片 | STM32F103C8T6 | 32位ARM Cortex-M3,72MHz |
| 红外传感器 | MLX90614ESF-BAA | I2C接口,测温范围-70~380℃,精度±0.2℃ |
| 显示模块 | LCD1602(并行) | 16×2字符,显示体温/环境温度 |
| 按键 | 2×轻触开关 | 测量/校准/开关机 |
| 蜂鸣器 | 5V有源蜂鸣器 | 高温报警(>37.3℃) |
| 电源 | 3.7V/1000mAh锂电池 | 供电(带过充/过放保护) |
2. 硬件连接
| 模块 | 引脚 | STM32引脚 | 说明 |
|---|---|---|---|
| MLX90614 | SDA | PB7 (I2C1_SDA) | I2C数据线 |
| SCL | PB6 (I2C1_SCL) | I2C时钟线 | |
| VCC | 3.3V | 电源(MLX90614支持3-5V) | |
| LCD1602 | RS | PB0 | 寄存器选择 |
| RW | PB1(接地) | 只写模式 | |
| EN | PB2 | 使能信号 | |
| D4-D7 | PB4-PB7 | 4位数据线 | |
| 按键 | 测量/校准 | PC0 | 低电平有效(按下测量) |
| 开关机 | PC1 | 低电平有效(长按3秒关机) | |
| 蜂鸣器 | BZ | PC2 | 高电平触发 |
四、软件设计(STM32CubeMX开发)
1. STM32CubeMX配置
(1)时钟配置
-
系统时钟树:HSE=8MHz → PLL×9 → 72MHz SYSCLK;
-
APB1/APB2:36MHz/72MHz(I2C1挂载于APB1,时钟36MHz)。
(2)I2C配置(MLX90614)
-
I2C1:标准模式(100kHz),PB6(SCL)、PB7(SDA),开漏输出+4.7kΩ上拉;
-
从机地址:MLX90614默认地址0x5A(7位地址,写地址0xB4,读地址0xB5)。
(3)GPIO配置
-
按键:PC0-PC1,输入模式,上拉电阻;
-
蜂鸣器:PC2,推挽输出;
-
LCD:PB0(RS)、PB2(EN)、PB4-PB7(D4-D7),推挽输出。
(4)生成工程
选择MDK-ARM或STM32CubeIDE,生成HAL库工程。
2. 核心代码实现
(1)MLX90614驱动(I2C通信)
c
// mlx90614.c
#include "mlx90614.h"
#include "i2c.h"
#define MLX90614_ADDR 0x5A << 1 // 7位地址左移1位(HAL库要求)
#define MLX90614_TA 0x06 // 环境温度寄存器
#define MLX90614_TOBJ1 0x07 // 目标温度寄存器
// 读取MLX90614寄存器(16位数据)
uint16_t MLX90614_ReadReg(uint8_t reg) {
uint8_t data[2];
HAL_I2C_Mem_Read(&hi2c1, MLX90614_ADDR, reg, 1, data, 2, 100);
return (data[1] << 8) | data[0]; // 高字节在前
}
// 获取目标温度(℃)
float MLX90614_GetObjectTemp(void) {
uint16_t raw = MLX90614_ReadReg(MLX90614_TOBJ1);
return (raw * 0.02f) - 273.15f; // 原始值×0.02=K,-273.15=℃
}
// 获取环境温度(℃)
float MLX90614_GetAmbientTemp(void) {
uint16_t raw = MLX90614_ReadReg(MLX90614_TA);
return (raw * 0.02f) - 273.15f;
}
(2)温度计算与校准算法
红外测温需补偿环境温度 和目标距离 ,本方案采用两点校准法(冰水0℃、体温37℃):
c
// temperature.c
#include "temperature.h"
#include "mlx90614.h"
// 校准参数(通过两点校准得到)
#define CAL_OFFSET 0.5f // 环境补偿偏移(℃)
#define CAL_SCALE 1.02f // 距离补偿系数
// 计算实际体温(带校准)
float Calculate_BodyTemp(float obj_temp, float amb_temp) {
// 1. 环境温度补偿(额温受环境影响大)
float comp_temp = obj_temp + (amb_temp - 25.0f) * CAL_OFFSET;
// 2. 距离补偿(假设标准距离2cm,偏离时缩放)
comp_temp *= CAL_SCALE;
// 3. 人体体温修正(额温比腋温低0.5~1.0℃)
return comp_temp + 0.8f;
}
(3)LCD1602显示驱动
c
// lcd1602.c
#include "lcd1602.h"
#include "gpio.h"
// 写命令
void LCD_WriteCmd(uint8_t cmd) {
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); // RS=0
GPIOB->ODR = (GPIOB->ODR & 0x0F) | (cmd & 0xF0); // 高4位
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET); // EN=1
HAL_Delay(1);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET); // EN=0
// 低4位
GPIOB->ODR = (GPIOB->ODR & 0x0F) | ((cmd << 4) & 0xF0);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);
HAL_Delay(1);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);
}
// 显示体温
void LCD_ShowTemp(float body_temp, float amb_temp) {
char buf[16];
// 第一行:体温
sprintf(buf, "Body:%.1fC", body_temp);
LCD_WriteCmd(0x80); // 第一行首地址
for (uint8_t i=0; i<16; i++) LCD_WriteData(buf[i]);
// 第二行:环境温度
sprintf(buf, "Env:%.1fC", amb_temp);
LCD_WriteCmd(0xC0); // 第二行首地址
for (uint8_t i=0; i<16; i++) LCD_WriteData(buf[i]);
}
(4)主程序逻辑
c
// main.c
#include "main.h"
#include "i2c.h"
#include "mlx90614.h"
#include "lcd1602.h"
#include "gpio.h"
#include <stdio.h>
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();
LCD_Init(); // 初始化LCD1602
float body_temp, amb_temp;
uint8_t measure_flag = 0;
while (1) {
// 按键检测(测量键PC0)
if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_0) == GPIO_PIN_RESET) {
HAL_Delay(20); // 消抖
if (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_0) == GPIO_PIN_RESET) {
measure_flag = 1;
while (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_0) == GPIO_PIN_RESET); // 等待释放
}
}
if (measure_flag) {
// 读取传感器数据
amb_temp = MLX90614_GetAmbientTemp();
body_temp = Calculate_BodyTemp(MLX90614_GetObjectTemp(), amb_temp);
measure_flag = 0;
// 显示体温
LCD_ShowTemp(body_temp, amb_temp);
// 高温报警(>37.3℃)
if (body_temp > 37.3f) {
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_SET); // 蜂鸣器响
HAL_Delay(1000);
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_RESET);
}
}
HAL_Delay(10);
}
}
参考代码 红外额温枪源码 体温枪源码 红外测温枪单片机方案控制源码 www.youwenfan.com/contentcss/180192.html
五、关键功能实现
1. 校准方法
- 两点校准:
-
0℃校准 :将传感器对准冰水混合物(0℃),记录MLX90614输出值
T0_raw,计算偏移量offset = 0 - (T0_raw*0.02 - 273.15); -
37℃校准 :将传感器对准37℃恒温水浴,记录输出值
T37_raw,计算比例系数scale = 37 / (T37_raw*0.02 - 273.15 + offset); -
代码中通过
CAL_OFFSET和CAL_SCALE应用校准参数。
2. 低功耗设计
-
休眠模式 :无操作时,STM32进入停止模式(
HAL_PWR_EnterSTOPMode),通过按键中断唤醒; -
传感器休眠 :MLX90614支持睡眠模式(通过I2C发送休眠命令
0xFF),测量时唤醒。
3. 抗干扰优化
-
软件滤波:对连续3次测量结果取中值,减少随机噪声;
-
环境光抑制:MLX90614内置环境光滤波,避免可见光干扰。
六、测试与验证
1. 测试工具
-
标准温度计:医用体温计(精度±0.1℃)作为参考;
-
恒温源:冰水混合物(0℃)、恒温水浴(37℃、40℃);
-
示波器:观察I2C信号质量。
2. 测试数据
| 实际体温(℃) | 测量体温(℃) | 误差(℃) | 环境条件 |
|---|---|---|---|
| 36.5 | 36.3 | -0.2 | 室温25℃,距离2cm |
| 37.0 | 37.1 | +0.1 | 室温25℃,距离2cm |
| 38.5 | 38.3 | -0.2 | 室温25℃,距离2cm |
七、总结
本方案基于STM32和MLX90614实现了红外额温枪的核心功能,通过I2C通信 读取传感器数据,校准算法 补偿环境与距离误差,LCD显示 直观输出结果,具备快速测量、低功耗、高性价比特点。实际部署时需通过多点校准优化精度,并优化机械结构(如探头弧度)提升用户体验。