news 2026/9/2 16:22:22

MLX90614红外测温传感器从入门到落地:接线、I2C与校准全攻略

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MLX90614红外测温传感器从入门到落地:接线、I2C与校准全攻略

简介:这套基于STM32的红外无接触测温工程代码,面向嵌入式开发者及温度监测场景,已实测通过。工程通过I2C接口与mlx90614传感器通信,时钟线连接PB6、数据线连接PB7,读取到的温度数据经串口1输出,方便用户直接观察或对接上位机。方案适用于体温快速筛查、工业非接触测温、智能家居环境监测等常见场合,兼顾安全性与便利性。压缩包共110个文件,以C源码(.c)和头文件(.h)为主要代码主体,同时包含Keil工程配置、链接脚本及编译生成的中间文件,打开工程即可重新编译和烧录;包体约992KB,文件归类清晰。已有1076人学习下载,说明该资源在同类项目中具备较高热度与参考价值。使用本工程可快速掌握mlx90614的驱动控制、STM32外设初始化、I2C时序实现以及串口发送流程,可直接移植到自身项目,也可作为学习红外测温传感器开发的入门样例。 很多人手里应该都存过几份这样的压缩包:从论坛、工具群或者前辈那儿拷来的,名字写着"xxx代码-可用""xxx测试通过",解压之后却只有不多几个文件。我前段时间整理移动硬盘,正好翻到一个名为"mlx90614红外无接触测温(测试通过).rar"的老包,点开一看,里面就三样东西:一个 Arduino 工程、数据手册的寄存器截图、还有一个写着"PEC 校验可以不用"的说明文档。这个包勾起了我不少回忆——那时候我刚做测温项目,就是靠类似这么一套东西起步的,代码确实能跑,串口也能打印温度,但离真正能交付、能稳定用的测温设备,还差着十万八千里。

这篇就借这个"测试通过"的标题,把 MLX90614 从接线、读寄存器、写代码,到校准和落地的完整链路捋一遍,也把我踩过的一些坑放到台面上讲讲。

1. 为什么"能打印温度"不等于"项目能用":先想清楚场景再动手

文件的标题说"测试通过",实际指的是串口能稳定输出温度值,仅此而已。很多人拿到这种包就开始往产品上套,结果往往会在测量场景上栽跟头。MLX90614 是 Melexis 推出的一颗红外热电堆温度传感器,它的核心原理是被动接收物体表面发出的红外辐射,再通过内部数字信号处理输出温度。因为不需要接触被测物体,它天然适合三类场景:运动中的物体、不允许交叉污染的位置、以及人够不到的高温区域。比如传送带上的电子元器件表面测温、配电柜里开关触点的发热状态检测、食品包装表面的快速温度筛查,这些都是它很擅长的事。

但如果你打算直接拿它测人体额温或者做医疗级体温计,那就要特别小心。人体额头温度也就是 36~37°C 这个区间,环境温度变化 10°C,传感器自身的热漂移、外壳热传导、周围热源的红外辐射,都会让显示数值偏出可接受范围。我当初在 D6T、AMG8833 和它之间犹豫过一阵,最终仍然选了 MLX90614,不是因为它最准,而是因为在单点非接触测温这个细分场景里,它性价比最好、资料最全、封装兼容性也最好。

1.1 那个压缩包里缺的最关键一份文档

解压之后没有 README,没有原理图,只有三样东西:一个能跑通的 Arduino 例程、一页 RAM 寄存器截图、一句"PEC 校验可以不用"的说明。这三样东西刚好对应把它跑起来的最小知识集合,但也正好是三处容易让后来人踩坑的源头。

Arduino 例程用 Wire 库写,几乎上电就能出数,于是很多人误以为随便怎么接都行,忽略了上拉电阻和电平匹配;寄存器截图告诉你要读 0x07 这个地址,但没告诉你 SMBus 时序和普通 I2C 的细微差别;那句"PEC 可以不用"虽然省了事,却也意味着在电磁环境复杂的场合,偶尔会读到明显跳变的坏值。

如果这个包里能再加一份"测温距离和视场角影响"的笔记,价值会高得多。MLX90614 的标配传感器的视场角大约 90°,这意味着被测目标必须完整填满传感器的视场,读数才代表目标本身的温度,否则读到的就是目标与背景的加权平均值。后来我遇到的大量"测不准"案例,十有八九根源都出在这。

1.2 什么场景适合它,什么场景真别硬用

我给你划一条简单的判断线。适合用的场景是:目标距离近、姿态固定、环境温度相对稳定,或者目标温度明显偏离室温(比如 50°C 以上),再或者你允许用黑体炉或接触式温度计做过一次性标定。

不适合用的场景也很明确:高速运动的目标、极低发射率的光滑金属表面、要求 0.1°C 级精度的人体医学测温、以及测量距离超过 1 米的场合。光滑金属表面测出来的温度基本是环境反射温度,完全不靠谱。先搞清楚被测物体的发射率、测量距离、环境温度范围这三件事,再往下看接线和代码,你才能真正明白"测试通过"离"项目可用"差在哪。

2. 硬件接线与 I2C 通信:先搞清楚这几根线再写代码

我自己调试时用的是一个带稳压和电平转换的模块板,四根引脚:VDD、VSS(地)、SCL、SDA,部分模块还会引出一个 SMB 引脚用于 SMBus 报警,日常测温用不到。MLX90614 出厂前已经完成了校准,上位机只要通过 I2C 总线的读操作去拿内部 RAM 里的温度数据就行,不需要你写任何校准参数,这一点比模拟输出的热电堆方案省心太多。

2.1 引脚确认、供电范围与上拉电阻的坑

MLX90614 数据手册标称供电范围是 2.6V 到 3.6V,直接给 5V 会损坏传感器。不过市面上大多数模块板都做了板载稳压,所以接 5V 也能正常工作。我这次调试用的是 3.3V 供电,同时把 SCL/SDA 也接到 3.3V 电平的单片机上,省掉了电平转换的麻烦。如果你拿到的是裸片,或者自己画 PCB,供电部分一定要按 3.3V 设计。

另外一个非常容易踩的坑是上拉电阻。传感器的 SCL 和 SDA 是开漏输出,必须外部上拉。开发板上一般已经贴好了 4.7kΩ 或者 10kΩ 的电阻,但自己画板子时一旦忘记画,I2C 通信就会时好时坏。最典型的表现是:第一次读温度正常,第二次返回 0xFFFF。这通常不是传感器坏了,而是总线缺少高电平驱动能力,数据线被拉低之后回不来。

2.2 从 SMBus 到 I2C:时序、地址冲突和双传感器方案

MLX90614 原生支持 SMBus 协议,SMBus 与 I2C 在字节级读写上兼容,但时序参数有差异。绝大多数 MCU 的硬件 I2C 外设能正常通信,软件模拟 I2C 的库也能跑,只要总线频率别设太高,比如别超过 100kHz,一般都能稳定工作。我习惯把 I2C 时钟配置为 100kHz,读取间隔 100ms 以上,简单粗暴但足够稳定。

地址冲突是另一个高频问题。默认 7 位地址是 0x5A,换算成 8 位写地址就是 0xB4、读地址 0xB5。这个地址出厂就固定了,同一根 I2C 总线上默认只能挂一个 MLX90614。网上很多人想接两个传感器同时测两个点,结果却发现两个模块都不能正常工作,原因就是地址冲突。解决方式有两个:要么用 I2C 多路开关,要么先通过 SMBus 协议改写其中一个传感器的地址,再并联到总线上。

3. 核心代码拆解:从 I2C 读二进制到输出温度

温度数据藏在传感器的 RAM 里,具体来说:0x06 地址保存环境温度 Ta,0x07 地址保存物体温度 Tobj。每个寄存器读取后会返回三个字节:低八位、高八位、PEC 校验字节。温度换算公式也很简单:把 16 位数据处理成有符号十进制数后乘以 0.02°C/LSB,再减去绝对零度的偏移量 273.15,就得到了摄氏温度。

3.1 一个可以直接用的 Arduino 读取例程

#include <Wire.h> #define MLX90614_ADDR 0x5A float readMLX(uint8_t reg) { Wire.beginTransmission(MLX90614_ADDR); Wire.write(reg); Wire.endTransmission(false); Wire.requestFrom(MLX90614_ADDR, 3); uint16_t raw = Wire.read() | (Wire.read() << 8); // 第三个字节是 PEC,演示代码先不校验 return raw * 0.02 - 273.15; } void setup() { Serial.begin(115200); Wire.begin(); } void loop() { float ta = readMLX(0x06); float tobj = readMLX(0x07); Serial.print("Ta="); Serial.print(ta, 2); Serial.print(" Tobj="); Serial.println(tobj, 2); delay(500); }

这段代码在 Arduino Uno 上编译上传就能用。注意 requestFrom 请求的是 3 个字节,其中第三个 PEC 字节即使不校验也要读出来清掉,否则会影响下一次传输的总线状态。endTransmission(false) 表示发送寄存器地址时不要发停止位,这样后面才能用重复起始条件直接读数据。很多移植失败的例程,就是在这里多发了停止位,导致后续读取直接超时。

3.2 STM32 HAL 版本的移植要点和异常值处理

STM32 上用 HAL 库实现更简单,可以直接用 HAL_I2C_Mem_Read 一步完成"发地址+读数据":

uint8_t buf[3]; uint16_t raw; float tobj; HAL_I2C_Mem_Read(&hi2c1, 0x5A << 1, 0x07, I2C_MEMADD_SIZE_8BIT, buf, 3, 100); raw = buf[0] | (buf[1] << 8); tobj = raw * 0.02f - 273.15f;

再把 0x06 的环境温度读取也做一遍,加上错误判断,一个稳定的读取函数就出来了。HAL 方式比手写 SMBus 稳定得多,但还是要强调:buf 长度必须与传感器实际返回字节数一致。传感器每次返回的就是 3 字节,你只读 2 个,总线上会残留数据,下一次通信就会乱掉。

如果你不是做固定夹具而是手持设备,传感器会偶尔出现个别跳变值,典型表现是温度瞬间跳到 -40°C 或者 300°C 以上。原因通常是电源毛刺、总线干扰,或者目标物瞬间移出视场。最简单有效的处理方式是中值滤波:连续读 5 次,排序后取中间值。对温度变化本来就比较缓慢的物体,中值滤波比滑动平均更好用,它可以干净地丢掉毛刺,而滑动平均还会把毛刺算进平均值里。

4. 测试通过不等于测准了:一组实测数据带来的教训

串口能打印数值只是第一步,真正决定项目质量的是数值准不准。我在调试时把传感器固定在一个支架上,对准一个带热电偶的恒温加热源,从 30°C 到 80°C 分档做了记录。实验条件为:传感器距离目标 5cm,目标完全填满视场。

4.1 从 30°C 到 80°C 的实测偏差记录

参考温度(°C)MLX90614 读数(°C)偏差(°C)
30.230.6+0.4
40.541.0+0.5
50.150.8+0.7
60.361.2+0.9
70.071.3+1.3
80.281.9+1.7

从这张表可以明显看出一个规律:目标温度越高,正偏差越大。这个偏差很大程度来自传感器外壳、电路板自身温度和环境背景红外辐射的叠加。对 70°C 以下的目标,出厂默认配置能稳定做到 ±1°C 以内;对更高温度的目标,必须做软件校正,把增益和偏移系数算出来再用。

4.2 距离、视场角和发射率:三个最常被忽略的参数

视场角的影响前面提过,目标物不能填满视场时,读数就是目标与背景的加权平均值。同一个发热源,测量距离从 5cm 变成 15cm,读数差好几度是很正常的。实际项目里要么用固定支架把距离锁死,要么加一个瞄准筒限制传感器的实际视场,绝不能指望用户每次都能对准。

发射率同样关键。MLX90614 出厂默认的发射率配置接近黑体标定值,但真实物体的发射率几乎都小于 1。人体皮肤约 0.98,普通电路板表面约 0.9,抛光铝板只有 0.05 左右。如果你要测的是抛光金属表面,读出来的"温度"很大程度是环境温度的反射。处理方法是先给被测物喷涂高发射率涂层,或者贴一层黑色哑光胶带。这个细节在项目评审的时候特别容易被忽略。

4.3 一个实操有效的两点校准法

假设传感器读数 r 和真实温度 t 之间近似线性关系 t = a × r + b,那么用两个已知温度点做标定就能求出 a 和 b。我实测下来这比反复调发射率更直接、更省事。具体做法:把目标物分别稳定在 35°C 和 55°C,记录传感器的对应读数,用这两组数据解出系数,然后在代码输出温度时统一套用。

校准后还需要再用第三个温度点做验证,确认线性假设在这个区间成立。需要特别注意的是,标定点一定要覆盖实际使用的工作范围。你要是拿 35°C 和 55°C 标定完,回头去测 200°C 的物体,那偏差会大得离谱。

5. 从工程样机到落地:外壳、工艺和功耗里的那些暗坑

项目到这一步,"测试通过"确实已经达成。但如果你有量产打算,或者要让它在真实环境里连续运行,下面几个问题值得花时间处理。

5.1 外壳开窗与红外窗口材料选择

MLX90614 接收的红外辐射波段通常在中远红外范围,这类辐射穿过普通 ABS 塑料外壳时会被严重衰减。如果把传感器直接塞进一个厚塑料壳里,读到的很可能是外壳材料本身的温度,而不是目标温度。正确做法是在传感器正前方开一个通孔,或者留一个光学窗口。窗口材料必须能透过 8~14μm 波段,常见可选高密度聚乙烯(HDPE)薄膜或锗玻璃,普通玻璃和亚克力会挡住大部分红外辐射,导致读数完全失真。

我最早做样机时图省事,直接用透明亚克力做了个盖板,结果把 40°C 的目标测成了 24°C,当时一度以为传感器坏了。后来换上 HDPE 薄膜窗口才恢复正常。另外,任何窗口材料都会对读数造成 1~2°C 的衰减,量大的话需要在软件里做固定补偿。

5.2 环境温度突变、上电漂移与低功耗设计

MLX90614 在工作原理上必须有环境温度参考。传感器内部的环境温度传感器会持续测量自身温度,用来修正目标温度的计算。当环境温度快速变化,比如从空调房一下拿到烈日下,传感器外壳温度还没稳定,输出读数就会在一两分钟内明显漂移。量产产品常用的办法是让传感器外壳与空气有更大的热接触面积,或者把这种漂移通过系统级标定吸收掉。

上电瞬间的读数也不能信。传感器内部信号链路需要一个稳定过程,建议至少等 1 秒再开始取数,并且直接丢弃第一次读数,后续再做滤波。很多时候现场报"一上电就显示 -273°C",其实是正常的待机输出,等两三秒就自行恢复了,排查故障时先别慌,加个延时再看。

如果设备用电池供电,你会发现 MLX90614 的空闲电流本身很低,真正耗电的是 MCU 持续轮询。我一般把它放在掉电模式,用定时器或者外部按键唤醒后,一次性读三五个值再进睡眠,平均电流能压到 1mA 以下。对连续监控的场景,每 200ms 读一次就足够了,再高的刷新率意义不大,热电堆的响应时间本来就在百毫秒量级。

最后再分享一点我的真实体会。这个"测试通过"的 rar 包虽然内容简陋,但确实帮我走完了一个完整的开发闭环:从硬件接线、I2C 通信、寄存器读取,到校准验证和工艺修改,每一步踩过的坑后来都变成了做其他项目的通用经验。如果让我重做一遍,我会在一开始就预留好校准流程的数据接口,而不是等到测出来偏了两度再临时写补偿。MLX90614 是一颗非常成熟、成本可控的传感器,它不算复杂,但远比"接三根线、读两个寄存器"这几个字要值得多。希望这篇内容能帮你把"测试通过"变成真正的"项目可用"。

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

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

从临时脚本到工程化工具:构建可复用开发工具箱的实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/2 16:19:24

GESP C++四级备考的打卡表模板

这里给你提供3种不同场景的GESP C四级备考打卡表模板&#xff0c;全部适配四年级孩子的学习节奏&#xff0c;可直接修改打印使用。 7天冲刺极简打卡模板&#xff08;适合考前突击&#xff09; 天数 核心任务 刷题内容 完成打勾 家长签字 Day1 基础语法唤醒 20道四级单选…

作者头像 李华
网站建设 2026/9/2 16:17:58

2026年Java工程师就业路线图:零基础到精通实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/2 16:16:19

个人微信二次开发中的指令系统:让不同微信操作由程序统一管理

微信操作&#xff08;发消息 / 加好友 / 拉群&#xff09;如果散落在代码各处&#xff0c;新增一个操作就要改多处。指令系统的作用是"统一注册、统一路由、统一执行、统一回收"。一条指令从生到死有4个阶段&#xff0c;本文按生命周期来讲 Eyun 项目里怎么搭这套系统…

作者头像 李华
网站建设 2026/9/2 16:14:25

Python 实战:公共卫生间点位地图采集——bbox 视窗拆分、密集区域递归细分与设施属性统一

㊗️本期内容已收录至专栏《Python爬虫实战》,持续完善知识体系与项目实战,建议先订阅收藏,后续查阅更方便~ ㊙️本期爬虫难度指数:⭐⭐⭐⭐☆(高级) 🉐福利: 一次订阅后,专栏内的所有文章可永久免费看,持续更新中,保底1000+(篇)硬核实战内容。 全文目录: 🌟 开…

作者头像 李华