news 2026/9/6 20:47:52

基于STM32与MLX90614的红外测温报警系统设计与实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于STM32与MLX90614的红外测温报警系统设计与实现

简介:基于STM32的红外测温系统设计文档,面向嵌入式系统学习者、电子竞赛参赛者和相关专业毕业生,提供从课题背景、技术现状到方案论证、软硬件实现的完整设计资料,适用于医疗、工业等非接触测温场景。文档以STM32F103微控制器为处理核心,采用MLX90614红外测温模块实现非接触测温,并辅以DS18B20、LCD1602、按键、复位、电源和报警等模块,详细说明了系统硬件电路、主程序流程、子程序逻辑和系统调试方法。整个资源包仅包含1个docx文档,大小2.09MB,目录结构完整,内含硬件原理图、引脚说明、模块接线图、程序流程框图和部分关键程序,能帮助读者快速理解红外测温原理、STM32外设使用以及软硬件联调流程。目前已有175人学习浏览,尤其适合需要参考完整开发流程或撰写课程设计/毕业论文的读者,是一份内容详实、结构清晰的典型案例。

1. 项目要做什么:红外测温系统的需求与整体设计思路

如果你最近在准备STM32相关的毕业设计或者课程项目,大概率绕不开"测温"这个方向。我最初接这个项目的时候,需求也比较直接:做一个非接触式的红外测温系统,把测到的温度实时显示出来,能设置报警阈值,超温就响蜂鸣器。核心器件就是STM32单片机加一颗红外温度传感器。

为什么选非接触式的红外测温,而不是传统的NTC热敏电阻或者DS18B20这种接触式方案?因为实际使用场景里有很多情况是不方便接触被测物的。比如测高速旋转的电机外壳、测电路板上功率管表面温度、测高温管道外壁,甚至只是单纯想隔着一小段距离测个水温,接触式传感器都很难办。红外测温的好处就是不用碰、不用贴,传感器对准目标就能读温度,响应还特别快。MLX90614这颗传感器的响应时间典型值在几十毫秒级别,比DS18B20那种动辄几百毫秒的转换时间快得多。

这个项目的受众,我个人觉得主要是两类人:一是正在做STM32课程设计/毕业设计的学生,二是想快速上手"单片机+传感器"完整开发流程的嵌入式入门者。项目本身不复杂,但麻雀虽小五脏俱全,从传感器选型、通信协议、数据处理到人机交互,每个环节都覆盖到了。做完这个项目,你对STM32的I2C通信、定时器、中断、低功耗这些常用外设基本都能有个实操层面的认识。

在设计系统架构的时候,我把它拆成几个模块来看:主控模块负责核心控制和数据处理,传感器模块负责采集红外温度,显示模块负责把温度值和人机交互界面呈现出来,报警模块负责超温提醒,电源模块负责给整机供电。这样拆分的好处是每个模块可以独立调试,出问题也容易定位。整机的工作流程就是:上电初始化外设,周期性读取红外传感器的温度数据,经过滤波和校准换算成实际温度值,刷新到OLED屏幕上;同时判断当前温度有没有超过设定的阈值,超了就触发蜂鸣器报警。

2. 硬件选型与设计细节

2.1 为什么选STM32F103C8T6当主控

STM32型号很多,F103系列可以称得上最经典的一个,尤其是C8T6这颗芯片,在学习和毕设里基本属于"万金油"级别。它内部有64KB Flash、20KB SRAM,主频72MHz,足够跑这个项目了。关键是这颗芯片在淘宝上价格便宜,几块钱一片,配套资料极多,网上随便一搜就是一堆例程。

从外设资源上看,F103C8T6有3个USART、2个I2C、2个SPI、多个定时器,还有ADC、DAC,对于测温系统这种规模的应用绰绰有余。就算后续你想加个ESP8266把温度上传到云平台,USART资源也够用。项目里我用到了它的I2C1来通信,基本算是它的基础功能,不存在资源紧张的问题。

2.2 MLX90614红外测温传感器的选型理由与原理

传感器选了MELEXIS的MLX90614,这是目前做非接触测温最常用的一颗数字红外传感器。它内部集成了一个红外热电堆探测器和一颗信号处理芯片,直接把红外辐射信号转换为数字温度值,通过I2C(实际上是SMBus)接口输出,省掉了复杂的模拟信号调理电路。这个"数字输出"的特性非常重要,因为热电堆输出的模拟电压信号极其微弱,如果自己搭放大电路,放大器的零点漂移和噪声就够折腾很久,直接选用带内部处理的传感器模块能大幅降低开发门槛。

我得说说它怎么测温度的。红外测温的理论基础是斯特藩-玻尔兹曼定律,物体辐射的能量和温度的四次方成正比。传感器内部的热电堆检测到红外辐射能量后,根据热端和冷端的温差计算出目标表面的温度。MLX90614出厂前已经做了校准,我们直接读它的RAM寄存器就行。它0x07地址存放的是被测物体的温度,0x01地址存放的是传感器自身的环境温度,数据格式为16位二进制补码,单位是开尔文,精度是0.02℃每比特,换算公式是这个:

实际温度(℃) = 原始数据 × 0.02 − 273.15

这个公式在做数据处理的时候会用到,后面代码部分我会再演示一遍。需要留心的是,MLX90614出厂默认的I2C地址是0x5A(7位地址),通信协议兼容标准I2C,但有些细节和标准I2C不完全一样,比如它要求发送PEC校验字节,不过我们用STM32的硬件I2C或者软件模拟I2C时,基本把PEC忽略也能正常读写,我实测是没问题的。

2.3 显示与报警模块的设计

显示模块我选了0.96寸的OLED屏,驱动芯片是SSD1306,接口是I2C的。之所以不用LCD1602,一是OLED自带字库且对比度高,二是它只需要两根线(SDA、SCL)就能通信,接线超级简单,三是显示内容可以灵活定义,画个曲线、显示个图标都行。对于这个项目,OLED可以显示当前的实时温度、环境温度、报警阈值,还可以画一个简单的温度趋势条,看起来比数码管和1602高级不少。SSD1306的I2C地址一般是0x3C,也有部分是0x3D,买的时候可以让卖家确认一下,或者写个扫描程序扫一遍确定。

报警模块就是蜂鸣器,用三极管9012做开关驱动,STM32的GPIO输出高电平时蜂鸣器响。注意蜂鸣器分有源和无源两种,有源蜂鸣器内部带振荡电路,通电就响,程序里只需要给它高低电平就行;无源蜂鸣器需要PWM信号才能发声。做这个项目买有源的就行,省事。

2.4 电源方案的考量

电源这块值得单独说。MLX90614传感器既支持3.3V也支持5V供电,但如果你要用STM32的ADC去量它的模拟输出型号,那得配上合适的电平。好在我们用的是I2C数字接口,直接统一用3.3V供电就行。整个系统的功耗也不高,STM32F103在72MHz运行时的电流大概几十毫安,传感器大概1.5毫安左右,OLED屏幕点亮时也就十毫安上下。用USB线接入一个5V电源,通过AMS1117-3.3稳压芯片降到3.3V给整个系统供电,完全够用。如果是做便携版本,可以上锂电池加TP4056充电板,续航也足够。

3. 软件设计与核心代码实现

3.1 STM32CubeMX初始化配置

软件部分,我用的是STM32CubeMX生成工程框架,代码逻辑自己在Keil里补充。为什么用CubeMX?因为初始化代码手写太容易出错,特别是时钟树和GPIO复用功能,CubeMX可视化配置完自动生成初始化代码,可以省去很多低级错误。而且它生成的代码是HAL库风格的,可读性好、跨型号移植方便。

时钟配置上,把HSE外部高速时钟设为8MHz晶振,系统时钟通过PLL倍频到72MHz,这是STM32F103的最经典配置。I2C1选择PB6和PB7引脚,分别对应I2C1_SCL和I2C1_SDA。I2C速度配置为100kHz标准模式就行,MLX90614默认的SMBus通信速度上限是100kHz,如果你想跑400kHz快速模式也可以,但建议先按标准模式来,稳定第一。GPIO方面,PC13接蜂鸣器控制引脚,配置为输出模式。定时器方面,我开了一个TIM2做1ms时基,用来做按键扫描和测温周期的调度——这个思路比单纯用delay死等要高效得多,系统还能顺带响应用户操作。

3.2 I2C读取MLX90614温度数据的完整流程

接下来是核心的部分:读温度。MLX90614的I2C读时序和普通I2C设备有一点差异,它采用了"写寄存器地址,然后重启总线,再读数据"的流程。如果你直接调用HAL_I2C_Mem_Read这种标准函数,可能读不出来数据,因为HAL库的Mem_Read时序和MLX90614需要的时序不完全匹配。我自己实测遇到的情况是:用HAL_I2C_Mem_Read读出来的数据一直是0xFFFF或者时不时报错,后来改成手动组合I2C读写函数才稳定。

下面是我实际使用的读取代码,基于HAL库封装了一个独立的读温度函数:

// 从MLX90614指定RAM地址读取16位数据 uint8_t MLX90614_ReadRAM(uint8_t regAddr, uint16_t *data) { uint8_t buf[2]; HAL_StatusTypeDef status; // 发送起始信号 + 设备地址(写) + 寄存器地址 status = HAL_I2C_Master_Transmit(&hi2c1, (MLX90614_ADDR << 1) | 0, &regAddr, 1, 100); if (status != HAL_OK) return 1; // 重启总线,发送设备地址(读),读取2字节数据 status = HAL_I2C_Master_Receive(&hi2c1, (MLX90614_ADDR << 1) | 1, buf, 2, 100); if (status != HAL_OK) return 2; *data = (uint16_t)buf[0] | ((uint16_t)buf[1] << 8); return 0; } // 计算实际温度,单位℃ float MLX90614_GetTemp(uint8_t regAddr) { uint16_t rawData = 0; float temp = 0; if (MLX90614_ReadRAM(regAddr, &rawData) == 0) { temp = (float)rawData * 0.02f - 273.15f; } return temp; }

读出来的rawData是开尔文温度值的16倍放大值,乘以0.02就是开尔文温度,再减去273.15就得到摄氏温度。这个换算关系在MLX90614的数据手册里有明确说明,属于常规操作。需要注意的是,如果寄存器地址传0x07读到的是物体温度,传0x01读到的是环境温度,二者用途不同。我一般会在主循环里先读一次物体温度,算完平均值,再读一次环境温度,用来辅助判断测量是否合理——如果环境温度读出来明显异常,大概率是传感器接触不良或者I2C总线上有问题。

3.3 平均滤波:为什么需要以及怎么实现

直接读出来的温度数据会有轻微波动,尤其是近距离测量时,如果目标温度本身不稳定,读数会跳来跳去。解决办法就是做软件滤波。我用了最简单的滑动平均滤波:维护一个长度为10的数组,每来一个新数据就覆盖最旧的一个,然后取平均值作为本轮的有效温度值。这种滤波方式可以很好地抑制随机噪声,而且实现代码非常简单。

滑动平均的效果我实测过,在传感器对准一个稳定热源的情况下,未滤波时读数波动可能有±0.5℃左右,滤波后能稳定在±0.1℃以内,效果很明显。代码如下:

#define FILTER_SIZE 10 float filterBuf[FILTER_SIZE]; uint8_t filterIndex = 0; uint8_t filterCount = 0; float Temperature_Filter(float newTemp) { float sum = 0; uint8_t i = 0; filterBuf[filterIndex] = newTemp; filterIndex = (filterIndex + 1) % FILTER_SIZE; if (filterCount < FILTER_SIZE) filterCount++; for (i = 0; i < filterCount; i++) { sum += filterBuf[i]; } return sum / filterCount; }

这段代码的思路很直白:数组存满10个温度值后,每来一个新值就把最旧的挤掉,然后求平均。filterCount是为了在数组未填满时也能正常工作,不至于除以0或者除以错误的长度。

3.4 OLED显示与报警逻辑的实现

OLED显示我用的是常用的SSD1306驱动,网上有很多封装好的字库和画点函数。为了节省MCU资源,我选择了I2C接口的OLED,通信速率400kHz,刷新一帧全屏大概需要几十毫秒,对于这个项目来说完全够用。屏幕上除了显示温度数值,我还在底部画了一个简易的进度条,直观显示当前温度在设定阈值下的位置,用一条白色竖线指示实测温度,用户一眼就能看出温度离报警值还有多远。

报警逻辑我用了一个"施密特触发"的思想:当温度升高到设定报警值以上时,蜂鸣器响;当温度降到报警值以下的回差范围(比如3℃)后,蜂鸣器才停止。为什么这么设计?因为如果只在阈值点附近做简单比较,当温度在阈值附近波动时蜂鸣器会反复开启关闭,听起来就是"嗞嗞嗞"乱响,很烦人。加上回差后,报警一旦触发就要降下来几度才会解除,消除了这种临界抖动。代码里就是维护一个报警状态标志,进入报警状态后需要温度低于报警阈值减去回差值才复位。

#define ALARM_THRESHOLD 38.0f #define ALARM_HYSTERESIS 3.0f uint8_t alarmState = 0; void Alarm_Update(float currentTemp) { if (alarmState == 0) { if (currentTemp >= ALARM_THRESHOLD) { alarmState = 1; HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_SET); } } else { if (currentTemp < (ALARM_THRESHOLD - ALARM_HYSTERESIS)) { alarmState = 0; HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_RESET); } } }

这个报警逻辑虽然简单,但在实际使用中非常关键。我在调试阶段因为没有加回差,就遇到过蜂鸣器在阈值附近"疯狂抖动"的问题,后来查了资料才想到施密特触发这个方案,实际用下来体验好了很多。

4. 实操步骤与调试过程全记录

4.1 硬件搭建与接线注意事项

在实际动手之前,我先在面包板上把电路搭了起来。接线关系比较简单:STM32最小系统板(我这里用的是C8T6最小核心板)引出3.3V和GND给MLX90614供电,PB6连SCL,PB7连SDA;OLED同样接3.3V、GND、SCL、SDA,和MLX90614挂同一条I2C总线上。蜂鸣器模块的信号脚接PC13。

接线时有几个新手常踩的坑我得提一下。第一,I2C的SCL和SDA需要上拉电阻,一般模块板上已经自带了4.7kΩ上拉电阻,可以直接共用一个总线上。但如果你的传感器是纯裸芯片而非模块,那就必须自己在总线上加上拉电阻,否则I2C通信完全不通。第二,MLX90614的VCC如果接的是5V,那么I2C电平也是5V的,这时候如果STM32的I2C引脚是容忍5V的倒还好,但为了保险起见一律统一用3.3V供电,省得逻辑电平不匹配出问题。第三,OLED屏幕接I2C时,SCL和SDA别接反了,我见过不少因为这两根线接反导致屏幕一直不亮的案例。

MLX90614模块在淘宝上有些是4针(VCC、GND、SCL、SDA),有些是5针多了一个SMBus地址选择脚。多出的地址选择脚是干嘛的?它可以让你在一条I2C总线上挂多颗MLX90614,通过电平来改地址。如果只用一个传感器,这个脚悬空即可。

4.2 Keil工程配置与下载调试

用CubeMX生成工程后,用Keil打开,编译前务必确认芯片型号和Flash下载算法正确。F103C8T6的Flash是64KB,如果误选了C8T6以外的型号,可能导致下载失败。下载器我用的是ST-Link V2,连接方式就是SWD模式占用的SWDIO、SWCLK、GND、3.3V四个引脚。这个模式下目标板其实不供电也行,但为了保险我还是让板子自己供电,ST-Link只负责烧录。

第一次下载时如果报错"Error: Flash Download failed - Cortex-M3",先检查ST-Link和板子之间的接线。SWD接口只要SWDIO和SWCLK两根线接对就行,不用接复位脚,比JTAG的4根线简单多了。另外,如果你板子上有别的外设把SWDIO或SWCLK占用了,下载就可能失败,这时候需要按住复位键再点下载,等进度条动起来再松手,能绕过这个问题。

4.3 联调过程中的实测数据与心得

整套系统跑起来后,我做了几个实测。用传感器的探头对准一杯温水,水温用玻璃温度计读数做参考。传感器距水面大概3厘米,测温稳定后OLED显示温度和水银温度计差值在0.5℃以内,考虑到玻璃温度计本身也有读数误差,这个精度完全可以接受。我又把传感器对准一块刚从冰箱拿出来的冰袋,读数从室温快速下降到2.3℃,响应速度确实比接触式的传感器快很多。

有一个细节值得注意:MLX90614有一个固定的视场角(FOV)。根据型号不同,FOV可能从35°到90°不等。这意味着传感器测的是视场范围内所有物体红外辐射的平均值。如果视场角内既有高温物体又有低温背景,读数就会偏向两者的加权平均,和你想测的目标温度有偏差。所以实际使用时,传感器要尽量靠近被测目标,让目标物体占满整个视场角,读数才准确。我在测试时就发现,距离很近(5厘米内)时读数稳定且准确,拉远到30厘米以上读数就会有明显下降,因为背景的冷物体参与了红外能量的积分计算。

5. 常见问题与排查技巧

5.1 I2C通信失败的排查思路

这个项目里最常遇到问题的地方就是I2C通信。症状表现是读温度一直为0、读出的数据为0xFFFF、OLED黑屏不亮等。排查思路我建议按这个顺序来:先确认供电——用万用表量一下MLX90614的VCC引脚电压是否正常。再确认接线——SCL/SDA是否和STM32配置的引脚一致,是不是搞混了。然后确认地址——MLX90614默认地址0x5A,但有些模块上如果有地址选择跳线帽,接上后地址会变成0x5B或者别的值,需要仔细看模块说明。最后就是确认上拉电阻——I2C总线必须要有上拉,如果你用杜邦线连接两个模块,而模块板载没有上拉电阻的话,必须自己外接两个4.7kΩ上拉电阻到VCC。我在调试时经历过一次非常奇怪的现象:同一套接线,程序烧进去后第一次读取正常,但等几秒后一直返回0。后来检查发现是杜邦线松了,接触不良导致I2C总线被拉死。所以建议接线后,可以先写一个简单的I2C扫描程序,把总线上所有设备地址扫出来,确认设备都在,再继续下一步开发。

5.2 温度数据异常的常见原因

如果I2C通信正常,但读出来的温度值不对,比如读出来一个稳定的-270.15℃或者很高的异常值,基本上可以判断是换算出了问题。最常见的原因是把开尔文和摄氏度的换算做错,或者把0.02的精度系数写错。MLX90614的数据是开尔文温度放大50倍存储的,也就是每一比特代表0.02K。所以换算公式是:摄氏度 = 原始值 × 0.02 − 273.15。如果你忘了减273.15,读数就会比正常值高273℃左右,这种低级错误我调试的时候犯过一次,后来在代码注释里写清楚这个换算关系才没再犯。

另一个常见问题是传感器镜片脏了。MLX90614模块的感应区域上面有一个光学透镜(或者滤光片),如果它被灰尘、油污遮住了,测量的温度就会严重不准。测试时手不要直接碰镜片,脏了用棉签蘸少量酒精轻轻擦拭。还有,如果被测目标表面是高度反射的亮金属表面,它的发射率很低(比如抛光铝只有0.04~0.1),红外测温很可能就不准,因为传感器默认目标发射率是1。这种场景下可以在目标表面贴一块黑色哑光胶带再测,读数就能恢复正常。

6. 从这个项目里可以延伸的后续方向

做完这个基础版本后,我一直在想怎么让它更有实用价值。思路可以扩展的方向挺多的。首先是增加无线传输功能,用ESP8266模块通过串口连接STM32,把温度数据上传到云平台或者局域网内的服务器,配合手机App就能实现远程温度监控,这个在冷链运输、机房温度监控场景里非常实用。其次是增加数据记录功能,用SD卡模块定时存储温度数据,配合RTC实时时钟记录时间戳,就能形成一条温度历史曲线,导出到PC端用Python做数据分析,可以查看温度变化趋势,这在食品储存和环境监测等领域很有用。目前这个项目做下来,从硬件选型到软件实现再到问题排查,算是一次完整的嵌入式开发实战训练。如果你也在做类似的STM32项目,可以参考我这个整体思路,先画出系统的功能框图和数据流,再动手做硬件和代码,能省去不少返工的麻烦。最后再分享一个我个人的开发习惯:每完成一个模块的功能测试,就提交一次代码版本,加个注释说明当前状态。项目周期不长的还好,如果同时改代码和调硬件,没有版本管理很容易改着改着就不知道哪一版是能用的了。这个习惯帮我省了很多时间,建议你也试试。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/6 20:44:37

Qwerty Learner 常见问题速查:从安装报错到数据异常的完整排障指南

Qwerty Learner 常见问题速查&#xff1a;从安装报错到数据异常的完整排障指南 【免费下载链接】qwerty-learner 为键盘工作者设计的单词记忆与英语肌肉记忆锻炼软件 / Words learning and English muscle memory training software designed for keyboard workers 项目地址:…

作者头像 李华
网站建设 2026/9/6 20:43:24

FLOW3D多孔介质模型与渗流模拟:从参数原理到工程应用解析

简介&#xff1a;这份FLOW-3D多孔介质模型渗流模型PPT&#xff0c;是一份面向CFD工程师、水利与环境研究人员及FLOW-3D初学者的中文技术讲稿&#xff0c;聚焦流体在砂石、毛细孔、管束等多孔介质中的渗流模拟难题。内容从达西定律入手&#xff0c;系统讲解FLOW-3D拖曳力模型的数…

作者头像 李华
网站建设 2026/9/6 20:39:43

零碳智慧园区数字化节能监管管控平台建设方案深度拆解

简介&#xff1a;一套完整的零碳智慧园区数字化节能监管管控平台建设方案&#xff0c;正文共326页、逾12万字&#xff0c;适合园区能源管理负责人、智慧园区方案规划师、系统集成商及节能改造项目技术人员使用。方案内容覆盖建设背景、用能现状&#xff08;用电、用水、用能安全…

作者头像 李华
网站建设 2026/9/6 20:39:30

微课制作全流程:从选题设计到成片包装的获奖实战指南

简介&#xff1a;2022年中国大学生计算机设计大赛微课类中南赛区一等奖的教学文档&#xff0c;围绕破伤风诊疗技能与临床思维训练虚拟仿真教学系统展开。文档共1个PDF文件&#xff0c;大小5.18MB&#xff0c;涵盖教学目标、教学设计、教学素材、教学反思、练习测试与学生反馈等…

作者头像 李华
网站建设 2026/9/6 20:38:16

基于MATLAB/Simulink的输电线路故障仿真建模与分析方法

简介&#xff1a;面向电力系统专业学生与工程技术人员的MATLAB/SIMULINK输电线路故障仿真分析文档&#xff0c;重点讲解短路故障的建模与仿真方法。内容从短路故障类型、MATLAB/SIMULINK基础入手&#xff0c;系统梳理短路计算原理与步骤&#xff0c;并给出三相短路系统仿真模型…

作者头像 李华