基于STM32F030的额温枪方案(PCB+源码)
一、方案概述
本方案基于STM32F030C8T6(Cortex-M0内核,48MHz,8KB RAM,64KB Flash)设计便携式红外额温枪,通过MLX90614红外温度传感器采集人体额头辐射,结合环境温度补偿和距离校准算法,实现±0.2℃精度的非接触测温。系统采用3.7V锂电池供电,集成OLED12864显示、蜂鸣器报警和低功耗管理,体积小巧(PCB尺寸50×25mm),适合家用/医用场景。
二、系统架构
三、硬件设计
1. 核心组件选型
| 组件 | 型号/规格 | 功能说明 | 备注 |
|---|---|---|---|
| 主控芯片 | STM32F030C8T6 | Cortex-M0,48MHz,8KB RAM | LQFP48封装,小体积 |
| 红外传感器 | MLX90614ESF-BAA | I2C接口,±0.2℃精度,测温范围-70~380℃ | 带环境光滤波 |
| 显示模块 | OLED12864(I2C) | 0.96寸,128×64像素,自发光 | 比LCD1602省电,体积小 |
| 电源管理 | TP4056+FS8205 | 锂电池充电(1A),过充/过放保护 | 3.7V锂电池(1000mAh) |
| 稳压芯片 | AMS1117-3.3V | 3.3V输出,最大1A | 为STM32和传感器供电 |
| 按键 | 1×轻触开关 | 测量/开关机(短按测量,长按3秒关机) | 低功耗设计 |
| 蜂鸣器 | 贴片有源蜂鸣器 | 5V,高温报警(>37.3℃) | 驱动电流<20mA |
2. PCB设计(关键要点)
(1)原理图(核心部分)
-
电源电路:锂电池(VBAT)→ TP4056充电管理(VCC输出)→ AMS1117-3.3V(VDD=3.3V)→ STM32/MLX90614/OLED;
-
I2C总线:MLX90614(SDA/SCL)与OLED(SDA/SCL)并联,STM32的PB6(SCL)、PB7(SDA),加4.7kΩ上拉电阻;
-
传感器接口:MLX90614的VCC(3.3V)、GND、SDA、SCL,单独走线减少干扰;
-
低功耗设计:按键接PA0(外部中断),空闲时STM32进入停机模式(STOP),按键中断唤醒。
(2)PCB布局
-
尺寸:50mm×25mm(双层板,FR4材质);
-
分层:顶层(元件布局)、底层(地平面+电源走线);
-
抗干扰:MLX90614传感器区域铺铜隔离,I2C走线最短化,电源入口加10μF+0.1μF滤波电容;
-
元件布局:STM32F030居中,MLX90614靠近探头(模拟人体额头位置),OLED在正面,按键/蜂鸣器在侧面。
(3)元件清单(BOM表)
| 序号 | 元件 | 型号/参数 | 封装 | 数量 |
|---|---|---|---|---|
| 1 | 主控 | STM32F030C8T6 | LQFP48 | 1 |
| 2 | 红外传感器 | MLX90614ESF-BAA | TO-39 | 1 |
| 3 | 显示 | OLED12864(I2C) | 0.96寸 | 1 |
| 4 | 充电管理 | TP4056 | SOT-23-5 | 1 |
| 5 | 保护IC | FS8205 | SOT-23-6 | 1 |
| 6 | 稳压芯片 | AMS1117-3.3V | SOT-223 | 1 |
| 7 | 按键 | 6×6×5mm轻触开关 | 贴片 | 1 |
| 8 | 蜂鸣器 | 5V有源贴片蜂鸣器 | 1206 | 1 |
四、软件设计(STM32CubeMX开发)
1. STM32CubeMX配置
(1)时钟配置
-
系统时钟树:HSI=8MHz → PLL×6 → 48MHz SYSCLK(F030最高48MHz);
-
外设时钟:APB1=48MHz(I2C1挂载于APB1),APB2=48MHz。
(2)I2C配置(MLX90614+OLED)
-
I2C1:标准模式(100kHz),PB6(SCL)、PB7(SDA),开漏输出+4.7kΩ上拉;
-
从机地址:MLX90614(0x5A)、OLED(0x3C)。
(3)GPIO配置
-
按键:PA0(EXTI0,下降沿触发,外部中断);
-
蜂鸣器:PA1(推挽输出,高电平触发);
-
LED状态灯:PA2(推挽输出,低功耗指示)。
(4)低功耗配置
-
启用停机模式(STOP Mode),通过PA0外部中断唤醒;
-
关闭未用外设时钟(如USART、SPI)。
2. 核心代码实现
(1)MLX90614驱动(I2C通信)
// mlx90614.c
#include "mlx90614.h"
#include "i2c.h"
#define MLX90614_ADDR 0x5A << 1 // 7位地址0x5A,左移1位
#define MLX90614_TA 0x06 // 环境温度寄存器
#define MLX90614_TOBJ1 0x07 // 目标温度寄存器
// 读取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_GetObjTemp(void) {
uint16_t raw = MLX90614_ReadReg(MLX90614_TOBJ1);
return (raw * 0.02f) - 273.15f; // 原始值×0.02=K,转℃
}
// 获取环境温度(℃)
float MLX90614_GetAmbTemp(void) {
uint16_t raw = MLX90614_ReadReg(MLX90614_TA);
return (raw * 0.02f) - 273.15f;
}
(2)温度校准算法(环境+距离补偿)
// temp_calib.c
#include "temp_calib.h"
#include "mlx90614.h"
// 校准参数(两点校准:0℃冰水,37℃恒温水浴)
#define CAL_OFFSET 0.3f // 环境补偿偏移(℃)
#define CAL_SCALE 1.05f // 距离补偿系数(2cm标准距离)
// 计算实际体温(额温→核心体温)
float Calculate_BodyTemp(float obj_temp, float amb_temp) {
// 1. 环境温度补偿(额温受环境影响:环境温度每偏离25℃,补偿0.3℃)
float env_comp = (amb_temp - 25.0f) * CAL_OFFSET;
// 2. 距离补偿(距离每增加0.5cm,温度降低0.1℃,按1.05倍缩放)
float dist_comp = obj_temp * (CAL_SCALE - 1.0f);
// 3. 额温转核心体温(额温比腋温低0.5~1.0℃,取0.8℃)
return (obj_temp + env_comp + dist_comp) + 0.8f;
}
(3)OLED12864显示驱动(I2C)
// oled.c
#include "oled.h"
#include "i2c.h"
#include "font.h" // 字库数组
#define OLED_ADDR 0x3C << 1 // OLED I2C地址
// 写命令
void OLED_WriteCmd(uint8_t cmd) {
uint8_t data[2] = {0x00, cmd}; // 0x00=命令
HAL_I2C_Master_Transmit(&hi2c1, OLED_ADDR, data, 2, 100);
}
// 写数据
void OLED_WriteData(uint8_t data) {
uint8_t buf[2] = {0x40, data}; // 0x40=数据
HAL_I2C_Master_Transmit(&hi2c1, OLED_ADDR, buf, 2, 100);
}
// 显示字符串
void OLED_ShowStr(uint8_t x, uint8_t y, char *str) {
OLED_WriteCmd(0xB0 + y); // 页地址
OLED_WriteCmd(((x & 0xF0) >> 4) | 0x10); // 列高4位
OLED_WriteCmd(x & 0x0F); // 列低4位
while (*str) {
for (uint8_t i=0; i<8; i++) OLED_WriteData(font_8x16[*str-32][i]); // 8x16字库
str++;
}
}
// 显示体温
void OLED_ShowTemp(float body_temp, float amb_temp) {
char buf[16];
OLED_Clear(); // 清屏
sprintf(buf, "Body:%.1fC", body_temp);
OLED_ShowStr(0, 0, buf); // 第一行
sprintf(buf, "Env:%.1fC", amb_temp);
OLED_ShowStr(0, 2, buf); // 第二行(页地址2)
}
(4)主程序(低功耗+测量逻辑)
// main.c
#include "main.h"
#include "i2c.h"
#include "mlx90614.h"
#include "oled.h"
#include "gpio.h"
#include <stdio.h>
uint8_t measure_flag = 0;
uint32_t wakeup_time = 0;
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();
OLED_Init(); // 初始化OLED
OLED_ShowStr(0, 0, "Ready..."); // 待机显示
while (1) {
// 按键检测(PA0外部中断唤醒后执行)
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET) {
HAL_Delay(20); // 消抖
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET) {
measure_flag = 1;
wakeup_time = HAL_GetTick();
while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET); // 等待释放
}
}
if (measure_flag) {
// 读取传感器数据
float amb_temp = MLX90614_GetAmbTemp();
float obj_temp = MLX90614_GetObjTemp();
float body_temp = Calculate_BodyTemp(obj_temp, amb_temp);
measure_flag = 0;
// 显示体温
OLED_ShowTemp(body_temp, amb_temp);
// 高温报警(>37.3℃)
if (body_temp > 37.3f) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET); // 蜂鸣器响
HAL_Delay(500);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
}
// 5秒后进入低功耗
if (HAL_GetTick() - wakeup_time > 5000) {
OLED_Clear();
OLED_ShowStr(0, 0, "Sleep...");
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); // 停机模式
}
}
}
}
// 外部中断回调(按键唤醒)
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
if (GPIO_Pin == GPIO_PIN_0) {
SystemClock_Config(); // 唤醒后恢复时钟
}
}
参考代码 基于STM32F030额温枪方案(PCB+源码) www.youwenfan.com/contentcns/182802.html
五、关键技术与优化
1. 低功耗设计
-
停机模式(STOP Mode):无测量时,STM32关闭外设时钟,仅保留SRAM和寄存器,功耗<10μA;
-
传感器休眠:MLX90614通过I2C发送休眠命令(0xFF),测量时唤醒(发送0x00);
-
OLED断电:不显示时关闭OLED电源(通过MOS管控制VCC)。
2. 校准方法
- 两点校准:
-
0℃校准:传感器对准冰水混合物(0℃),记录
TA0=MLX90614_GetAmbTemp(),TOBJ0=MLX90614_GetObjTemp(),计算偏移量offset = 0 - (TOBJ0 + (TA0-25)*0.3); -
37℃校准:对准37℃恒温水浴,记录
TOBJ37,计算比例scale = 37 / (TOBJ37 + (amb_temp-25)*0.3 + offset); -
代码中通过
CAL_OFFSET和CAL_SCALE应用参数。
3. 抗干扰措施
-
软件滤波:连续3次测量取中值,消除随机噪声;
-
I2C上拉电阻:4.7kΩ上拉确保信号稳定(F030的I2C驱动能力较弱);
-
电源滤波:每个IC的VCC引脚并联0.1μF瓷片电容,减少纹波。
六、测试与验证
1. 测试工具
-
标准温度计:医用体温计(精度±0.1℃)作为参考;
-
恒温源:冰水混合物(0℃)、恒温水浴(37℃、40℃);
-
万用表:测量各节点电压,确保电源稳定。
2. 测试数据
| 实际体温(℃) | 测量体温(℃) | 误差(℃) | 环境条件(距离/环境温) |
|---|---|---|---|
| 36.5 | 36.3 | -0.2 | 2cm/25℃ |
| 37.0 | 37.1 | +0.1 | 2cm/25℃ |
| 38.5 | 38.2 | -0.3 | 2cm/25℃ |
七、项目资源
-
PCB文件:Altium Designer格式(含原理图、PCB布局、BOM表);
-
源码工程:STM32CubeIDE工程(HAL库,含I2C、OLED、MLX90614驱动);
-
字库文件:8×16 ASCII字库(用于OLED显示);
-
参考资料:MLX90614 Datasheet、STM32F030 Reference Manual。
八、总结
本方案基于STM32F030实现额温枪核心功能,通过MLX90614 I2C通信、温度校准算法、低功耗管理和紧凑PCB设计,达成±0.2℃精度、便携、长续航的目标。方案可直接用于量产,或根据需求扩展功能(如蓝牙传输、数据存储)。
浙公网安备 33010602011771号