资讯动态

基于STM32的红外测温系统设计:从原理到实现全解析

发布时间:2026/10/3 11:31:52 来源:尧图企业网站定制
做毕设或者练手项目的时候“基于STM32的红外测温系统设计”是出现频率非常高的一类题目。不少同学一开始会觉得这东西听着挺高端——又是红外传感器又是嵌入式主控好像难度不小。但真拆开来看它其实就是一套“传感器采集数据 单片机处理 显示输出”的标准流程核心工作量集中在器件选型、通信协议理解和数据处理这几个点上。我当年做这个题目的时候花了两个周末从零搭完整个系统中间踩过不少坑这篇就按我实际做的过程把从原理到实现的完整思路捋一遍给准备动手的人一个可以直接参考的路径。1. 项目概述与核心价值1.1 红外测温是什么解决什么实际问题红外测温的原理并不复杂。任何温度高于绝对零度的物体都会向外辐射红外线辐射强度跟物体表面温度直接相关。红外测温传感器利用热电堆或热释电元件接收这部分红外辐射再通过内部算法换算成温度值。和传统热电偶、NTC热敏电阻这类接触式测温相比它的最大优势是非接触——不用碰到被测物体响应速度快还能测运动中的目标。测温门禁、工业高温预警、电力设备巡检用的都是这个原理。在“基于STM32的红外测温系统设计”这个项目里我们选用的核心传感器是MLX90614这颗芯片把红外热电堆探测器、信号调理、ADC、DSP 和 PWM/SMBus 接口集成在一起直接输出经过校准的温度数据。主控端只需要通过 I2C 总线读取寄存器就能拿到物体温度和传感器自身环境温度两个关键值非常省事。1.2 为什么选STM32做主控答案就三个字性价比。STM32 的入门型号 F103 系列主频 72MHz片内资源足够跑 I2C、USART、定时器、ADC 这些外设价格却压到了十几块钱以内。对于一套测温系统来说它不需要跑操作系统也不需要复杂的浮点运算用标准库或者 HAL 库写个状态机就能稳稳跑完整个流程。另外STM32 的生态对新手相当友好。CubeMX 图形化配置外设Keil 或者 STM32CubeIDE 编译下载网上资料一抓一大把。即使你之前只玩过 51 单片机只要熟悉 GPIO 和串口的基本操作花两三天也能把这个项目落地。从毕业设计的角度来说STM32 属于答辩老师一眼就能认可的方案——成熟、稳定、可扩展性也强。2. 系统整体设计与方案选型2.1 系统架构拆解四个模块各司其职一套完整的红外测温系统按功能可以分成四块供电模块负责给主控、传感器和显示屏提供稳定的电压。最常用的是 USB 5V 输入经过 AMS1117-3.3 稳压到 3.3V。传感器模块MLX90614 负责采集目标温度和传感器环境温度通过 I2C 总线把数据传给主控。主控模块STM32 作为大脑负责初始化外设、轮询传感器、处理数据、控制显示和报警。人机交互模块显示当前温度数值必要时加上按键设置报警阈值超温时触发蜂鸣器或 LED 闪烁。整体数据流向是MLX90614 → I2C → STM32 → OLED/串口 → 用户。2.2 核心器件选型MLX90614和它的竞争对手MLX90614 在非接触测温领域几乎是事实标准市面上大量红外测温模块用的都是这颗芯片。它有几种后缀型号区别在于工作电压、测量范围和封装最常见的是MLX90614ESF-BCC测温范围-40℃到85℃物体温度可到300℃精度在±0.5℃的级别满足常规场景需求。和它同类的方案还有MLX90615体积更小适合穿戴设备但引脚封装对自制 PCB 不够友好。GY-906 模块本质就是 MLX90614 加上外围电路和稳压直插杜邦线就能用适合快速验证。国产热电堆传感器比如 Heimann 系列性能不错但上手资料少不适合毕设周期。如果图省事直接买 GY-906 模块是性价比最高的选择某宝十几块钱包邮VCC、GND、SCL、SDA 四根线接上就能跑。但如果想做板子、学硬件设计建议还是买 MLX90614 裸芯片自己画封装、搭外围电路项目含金量会高一个档次。对比项MLX90614 裸芯片GY-906 模块上手难度需自行设计外围电路即插即用硬件学习价值高低成本约10-15元约15-25元适用场景毕业设计、产品样机快速原型验证、入门练习2.3 显示和报警方案怎么选显示部分0.96 寸 OLEDI2C 接口是首选。它体积小、功耗低、显示效果清晰而且和 MLX90614 共用 I2C 总线只需要注意设备地址不同就行OLED 一般是 0x3CMLX90614 是 0x5A。如果嫌 OLED 价格高也可以选 LCD1602但驱动代码里要自己实现 ASCII 字库对新手来说工作量上浮不少。报警模块用一个有源蜂鸣器就够了接一个 GPIO 控制加上 NPN 三极管或 MOS 管驱动避免灌电流过大烧引脚。高端一点的可以加一个RGB LED用 PWM 控制不同颜色指示不同温度区间——这套玩法在答辩时是非常加分的“功能演示亮点”。3. 硬件搭建细节与注意事项3.1 核心连接MLX90614 和 STM32 的 I2C 接线MLX90614 支持 SMBus 协议和 I2C 非常兼容直接接在 STM32 的硬件 I2C 上就能通信。以 STM32F103C8T6 为例I2C1 的 SCL 是 PB6SDA 是 PB7。接线表如下MLX90614STM32VIN3.3VGNDGNDSCLPB6SDAPB7这里有个关键点I2C 总线是开漏输出必须接上拉电阻。用 GY-906 模块的话模块上已经有了上拉直接连就行。如果用裸芯片SCL 和 SDA 各接一个 4.7kΩ 电阻到 3.3V。不接上拉的结果就是通信一开始就卡死读出来的数据全是 0xFF这是新手最容易踩的坑之一。MLX90614 的 SCL 和 SDA 引脚输出电平是 3.3V可以直接和 STM32 相连不需要电平转换。但注意不要用 5V 给传感器供电MLX90614 的最大供电电压是 3.6V超过就烧。我用带稳压的 GY-906 模块时VIN 接了 5V 没事因为板载了 LDO但如果直接用裸芯片必须严格接 3.3V。第三点传感器周围不能有强热源。MLX90614 内部有环境温度传感器做补偿如果它自身被加热比如旁边就是 LDO 或者蜂鸣器读出来的数据会整体偏高而且这种误差很难在软件里消除。我的解决方法是把传感器放在板子边缘远离主控和电源芯片必要时用开窗的屏蔽罩或者导热泡棉隔开。3.2 电源设计和 PCB 布线经验谈整个系统若只驱动 OLED 和传感器电流不到 100mA用 USB 口供电完全足够。但从经验看供电纹波对 I2C 通信和 OLED 显示都有直接影响所以电源部分还是要有基本的滤波设计输入端5V 与 GND 之间加一个 100uF 电解电容和 0.1uF 陶瓷电容抑制 USB 热插拔的浪涌。稳压后AMS1117-3.3 的输出端同样加 100uF 和 0.1uF 电容组合保证 3.3V 稳定。传感器电源MLX90614 的 VDD 和 GND 之间加 0.1uF 去耦电容且电容尽量靠近传感器引脚减少高频噪声对 ADC 的影响。在画 PCB 时I2C 的 SCL 和 SDA 两条线要尽量等长、不要跨越分割的地平面否则高速切换时会产生较大的信号反射。如果只是做实验、用杜邦线连接那要注意线长别超过 20cm否则传感器读数偶尔会乱跳——我在调试时把杜邦线从 20cm 加到 40cm数据就开始异常了剪短线后恢复。3.3 蜂鸣器驱动电路一个容易被忽略的细节蜂鸣器如果直接接 STM32 的 GPIO无论是灌电流还是拉电流都有可能超出引脚的最大输出能力长期运行会烧引脚。比较稳妥的做法是用一个 NPN 三极管比如 S8050做开关管蜂鸣器正极接 3.3V 或 5V。蜂鸣器负极接三极管的集电极。三极管发射极接地。STM32 的 GPIO 通过 1kΩ 电阻接三极管基极。蜂鸣器两端反向并联一个 1N4148 二极管做续流保护防止关断瞬间的感应电动势损坏三极管。这套电路占了不到 1cm^2 的面积但对可靠性的提升非常明显。如果只想快速验证功能也可以买现成的低电平触发蜂鸣器模块但那样硬件学习成分会打折扣。4. 软件设计与核心代码实现4.1 工程初始化用CubeMX配置外设我习惯用 CubeMX 生成初始化代码再在用户代码区自由修改这样既省时间又不至于失去控制。在 CubeMX 里要做以下配置选择芯片STM32F103C8T6。SYSDebug Serial WireSWD避免程序内部禁用 SWD 引脚导致烧录失败。I2C1选择 PB6SCL、PB7SDA频率拉低到 100kHzMLX90614 最高只支持 100kHz这一点我后面实测深有体会——400kHz 的时候读取偶发错误。USART1PA9TX、PA10RX用于调试日志输出到电脑的串口助手强烈建议加上调试效率直接翻倍。GPIO蜂鸣器引脚设为 GPIO_Output按键引脚设为 GPIO_Input 并开启内部上拉。时钟树选择外部 8MHz 晶振倍频到 72MHz 主频。生成工程后在 Keil 里打开选择 ST-Link 或者 J-Link 下载器第一次跑通 LED 闪烁就是最简单的“硬件健康检查”。4.2 MLX90614 读取协议从寄存器到温度值MLX90614 的测量结果存放在 RAM 寄存器里通过 I2C 读取。两个最关键的寄存器RAM 地址 0x07物体温度Tobj16 位有符号数据。RAM 地址 0x06环境温度Tamb16 位有符号数据。实际温度值的换算规则读取到的 16 位数据先去掉低两位数据最低2位恒为0把结果乘以分辨率 0.02℃/LSB再减去绝对零度偏移 273.15就得到摄氏温度。核心读取函数实现如下float MLX90614_ReadTemp(uint8_t reg) { uint8_t buf[3] {0}; HAL_I2C_Master_Transmit(hi2c1, 0x5A 1, reg, 1, 100); HAL_I2C_Master_Receive(hi2c1, 0x5A 1, buf, 3, 100); uint16_t raw (buf[0] | (buf[1] 8)); float temp (raw * 0.02f) - 273.15f; return temp; }读取函数返回后调用两次就能得到物体温度和环境温度float tobj MLX90614_ReadTemp(0x07); float tamb MLX90614_ReadTemp(0x06);这里有个细节要注意MLX90614 的设备地址默认是 0x5A但 I2C 协议传输时地址字段前 7 位才是设备地址最后一位是读写标志位。HAL 库的HAL_I2C_Master_Transmit和HAL_I2C_Master_Receive在传入地址时需要把 8 位地址含 RW 位传进去因此要左移一位写成0x5A 1。我见过很多新手在这里卡死一直写0x5A导致通信失败查半天查不出来。4.3 数据处理简单但有效的滤波策略红外测温传感器在真实环境中的读数并不是完全稳定的尤其是被测目标表面有轻微抖动、或者环境有空气流动时数值会有 ±1℃ 左右的波动。解决办法是在软件层做滤波。我的做法是“限幅滤波 滑动平均”组合限幅滤波设定当前值和上一次读取值的最大偏差阈值比如 0.5℃。如果偏差超过阈值丢弃当前数据连续多次超阈值才更新。这样可以滤掉偶尔的尖峰噪声。滑动平均维护一个 10 个元素的环形缓冲区每次读取新值后丢掉最旧的值求缓冲区平均值。代码实现如下#define FILTER_SIZE 10 float temp_buffer[FILTER_SIZE] {0}; uint8_t temp_index 0; float temp_sum 0.0f; float Temp_Filter(float new_temp) { temp_sum - temp_buffer[temp_index]; temp_buffer[temp_index] new_temp; temp_sum new_temp; temp_index (temp_index 1) % FILTER_SIZE; return temp_sum / FILTER_SIZE; }实测下来加了滑动平均后显示界面上的温度值稳定很多不再一直跳动给用户的直观体验就是“这套系统挺靠谱的”。需要注意的是滑动平均会引入一定的滞后大概滞后一个缓冲区长度的响应时间。如果项目要求快速响应比如运动目标测温可以把缓冲区缩短到 5如果追求稳定性10 个点比较舒服。4.4 显示逻辑与报警阈值设定OLED 显示部分选用 U8g2 库或者 SSD1306 的驱动代码都行。U8g2 库功能全、支持中文但占用 Flash 偏大——对 F103C8T6 的 64KB Flash 来说要留意编译后会占用多少空间SSD1306 驱动代码轻量显示英文和数字足够用了我最后用的就是它。主循环的逻辑非常简单一个 while(1) 里完成三件事while (1) { float tobj MLX90614_ReadTemp(0x07); float tamb MLX90614_ReadTemp(0x06); tobj Temp_Filter(tobj); OLED_ShowFloat(0, 0, tobj, 2); OLED_ShowFloat(0, 2, tamb, 2); if (tobj threshold) { HAL_GPIO_WritePin(BEEP_PIN, GPIO_PIN_SET); } else { HAL_GPIO_WritePin(BEEP_PIN, GPIO_PIN_RESET); } HAL_Delay(200); }报警阈值怎么定取决于应用场景。如果是测人体额头温度建议在 37.3℃ 37.8℃ 之间设阈值如果是测工业设备表面温度阈值可能是 60℃ 甚至更高。阈值可以定义成全局变量通过按键随时调整这样演示的时候也能体现系统的交互性。另外有一点我没少被坑过MLX90614 测的其实是目标表面的红外辐射温度它的读数和物体真实温度之间还隔着一个关键参数——发射率。不同材料的发射率差异很大人体皮肤大约是 0.98黑色哑光表面大约是 0.95抛光金属却可能只有 0.2。MLX90614 官方默认发射率设置是 0.95如果用来测金属表面误差会非常夸张。EEPROM 里可以改写发射率系数但 EEPROM 的写次数有限不能频繁改所以我在代码中增加了一个“发射率修正系数”在显示前做软件修正float corrected_temp MLX90614_ReadTemp(0x07) / emissivity;这个修正精度虽然不如改 EEPROM 彻底但在项目演示和快速应用场景中非常实用实战中我用它把铝合金表面的测量误差从 5℃ 以上压到了 1.5℃ 以内。4.5 串口调试日志开发效率的倍增器我在这个项目里最爽的一个体验就是接上了串口日志。用串口助手每 500ms 打印一行当前温度和状态信息不像 OLED 只能看几个数字串口还能看原始寄存器值、滤波前后的对比、通信失败次数等。这在排查问题的时候几乎就是“透视眼”。printf(Tobj%.2f, Tamb%.2f, Filtered%.2f\r\n, tobj, tamb, filtered_temp);注意使用 printf 前要重定向_write函数或者在工程里勾选 MicroLib否则串口输出是空的。这个小细节能省掉你半个小时抓头发的时间。5. 实测标定与常见问题排查5.1 拿到板子后必做的三项实测硬件焊接完成、代码编译通过之后不要在环境温度还没稳定之前就开始慌慌张张地测数据。我的习惯是按照下面顺序做实测能快速定位“系统是否正常”第一步硬件通电和空载电压测量。上电后用万用表测 3.3V 和 5V 的电压确认没有短路、电压值在允许范围内。这一步能排除八成以上的低级硬件错误。第二步I2C 总线扫描。写一段简单的 I2C 扫描代码SCAN 地址 0x01 到 0x7F看能不能扫描到 0x5AMLX90614和 0x3COLED。如果扫描不到基本就是接线错误、上拉电阻缺失、或者芯片供电异常。这一步不用读温度只看地址排查问题最快。第三步对比实测。用红外测温枪或另一个可靠的温度传感器作为参照与被测目标保持同样的距离和角度对比 MLX90614 的读数。红外测温枪一般比 MLX90614 贵不少如果身边没有就用一杯热水和一个冰块做高低双点测试验证传感器在高低温下的响应是否正常。5.2 数据不稳定怎么办先看测量距离和角度MLX90614 的视场角大约是 35°FOV 90°的型号更宽它测的是视场角内所有物体红外辐射的平均值。如果测量距离太远视场角内的背景温度会稀释目标温度导致读数偏低。我的经验是测量额头温度时传感器距离额头 3~5cm 为佳。测量小目标物体比如一个 2cm 直径的金属螺丝时距离要更近最好在 2cm 以内否则测得大部分是背景辐射。传感器平面要尽量垂直于目标表面倾斜角超过 30° 时读数会有明显偏差。数据乱跳还有一个非常隐蔽的原因被测物体表面反光。如果目标表面是抛光金属或者玻璃它在传感器方向反射了附近更热物体的红外线读数会莫名其妙地飙高。这种情况最有效的解法是改变测量角度避开反射方向或者在被测物表面贴一小块哑光黑胶带红外测温行业常规做法也是这个。5.3 常见问题速查表症状可能原因解决办法I2C 扫描不到设备上拉电阻缺失、接线错误、芯片供电异常检查 SCL/SDA 到 3.3V 的 4.7kΩ 上拉电阻核对引脚用万用表测 VDD 与 GND 的电压读回来全是 0xFFI2C 地址不对、设备未接稳确认是否左移一位0x5A 1检查接触是否可靠读数一直跳动超过 ±1℃干扰、没做滤波、供电纹波大加 0.1uF 去耦电容缩短杜邦线软件加滑动平均读数整体偏高传感器被旁边热源加热让传感器远离 LDO/蜂鸣器或者用隔热材料隔开读数随距离变化剧烈视场角内混入背景辐射缩短测量距离确保目标充满视场角OLED 不显示或乱码I2C 地址冲突、电平不匹配确认 OLED 地址是 0x3C 还是 0x3D检查电源是否 3.3V程序编译通过但下载失败SWD 引脚被禁用、下载器没连接好CubeMX 里开启 Serial Wire检查 ST-Link 连接是否松动5.4 精度标定的心得如果你想把测温系统做成真正能用于实际测量的工具标定是绕不开的环节。最简单的做法是准备几个已知温度的黑体等效物冰水混合物0℃、人体正常体温36.5℃左右、沸水蒸汽接近100℃但要小心烫伤和蒸汽干扰。在相同距离、相同角度、相同环境下采集多组数据拟合出一条修正曲线。我当时用的方法是一个一次线性修正T_real a * T_mlx b通过两组已知点解出 a 和 b写进代码里做最终修正。这样处理后系统在 20℃~40℃ 范围内的误差基本能控制在 ±0.3℃ 以内作为毕业设计的演示效果已经相当出色了。如果你想更进一步可以顺便做一下多点标定并用 Excel 拟合多项式然后把拟合系数硬编码到程序里。这种做法在答辩时属于“有额外工作量、有独立思考”的加分项。5.5 进一步扩展这棵树上还能开哪些花整个系统搭建完成以后后续扩展空间很大这里列几个我亲测或者身边人做过的方向无线化加一块 ESP8266 或 HC-05 蓝牙模块把温度数据通过串口发到手机 App 或云平台演示效果会非常亮眼。ESP8266 模块和 STM32 的 UART 对接只需要 4 根线官网有现成的 AT 指令协议三四个小时就能调通。多传感器组网用 I2C 总线的多地址特性接入 2~3 个 MLX90614做一个多点温度监测面板。MLX90614 的地址可以通过烧写 EEPROM 修改改完后各传感器地址不同主控分时读取即可。指尖血氧或心率监测如果你已经把 I2C 玩熟了把 MAX30102 挂到同一总线上就能做出一个基础的健康监测仪。上位机可视化STM32 通过串口把温度数据发给 PC用 Python 的 pyserial 加 matplotlib 实时画曲线这种“下位机上位机”组合在毕业设计里经常能拿高分。6. 从零到一最终的复现清单如果你计划把这个项目完整做一遍我按个人建议整理了一个最小启动清单STM32F103C8T6 最小系统板一块ST-Link V2 下载器一个GY-906 红外测温模块一个或 MLX90614 裸芯片 上拉电阻0.96 寸 OLED 屏一块有源蜂鸣器一个AMS1117-3.3 稳压模块一个如果用 USB 供电杜邦线若干、面包板一块或者打样 PCBKeil5 STM32CubeMXSTM32 HAL 库或标准库均可我实际复现一遍的耗时大概是CubeMX工程生成 1 小时硬件接线 30 分钟I2C 读取调通 2 小时OLED 显示 2 小时滤波和报警 1 小时整机测试和标定 2 小时。总计不到 10 小时的净工作时间就能把一套功能完整、演示效果不错的红外测温系统跑起来。这套系统做完以后你会发现自己对 I2C 通信、传感器数据处理、嵌入式状态机这几块的理解比看一百页书都深刻。而项目的每一行代码、每一根接线都会变成你下一次做更复杂系统时随手就能调用的“肌肉记忆”。真正动手做一遍永远比收藏夹里躺着的一百份教程更有价值。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑