ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

STM32+MLX90614红外测温实战:原理、接线、驱动与排坑指南

STM32+MLX90614红外测温实战:原理、接线、驱动与排坑指南 简介MLX90614红外测温系统是嵌入式开发中的常见场景这份驱动资源面向STM32开发者用于解决红外测温模块的快速移植与驱动编写问题。ZIP压缩包共2个文件包含C源码与头文件各一个整体仅2KB便于直接嵌入工程阅读源码侧重初始化、I²C通信、寄存器配置和温度数据读取头文件则提供函数原型与相关常量定义。内容还涉及Object1/Object2温度寄存器、发射率设置、16位原始数据的温度换算公式以及通信失败、超时等异常处理的排错思路对ear9fp封装特点和实时测温场景也有补充说明。通过封装好的函数接口可快速完成初始化与温度读取减少对照数据手册逐条配置的重复工作用作模块接入与调试的参考笔记非常合适。目前已有1139人学习下载适合正在学习STM32外设驱动或需要快速集成MLX90614的开发者。 MLX90614配STM32做红外测温这两年几乎成了嵌入式项目的标配。毕设要做非接触测温手环、测温门禁、智能晾衣杆热源感应很多人的第一反应就是搜“STM32 MLX90614”找到代码、烧进去、串口能打印出温度就算跑通了。但等你真拿这东西去测一个具体物体就会发现事情没那么简单为什么测金属不准为什么读数跳来跳去为什么别人能跑通的代码在我板子上就是NACK这篇文章就围绕STM32加MLX90614这套组合把原理、接线、驱动、标定和排坑一次性讲完给正在做红外测温的兄弟们一份真正能照着干的手册。1. MLX90614凭什么能做非接触测温1.1 热电堆原理温度怎么变成数字MLX90614内部核心是红外热电堆传感器。任何有温度的物体都在向外辐射红外线辐射强度跟物体表面温度的四次方成正比温度越高辐射的红外能量越强。热电堆由上百个微型热电偶串联而成吸收红外辐射后产生与辐射强度成正比的微小电压信号这个信号经过芯片内置的运放放大、24位ADC数字化再通过DSP做环境温度补偿和非线性校正最后输出数字温度值。所以它测的是物体表面辐射温度而不是空气温度。这一点决定了很多使用场景的差异比如测一杯热水MLX90614测的是水面或杯壁的表面温度而DS18B20测的是水本身的温度。两者各有用途做红外测温项目首先要搞清楚你到底要测哪个温度。1.2 型号怎么选不是所有MLX90614都一样这块比较容易踩坑。MLX90614的型号后缀决定了物体测温量程和视场角ESF/BAA最常见的消费和医疗版物体测温范围约-40到115℃体温场景到50℃足够用环境温度范围-40到85℃90°视场价格最低适合人体测温、非接触测温门禁这类项目。A系列如A01、A02工业版物体测温范围可达-70到380℃适合测电机外壳、加热管、热水管路温度。DCI版本窄视场版本大概1°左右的视场角适合距离稍远、目标尺寸较小的点温场景。很多做毕业设计的同学上来就买ESF/BAA结果拿去测几百度的加热管读到的最高温度被芯片量程限制住白折腾一场。选型第一步就把量程和视场定好后续能省掉大量返工。1.3 SMBus接口和寄存器结构MLX90614对外提供两个接口PWM和SMBus兼容I2C。PWM模式直接把温度映射成占空比分辨率10位SMBus模式下分辨率16位0.02℃每LSB所以我一直推荐用SMBus读数据。出厂默认7位I2C地址是0x5A换算成8位写地址0xB4、读地址0xB5HAL库配置时DevAddress要填0xB4即0x5A左移一位这是新手最容易搞混的地方。芯片内部主要分两块存储RAM是运行数据区0x07地址存环境温度TA0x06地址存物体温度TObjEEPROM是配置区存发射率、地址、量程校准参数等出厂写死一般不轻易动。读数据时主机向芯片发送寄存器地址芯片返回3个字节低字节、高字节、PEC校验字节。前两字节拼成16位原始值换算后就是温度。2. 硬件连接与布局细节2.1 供电和引脚MLX90614的引脚在SMBus模式下一共4个VIN、GND、SCL、SDA。VIN供电电压要看你手里是散片还是模块散片按数据手册的标称电压来常见的是3.3V供电成品模块大多板载稳压5V供电也能正常工作。我建议拿不准的时候先看模块背面丝印或者直接查你购买页的原理图别凭感觉接。去耦电容不能省。VIN和GND之间加一个100nF陶瓷电容位置尽量靠近芯片的VIN引脚条件允许再并一个10uF电容。很多散片用户直接飞线电源纹波一大I2C通信就时好时坏表象是读数据偶尔成功偶尔失败实际根子在供电。2.2 上拉电阻不能省SMBus规范要求总线有上拉电阻MLX90614的SDA、SCL是开漏输出必须外部上拉。推荐4.7k到10k总线速度快就选小一点的阻值400kHz时4.7k比较稳。STM32内部上拉不要指望那个阻值普遍在30k以上驱动能力弱总线上升沿会变得很慢数据就容易出错。我第一次用的时候就犯了没加上拉的错SCL/SDA直接接STM32的PB6/PB7把内部上拉打开了读回来的数据隔三差五就是0xFFFF当时还以为是芯片坏了。后来示波器一抓发现总线上根本没有干净的高电平波形边缘塌得一塌糊涂。加上两个4.7k电阻之后问题立刻消失。从那以后我养成了一个习惯凡是I2C项目画板子的第一步就是把上拉电阻预留好哪怕之后用不到也比飞线补焊强。2.3 探头安装和视场角的影响传感器自身会发热而且芯片封装本身就有温漂所以安装时要让传感器周围有空气流通尽量避免直接贴在发热的大功率器件或主控芯片上。这就是为什么原厂文档都会说TA读数是传感器附近的环境温度——TA不准会直接连累TObj的补偿精度。视场角影响更大。MLX90614ESF是90°视场测量距离越远采集到的目标区域越大。距离10cm测到的是一个直径接近18cm的圆如果目标物体只有5cm大小读到的温度会混合背景温度结果偏低。做体温枪这种近距离测量问题不大但做设备监测时就要算好距离和目标尺寸或者选窄视场版本。安装的时候也要注意视场角内不要有塑料外壳、遮挡物不然测的就是遮挡物的温度。3. STM32驱动代码实现3.1 用CubeMX把I2C配好用STM32CubeMX配置I2C1标准模式和快速模式都可以建议先从100kHz起步跑通了再提到400kHz。关键是GPIO要配成开漏输出CubeMX里可以把PB6/PB7的内部上拉开起来但外部4.7k上拉才是正解内部上拉只是辅助。初始化配置代码大致如下I2C_HandleTypeDef hi2c1; hi2c1.Instance I2C1; hi2c1.Init.ClockSpeed 100000; // 100kHz先低速跑通 hi2c1.Init.DutyCycle I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 0; hi2c1.Init.AddressingMode I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode I2C_DUALADDRESS_DISABLE; hi2c1.Init.GeneralCallMode I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode I2C_NOSTRETCH_DISABLE; if (HAL_I2C_Init(hi2c1) ! HAL_OK) { Error_Handler(); }如果你用的是标准库而不是HAL库原理完全一样只是寄存器操作方式不同。标准库新建工程的时候记得把I2C外设时钟打开GPIO模式配成开漏复用漏掉任何一步都会让总线工作异常。3.2 读RAM寄存器三步完成读MLX90614温度数据其实很简单核心就一条HAL_I2C_Mem_Read。芯片内部寄存器短地址是8位所以MemAddressSize用I2C_MEMADD_SIZE_8BIT。/** * brief 从MLX90614读取寄存器数据 * param hi2c: I2C句柄 * param reg: 寄存器地址RAM区0x06物体温度0x07环境温度 * param data: 返回16位原始数据 * retval 0成功1超时或错误 */ uint8_t MLX90614_ReadReg(I2C_HandleTypeDef *hi2c, uint8_t reg, uint16_t *data) { uint8_t buf[3] {0}; // 注意DevAddress是7位地址左移一位0x5A 1 0xB4 if (HAL_I2C_Mem_Read(hi2c, 0x5A 1, reg, I2C_MEMADD_SIZE_8BIT, buf, 3, 200) ! HAL_OK) { return 1; } // buf[0]为数据低字节buf[1]为数据高字节buf[2]为PEC实际使用可忽略 *data ((uint16_t)buf[1] 8) | buf[0]; return 0; }温度换算/** * brief MLX90614原始数据转为摄氏度 * note 内部以0.02℃/LSB分辨率存储开尔文温度 * param raw: 16位原始值 * retval 温度℃ */ float MLX90614_ToCelsius(uint16_t raw) { return raw * 0.02f - 273.15f; }25℃室温附近读到的raw应该接近0x3A3C十进制14908乘0.02减273.15刚好约25℃。如果读到的原始值离这个范围很远先别急着调代码多半是硬件连接问题。3.3 不稳定的硬件I2C换成软件I2CSTM32F103系列在早期标准库时代硬件I2C被很多人调侃是“bug集合体”原因是SMBus时序跟标准I2C有细微差别尤其在总线超时检测、PEC字节上容易翻车。用HAL库以后稳定性好了不少但如果你发现硬件I2C读MLX90614时第一次总是失败、重试几次又能成功那基本还是外部上拉不足或者总线电容过大导致边沿过缓跟芯片本身关系不大。排查顺序建议是先按100kHz跑确保稳定了再提速若还是不稳定直接上软件I2C。软件I2C本质就是两个GPIO模拟时序代码量不大而且可以任意指定引脚硬件接线更灵活。核心读写思路如下#define MLX90614_ADDR 0x5A #define MLX90614_WRITE (MLX90614_ADDR 1) // 0xB4 #define MLX90614_READ ((MLX90614_ADDR 1) | 1) // 0xB5 // GPIO模拟I2CSCL/SDA配置为开漏输出拉高必须依赖外部上拉电阻 static void I2C_Start(void) { SDA_H(); SCL_H(); delay_us(5); SDA_L(); delay_us(5); SCL_L(); } static void I2C_Stop(void) { SDA_L(); SCL_H(); delay_us(5); SDA_H(); delay_us(5); }完整模拟I2C代码网上例程一大把这里只提关键坑软件I2C的延时函数必须准确。用for循环空转延时或者定时器延时都行但绝对不能在一个会被高优先级中断打断的地方做位翻转否则时序一乱芯片就不响应了。之前有人遇到“STM32延时函数delay卡死”的问题排查半天发现是中断里调用了会等待的延时函数导致主循环的I2C时序被打断。所以软件I2C的延时函数要选用不依赖中断的忙等待版本。3.4 完整读取流程实际项目里不可能只读一次我用的是“多次读取加中值滤波”的流程读TObj寄存器0x06连续读5次每次间隔10ms。去掉最大值和最小值剩下的取平均。再读TA寄存器0x07判断传感器自身环境温度是否正常。如果TObj和TA很接近说明传感器前方可能没有目标物体或者目标物体温度与环境一致属于正常现象不要误判成传感器故障。滤波的主要作用是消除偶发的毛刺尤其是工业现场有电机、变频器干扰的时候单次读数的可信度很低。平均之后的数值虽然也会有波动但至少趋势是稳定的拿去做阈值判断就不会频繁误触发。4. 温度数据换算与精度调校4.1 0.02和273.15这两个数怎么来的MLX90614内部把温度以0.02摄氏度的分辨率存成16位数据单位是开尔文。所以拿到raw值之后先乘以0.02得到开尔文温度再减去273.15就是摄氏度。不少人看到0.02会疑惑这个分辨率其实是芯片出厂就定死的换算公式全球通用不需要自己标定。细节上要注意raw本身在正常量程内不会超过0x7FFF所以直接用uint16_t运算、转float后再减273.15即可不需要特意处理负数。如果某些异常情况下raw大于0x8000大概率是芯片配置异常或读数错误代码里可以做一次范围过滤超出量程的数据直接丢弃防止把错误值送进控制逻辑。4.2 发射率为什么测金属会不准所有红外测温的“天敌”都是发射率。发射率代表物体表面辐射红外能量的能力黑体发射率是1人体皮肤约0.98普通油漆表面约0.9氧化铝约0.3而抛光铝只有0.04左右。MLX90614出厂默认按发射率1.0来计算测高发射率物体误差不大但测金属、镜面、反光面就会严重偏低。调整方法写EEPROM地址0x04写入值等于目标发射率乘以0xFFFF。人体测温场景建议写0.95左右也就是约0xF332十进制62258。写入时要注意EEPROM写入次数有限且有写保护时序操作前把出厂值备份好弄错可能把芯片配置搞乱甚至整个芯片变砖。如果不是对特定材料测温大多数场景保持默认1.0就行。你会发现一个典型现象拿红外测温测打磨后的铝块读出来只有40℃实际上铝块已经80℃了贴上黑色电工胶带再测温度瞬间就上来了。这不是传感器坏了是被测面的发射率变了。所以测金属目标最省事的办法就是贴黑胶带而不是折腾EEPROM。4.3 现场标定三步走我给母排测温项目做标定时是拿K型热电偶同时贴在同一个铜排上读两组数据做差值补偿。操作流程分三步准备一个恒温源或者直接用热水、恒温烙铁设定几个不同温度点。MLX90614对准目标表面稳定后记录读数同时记录热电偶的参考值。多测几个点后做线性拟合得到一个offset值写入代码里。注意测量距离每次都要保持一致90°大视场下距离差1cm结果就可能差好几度。这个方法虽然土但在工程现场反而最实用。需要提醒的是标定精度并不会超过热电偶本身的精度想要绝对准确就得上黑体炉那个成本就不是几十块钱能搞定的了。5. 常见问题与排查技巧实录5.1 问题速查表现象可能原因解决办法读数固定0xFFFFSDA/SCL接线错误、芯片未上电、上拉电阻缺失检查供电万用表量VIN电压补上外部上拉电阻HAL_I2C_Mem_Read返回NACK或超时从机地址填错、总线被拉死、SCL/SDA接反确认地址是0x5A左移一位逐个量SCL/SDA电平复位总线数据能读到但偶尔跳变很大总线干扰、电源纹波大、测量距离不稳定加去耦电容、降低I2C时钟、固定测量距离TObj和TA几乎一样传感器前方没有被测对象或被测物体温度与环境相同把传感器对准目标物体或用手挡一下测试测金属温度明显偏低金属表面发射率低红外测温测的是辐射温度而非真实温度表面贴黑胶带或涂黑漆后再测或调整发射率硬件I2C读取时好时坏SMBus时序兼容性、上拉电阻不匹配、总线电容过大降到100kHz检查上拉电阻不行直接换软件I2C5.2 开发环境的小坑调试MLX90614的时候如果程序烧录不进去不要光盯着传感器代码也要检查开发工具链这边。ST-Link连接丢失报“error: no stm32 target found”这类错误时很多时候是PA13/PA14被代码复用成普通GPIO了而你的I2C引脚恰好又离得很近飞线毛刺把调试端口干扰了。解决办法是把Boot0拉高进ISP模式擦除或者按住复位键点烧录、在芯片复位瞬间松开这些土办法实测都有效。还有一次项目拷给别人对方Keil里编译报错找不到芯片最后发现是芯片支持包没装好。所以拿到一个STM32工程第一件事先确认芯片型号和设备支持包跟你本机环境对得上不然排查半天全是环境问题。另外Keil5兼容C51和STM32的安装方式也不一样要分别装对应的芯片包混用工程模板经常会报奇怪的宏定义错误。5.3 我买到假芯片了吗最近市面上MLX90614散片鱼龙混杂很多人买回去读到的温度明显偏高或偏低。一个简单的验证方法把发射率保持默认用黑胶带贴在待测物体表面如果胶带区域读数和周围裸面读数差得很远说明裸面发射率低是正常现象。反过来如果怎么测都读不准最高温度还明显超量程或者读数存在跳表那才要考虑是不是翻新片或打磨片。正品芯片的RAM数据读取连续10次原始值波动不会超过3到5个LSB波动太大说明芯片本身或电源有问题。另外MLX90614的SMBus地址默认是0x5A如果I2C扫描时在别的地址也有响应那多半不是原装芯片后面各种怪问题也就不奇怪了。最后再说一个我个人的习惯做这类传感器项目一定先把典型场景的正常读数范围记录下来。比如25℃室温下MLX90614的0x07寄存器大概读到0x3A3C附近。以后不管代码怎么改、硬件怎么换只要读数偏离这个基准太多就能立刻判断是环境变化还是系统故障。这个习惯帮我省掉了大量排查时间。红外测温这东西原理不复杂真正的功夫都在细节里供电、上拉、发射率、测量距离、视场角每一个都能让数据面目全非。如果你也正在调MLX90614按照上面的顺序从硬件到软件排查一遍大概率能把问题解决掉。本文还有配套的精品资源点击获取
返回列表