STM32F1读取MLX90632非接触式红外温度传感器
时间:2023-11-29 07:37:00
MLX90632 简介
MLX90632是一个小型SMD SFN包装中的非接触式红外温度传感器可以实现高精度的非接触式温度测量。该装置存储在工厂EEPROM校准存储器中的校准常数。环境温度和目标温度可根据校准常数和测量数据计算。
MLX90632在工厂校准,环境温度范围为-20至85℃,目标温度范围为-20至200℃。测量值是传感器视野中所有物体的平均温度。当传感器处于热平衡和恒温条件下(传感器组件之间没有温差)时,应用程序设计师必须知道这些精度是有保证的,可以实现。
温度计的准确性可能受到包装中温差的影响,包括(除外):传感器后面的热电子元件、传感器后面或旁边的加热器/冷却器,或靠近传感器的热/冷物体,不仅加热温度计中的传感元件,还加热温度计包装。
MLX90632的主要优点之一是通过内部测量算法最大限度地降低传感器组件周围温差的测量效果。同样,局部热变化(如空气中的湍流)也不会在热堆的输出信号中产生热噪声。然而,一些极端情况会影响传感器。
MLX90632典型电源电压为3.3V,与芯片的通信是由的I 2 C在快速模式下完成。通过I 2 C,外部微控制器可访问以下块:用于测量数据RAM存储器用于存储微调值、校准常数和设备/测量设置EEPROM根据数据控制传感器的寄存器,外部微控制器可以计算目标温度,必要时也可以计算传感器温度。
光学滤光器(长波通)集成在传感器中,可以切断可见光和近红外辐射通量,提供环境光抗干扰。滤光器的波长带为2~14μm。
其特点主要有:
- 在高温环境下准确稳定地工作
- 采用 3mm x 3mm x 1mm DFN 包装不需要使用体积大的包装 TO 罐封装
- 消费水平:测量物体温度 -20 °C 至 200 °C,精度±1 ℃;医疗级:测量物体温度-20 °C 至 100 °C,人体温度测量精度高达±0.2 °C
- 使用 I2C 出厂校准数字接口,50° 的视场角
- 工作温度范围: -20 °C 至 85 °C
MLX90632 不同型号的异同
型号 | MLX90632-BCB-000 | MLX90632-DCB-000 | MLX90632-DCB-100 |
---|---|---|---|
准确性 | 标准精度 | 医用级精度 | 医用级精度 |
I2C电压等级 | 3V3 | 1V8 | 1V8 |
电源电压范围 | 3-5V DC(模块带低压差稳压) |
---|---|
能耗 | 9.2μA(典型值)12μA(最大值) |
温度工作范围 | -20°C - 85°C |
输出信号 | I2C数字接口 |
PS: 传感器型号描述:
使用STM32F1单片机驱动MLX90632
- bsp_mlx90632.c 文件
/******************************************************************************* * Filename: bsp_mlx90632.c * Revised: All copyrights reserved to Roger. * Date: 2020-10-17 * Revision: v1.0 * Writer: Roger-WY. * * Description: 非接触式红外温度传感器模块驱动(数字) * * * Notes: https://www.melexis.com/zh/product/MLX90632/MLX90632 * All copyrights reserved to Roger-WY *******************************************************************************/ #include "bsp_mlx90632.h" #include
//----------------------------------------------------------------------------// #define MLX90632_I2C_SCL_RCC RCC_APB2Periph_GPIOC #define MLX90632_I2C_SCL_PIN GPIO_Pin_4 /* 连接到SCL时钟线的GPIO */ #define MLX90632_I2C_SCL_PORT GPIOC #define MLX90632_I2C_SDA_RCC RCC_APB2Periph_GPIOC #define MLX90632_I2C_SDA_PIN GPIO_Pin_5 /* 连接到SDA数据线的GPIO */ #define MLX90632_I2C_SDA_PORT GPIOC /* 定义读写SCL和SDA的宏 */ #define MLX90632_I2C_SCL_1() MLX90632_I2C_SCL_PORT->BSRR = MLX90632_I2C_SCL_PIN /* SCL = 1 */ #define MLX90632_I2C_SCL_0() MLX90632_I2C_SCL_PORT->BRR = MLX90632_I2C_SCL_PIN /* SCL = 0 */ #define MLX90632_I2C_SDA_1() MLX90632_I2C_SDA_PORT->BSRR = MLX90632_I2C_SDA_PIN /* SDA = 1 */ #define MLX90632_I2C_SDA_0() MLX90632_I2C_SDA_PORT->BRR = MLX90632_I2C_SDA_PIN /* SDA = 0 */ #define MLX90632_I2C_SDA_READ() ((MLX90632_I2C_SDA_PORT->IDR & MLX90632_I2C_SDA_PIN) != 0) /* 读SDA口线状态 */ #define MLX90632_I2C_SCL_READ() ((MLX90632_I2C_SCL_PORT->IDR & MLX90632_I2C_SCL_PIN) != 0) /* 读SCL口线状态 */ #define MLX90632_DELAY_MS(a) bsp_DelayNms(a); //----------------------------------------------------------------------------// #define POW10 10000000000LL /* 灵敏度 */ static double emissivity = 0.0; stMlx90632CalibraParTypeDef stMlxCalibraPar; //============================================================================// /* ******************************************************************************** * 函 数 名: Mlx90632_i2c_Delay * 功能说明: I2C总线位延迟,最快400KHz * 形 参: 无 * 返 回 值: 无 ******************************************************************************** */ static void Mlx90632_i2c_Delay(void) { volatile uint8_t i; for(i = 0; i < 50; i++); } static void Mlx90632_i2c_Start(void) { /* 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 */ MLX90632_I2C_SDA_1(); Mlx90632_i2c_Delay(); MLX90632_I2C_SCL_1(); Mlx90632_i2c_Delay(); MLX90632_I2C_SDA_0(); Mlx90632_i2c_Delay(); MLX90632_I2C_SCL_0(); // Mlx90632_i2c_Delay(); } /******************************************************************************* * 名 称: i2c_Stop * 功 能: CPU发起I2C总线停止信号 * 入口参数: 无 * 出口参数: 无 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: 停止时序 * SCL _____/ˉˉˉˉˉˉˉ * SDA _________/ˉˉˉˉˉ * | | * STOP *******************************************************************************/ static void Mlx90632_i2c_Stop(void) { /* 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 */ MLX90632_I2C_SCL_0(); Mlx90632_i2c_Delay(); MLX90632_I2C_SDA_0(); Mlx90632_i2c_Delay(); MLX90632_I2C_SCL_1(); Mlx90632_i2c_Delay(); MLX90632_I2C_SDA_1(); // Mlx90632_i2c_Delay(); } /******************************************************************************* * 名 称: i2c_WaitAck * 功 能: CPU产生一个时钟,并读取器件的ACK应答信号 * 入口参数: 无 * 出口参数: 返回0表示正确应答,1表示无器件响应 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/ static uint8_t Mlx90632_i2c_WaitAck(void) { uint8_t re; uint8_t TimeOutCnt = 20; /* 超时计数器 */ MLX90632_I2C_SDA_1(); /* CPU释放SDA总线 */ Mlx90632_i2c_Delay(); MLX90632_I2C_SCL_1(); /* CPU驱动SCL = 1, 此时器件会返回ACK应答 */ Mlx90632_i2c_Delay(); while(TimeOutCnt --) { if(MLX90632_I2C_SDA_READ()) /* CPU读取SDA口线状态 */ { re = 1; } else { re = 0; } } MLX90632_I2C_SCL_0(); Mlx90632_i2c_Delay(); return re; } /******************************************************************************* * 名 称: i2c_Ack * 功 能: CPU产生一个ACK信号 * 入口参数: 无 * 出口参数: 无 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/ static void Mlx90632_i2c_Ack(void) { MLX90632_I2C_SDA_0(); /* CPU驱动SDA = 0 */ Mlx90632_i2c_Delay(); MLX90632_I2C_SCL_1(); /* CPU产生1个时钟 */ Mlx90632_i2c_Delay(); MLX90632_I2C_SCL_0(); Mlx90632_i2c_Delay(); MLX90632_I2C_SDA_1(); /* CPU释放SDA总线 */ } /******************************************************************************* * 名 称: i2c_NAck * 功 能: CPU产生1个NACK信号 * 入口参数: 无 * 出口参数: 无 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/ static void Mlx90632_i2c_NAck(void) { MLX90632_I2C_SDA_1(); /* CPU驱动SDA = 1 */ Mlx90632_i2c_Delay(); MLX90632_I2C_SCL_1(); /* CPU产生1个时钟 */ Mlx90632_i2c_Delay(); MLX90632_I2C_SCL_0(); Mlx90632_i2c_Delay(); } /******************************************************************************* * 名 称: bsp_InitI2C * 功 能: 配置I2C总线的GPIO,采用模拟IO的方式实现 * 入口参数: 无 * 出口参数: 无 * 作 者: Roger-WY * 创建日期: 2018-06-29 * 修 改: * 修改日期: * 备 注: *******************************************************************************/ static void Mlx90632_InitI2C(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(MLX90632_I2C_SCL_RCC | MLX90632_I2C_SDA_RCC, ENABLE); /* 打开GPIO时钟 */ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; /* 开漏输出模式 */ GPIO_InitStructure.GPIO_Pin = MLX90632_I2C_SCL_PIN; GPIO_Init(MLX90632_I2C_SCL_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = MLX90632_I2C_SDA_PIN; GPIO_Init(MLX90632_I2C_SDA_PORT, &GPIO_InitStructure); /* 给一个停止信号, 复位I2C总线上的所有设备到待机模式 */ Mlx90632_i2c_Stop(); } /******************************************************************************* * 名 称: i2c_SendByte * 功 能: CPU向I2C总线设备发送8bit数据 * 入口参数: _ucByte : 等待发送的字节 * 出口参数: 无 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/ static void Mlx90632_i2c_SendByte(uint8_t _ucByte) { uint8_t i; /* 先发送字节的高位bit7 */ for(i = 0; i < 8; i++) { MLX90632_I2C_SCL_0(); Mlx90632_i2c_Delay(); if(_ucByte & 0x80) { MLX90632_I2C_SDA_1(); } else { MLX90632_I2C_SDA_0(); } _ucByte <<= 1; /* 左移一个bit */ Mlx90632_i2c_Delay(); MLX90632_I2C_SCL_1(); Mlx90632_i2c_Delay(); } MLX90632_I2C_SCL_0(); Mlx90632_i2c_Delay(); } /******************************************************************************* * 名 称: Mlx90632_i2c_ReadByte * 功 能: CPU从I2C总线设备读取8bit数据 * 入口参数: 无 * 出口参数: 读到的数据 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/ static uint8_t Mlx90632_i2c_ReadByte(void) { uint8_t i; uint8_t value; /* 读到第1个bit为数据的bit7 */ value = 0; for(i = 0; i < 8; i++) { value <<= 1; MLX90632_I2C_SCL_0(); Mlx90632_i2c_Delay(); MLX90632_I2C_SCL_1(); Mlx90632_i2c_Delay(); if(MLX90632_I2C_SDA_READ()) { value++; } } MLX90632_I2C_SCL_0(); Mlx90632_i2c_Delay(); return value; } //============================================================================// /******************************************************************************* * 名 称: bsp_Mlx90632Init * 功 能: Mlx90632传感器的初始化 * 入口参数: 无 * 出口参数: 无 * 作 者: Roger-WY. * 创建日期: 2018-08-08 * 修 改: * 修改日期: * 备 注: *******************************************************************************/ int8_t bsp_Mlx90632Init(void) { int8_t ucError = 0; Mlx90632_InitI2C(); bsp_Mlx90632ReadCalibraParInit(&stMlxCalibraPar); ucError = bsp_Mlx90632ReadCalibraParFromEeprom(&stMlxCalibraPar); return (ucError); } /******************************************************************************* * 名 称: bsp_Mlx90632WriteReg * 功 能: 对寄存器写值 * 入口参数: devAddr:设备地址 regAddr:寄存器地址 data:写入寄存器的值 * 出口参数: 读到的数据 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/ int8_t bsp_Mlx90632WriteReg(uint8_t devAddr, uint16_t regAddr, uint16_t data) { uint8_t ucAck = 0; uint8_t sendBuffer[5] = { 0}; //used to save the data to send sendBuffer[0] = devAddr << 1; sendBuffer[1] = (uint8_t)(regAddr >> 8); sendBuffer[2] = (uint8_t)regAddr; sendBuffer[3] = (uint8_t)(data >> 8); sendBuffer[4] = (uint8_t)data; Mlx90632_i2c_Start(); for(uint8_t i = 0; i < 5; i ++) { Mlx90632_i2c_SendByte(sendBuffer[i]); ucAck = Mlx90632_i2c_WaitAck(); if(ucAck) /* 如果Mlx90632,没有应答 */ { goto cmd_fail; /* 器件无应答 */ } } /* 发送I2C总线停止信号 */ Mlx90632_i2c_Stop(); return 0; /* 执行成功 */ cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */ /* 发送I2C总线停止信号 */ Mlx90632_i2c_Stop(); return -1; } /******************************************************************************* * 名 称: bsp_Mlx90632ReadReg * 功 能: 从寄存器里读值 * 入口参数: devAddr:设备地址 regAddr:寄存器地址 ppBuf:读取寄存器值的缓存区 nBytes:读取寄存器的字节数 * 出口参数: 读到的数据 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/ int8_t bsp_Mlx90632ReadReg(uint8_t devAddr, uint16_t regAddr, uint8_t* ppBuf, uint8_t nBytes) { uint8_t ucAck = 0; uint8_t ValBuf[6] = { 0}; uint8_t prcRegVal = 0; uint8_t i = 0; ValBuf[0] = devAddr << 1; ValBuf[1] = (uint8_t)(regAddr >> 8); ValBuf[2] = (uint8_t)regAddr; ValBuf[3] = (devAddr << 1) | 0x01; Mlx90632_i2c_Start(); for(i = 0; i < 3; i++) { Mlx90632_i2c_SendByte(ValBuf[i]); ucAck = Mlx90632_i2c_WaitAck(); if(ucAck) /* 如果没有应答 */ { goto cmd_fail; /* 器件无应答 */ } } //------------------------------------------------------------------------// Mlx90632_i2c_Start(); Mlx90632_i2c_SendByte(ValBuf[3]); ucAck = Mlx90632_i2c_WaitAck(); if(ucAck) /* 如果没有应答 */ { goto cmd_fail; /* 器件无应答 */ } while(nBytes) { *ppBuf = Mlx90632_i2c_ReadByte(); if(nBytes == 1) Mlx90632_i2c_NAck(); else Mlx90632_i2c_Ack(); nBytes--; ppBuf++; } /* 发送I2C总线停止信号 */ Mlx90632_i2c_Stop(); return 0; cmd_fail: /* 命令执行失败后,切记发送停止信号,避免影响I2C总线上其他设备 */ /* 发送I2C总线停止信号 */ Mlx90632_i2c_Stop(); return -1; } /******************************************************************************* * 名 称: bsp_Mlx90632ReadWord * 功 能: 从寄存器里读一个字(16-bit) * 入口参数: regAddr:寄存器地址 value:读取寄存器值的缓存区 * 出口参数: 0:读取成功 其他值,读取失败 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/ int8_t bsp_Mlx90632ReadWord(uint16_t regAddr, uint16_t* value) { int8_t ret = 0; uint8_t buf[2] = { 0}; ret = bsp_Mlx90632ReadReg(MLX90632_ADDR, regAddr, buf, 2); *value = buf[1] | (buf[0] << 8); return ret; } /******************************************************************************* * 名 称: bsp_Mlx90632ReadDoubleWord * 功 能: 从寄存器里读双字(32-bit) * 入口参数: regAddr:寄存器地址 value:读取寄存器值的缓存区 * 出口参数: 0:读取成功 其他值,读取失败 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/ int8_t bsp_Mlx90632ReadDoubleWord(uint16_t regAddr, uint32_t* value) { int8_t ret = 0; uint8_t buf[4] = { 0}; ret = bsp_Mlx90632ReadReg(MLX90632_ADDR, regAddr, buf, 4); *value = buf[2] << 24 | buf[3] << 16 | buf[0] << 8 | buf[1]; return ret; } /******************************************************************************* * 名 称: bsp_Mlx90632WriteWord * 功 能: 往寄存器里写入一个字(16-bit) * 入口参数: regAddr:寄存器地址 value:读取寄存器值的缓存区 * 出口参数: 0:读取成功 其他值,读取失败 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/ int8_t bsp_Mlx90632WriteWord(uint16_t regAddr, uint16_t data) { int8_t ret = 0; ret = bsp_Mlx90632WriteReg(MLX90632_ADDR, regAddr, data) ; return (ret); } /******************************************************************************* * 名 称: bsp_Mlx90632ReadCalibraParInit * 功 能: 校准参数初始化,如果eeprom的校准参数读出来为空,就是使用此默认值 * 入口参数: pPar:校准参数结构体指针 * 出口参数: 无 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/ void bsp_Mlx90632ReadCalibraParInit(stMlx90632CalibraParTypeDef* pPar) { pPar->PR = 0x00587f5b; pPar->PG = 0x04a10289; pPar->PT = 0xfff966f8; pPar->PO = 0x00001e0f; pPar->Ea = 4859535; pPar->Eb = 5686508; pPar->Fa = 53855361; pPar->Fb = 42874149; pPar->Ga = -14556410; pPar->Ha = 16384; pPar->Hb = 0; pPar->Gb = 9728; pPar->Ka = 10752; } /******************************************************************************* * 名 称: bsp_Mlx90632ReadCalibraParFromEeprom * 功 能: 从传感器内部EEPROM中读取校准参数 * 入口参数: pPar:校准参数结构体指针 * 出口参数: 无 * 作 者: Roger-WY * 创建日期: 2022-05-04 * 修 改: * 修改日期: * 备 注: *******************************************************************************/ int8_t bsp_Mlx90632ReadCalibraParFromEeprom(stMlx90632CalibraParTypeDef* pPar) { int8_t ret = 0; ret = bsp_Mlx90632ReadDoubleWord(MLX90632_EE_P_R, (uint32_t*)&pPar->PR); if(ret < 0) return ret; ret = bsp_Mlx90632ReadDoubleWord(MLX90632_EE_P_G, (uint32_t*)&pPar->PG); if(ret < 0) return ret; ret =