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
#include "bsp_mlx90632.h"
#include <math.h>
#define MLX90632_I2C_SCL_RCC RCC_APB2Periph_GPIOC
#define MLX90632_I2C_SCL_PIN GPIO_Pin_4
#define MLX90632_I2C_SCL_PORT GPIOC
#define MLX90632_I2C_SDA_RCC RCC_APB2Periph_GPIOC
#define MLX90632_I2C_SDA_PIN GPIO_Pin_5
#define MLX90632_I2C_SDA_PORT GPIOC
#define MLX90632_I2C_SCL_1() MLX90632_I2C_SCL_PORT->BSRR = MLX90632_I2C_SCL_PIN
#define MLX90632_I2C_SCL_0() MLX90632_I2C_SCL_PORT->BRR = MLX90632_I2C_SCL_PIN
#define MLX90632_I2C_SDA_1() MLX90632_I2C_SDA_PORT->BSRR = MLX90632_I2C_SDA_PIN
#define MLX90632_I2C_SDA_0() MLX90632_I2C_SDA_PORT->BRR = MLX90632_I2C_SDA_PIN
#define MLX90632_I2C_SDA_READ() ((MLX90632_I2C_SDA_PORT->IDR & MLX90632_I2C_SDA_PIN) != 0)
#define MLX90632_I2C_SCL_READ() ((MLX90632_I2C_SCL_PORT->IDR & MLX90632_I2C_SCL_PIN) != 0)
#define MLX90632_DELAY_MS(a) bsp_DelayNms(a);
#define POW10 10000000000LL
static double emissivity = 0.0;
stMlx90632CalibraParTypeDef stMlxCalibraPar;
static void Mlx90632_i2c_Delay(void)
{
volatile uint8_t i;
for(i = 0; i < 50; i++);
}
static void Mlx90632_i2c_Start(void)
{
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();
}
static void Mlx90632_i2c_Stop(void)
{
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();
}
static uint8_t Mlx90632_i2c_WaitAck(void)
{
uint8_t re;
uint8_t TimeOutCnt = 20;
MLX90632_I2C_SDA_1();
Mlx90632_i2c_Delay();
MLX90632_I2C_SCL_1();
Mlx90632_i2c_Delay();
while(TimeOutCnt --)
{
if(MLX90632_I2C_SDA_READ())
{
re = 1;
}
else
{
re = 0;
}
}
MLX90632_I2C_SCL_0();
Mlx90632_i2c_Delay();
return re;
}
static void Mlx90632_i2c_Ack(void)
{
MLX90632_I2C_SDA_0();
Mlx90632_i2c_Delay();
MLX90632_I2C_SCL_1();
Mlx90632_i2c_Delay();
MLX90632_I2C_SCL_0();
Mlx90632_i2c_Delay();
MLX90632_I2C_SDA_1();
}
static void Mlx90632_i2c_NAck(void)
{
MLX90632_I2C_SDA_1();
Mlx90632_i2c_Delay();
MLX90632_I2C_SCL_1();
Mlx90632_i2c_Delay();
MLX90632_I2C_SCL_0();
Mlx90632_i2c_Delay();
}
static void Mlx90632_InitI2C(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(MLX90632_I2C_SCL_RCC | MLX90632_I2C_SDA_RCC, ENABLE);
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);
Mlx90632_i2c_Stop();
}
static void Mlx90632_i2c_SendByte(uint8_t _ucByte)
{
uint8_t i;
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;
Mlx90632_i2c_Delay();
MLX90632_I2C_SCL_1();
Mlx90632_i2c_Delay();
}
MLX90632_I2C_SCL_0();
Mlx90632_i2c_Delay();
}
static uint8_t Mlx90632_i2c_ReadByte(void)
{
uint8_t i;
uint8_t value;
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;
}
int8_t bsp_Mlx90632Init(void)
{
int8_t ucError = 0;
Mlx90632_InitI2C();
bsp_Mlx90632ReadCalibraParInit(&stMlxCalibraPar);
ucError = bsp_Mlx90632ReadCalibraParFromEeprom(&stMlxCalibraPar);
return (ucError);
}
int8_t bsp_Mlx90632WriteReg(uint8_t devAddr, uint16_t regAddr, uint16_t data)
{
uint8_t ucAck = 0;
uint8_t sendBuffer[5] = {0};
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)
{
goto cmd_fail;
}
}
Mlx90632_i2c_Stop();
return 0;
cmd_fail:
Mlx90632_i2c_Stop();
return -1;
}
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++;
}
Mlx90632_i2c_Stop();
return 0;
cmd_fail:
Mlx90632_i2c_Stop();
return -1;
}
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;
}
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;
}
int8_t bsp_Mlx90632WriteWord(uint16_t regAddr, uint16_t data)
{
int8_t ret = 0;
ret = bsp_Mlx90632WriteReg(MLX90632_ADDR, regAddr, data) ;
return (ret);
}
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;
}
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 = bsp_Mlx90632ReadDoubleWord(MLX90632_EE_P_O, (uint32_t*)&pPar->PO);
if(ret < 0)
return ret;
ret = bsp_Mlx90632ReadDoubleWord(MLX90632_EE_P_T, (uint32_t*)&pPar->PT);
if(ret < 0)
return ret;
ret = bsp_Mlx90632ReadDoubleWord(MLX90632_EE_Ea, (uint32_t*)&pPar->Ea);
if(ret < 0)
return ret;
ret = bsp_Mlx90632ReadDoubleWord(MLX90632_EE_Eb, (uint32_t*)&pPar->Eb);
if(ret < 0)
return ret;
ret = bsp_Mlx90632ReadDoubleWord(MLX90632_EE_Fa, (uint32_t*)&pPar->Fa);
if(ret < 0)
return ret;
ret = bsp_Mlx90632ReadDoubleWord(MLX90632_EE_Fb, (uint32_t*)&pPar->Fb);
if(ret < 0)
return ret;
ret = bsp_Mlx90632ReadDoubleWord(MLX90632_EE_Ga, (uint32_t*)&pPar->Ga);
if(ret < 0)
return ret;
ret = bsp_Mlx90632ReadWord(MLX90632_EE_Gb, (uint16_t*)&pPar->Gb);
if(ret < 0)
return ret;
ret = bsp_Mlx90632ReadWord(MLX90632_EE_Ha, (uint16_t*)&pPar->Ha);
if(ret < 0)
return ret;
ret = bsp_Mlx90632ReadWord(MLX90632_EE_Hb, (uint16_t*)&pPar->Hb);
if(ret < 0)
return ret;
ret = bsp_Mlx90632ReadWord(MLX90632_EE_Ka, (uint16_t*)&pPar->Ka);
if(ret < 0)
return ret;
return 0;
}
int bsp_Mlx90632StartMeasurement(void)
{
int ret, tries = 100;
uint16_t reg_status;
ret = bsp_Mlx90632ReadWord(MLX90632_REG_STATUS, ®_status);
if(ret < 0)
return ret;
ret = bsp_Mlx90632WriteWord(MLX90632_REG_STATUS, reg_status & (~MLX90632_STAT_DATA_RDY));
if(ret < 0)
return ret;
while(tries-- > 0)
{
ret = bsp_Mlx90632ReadWord(MLX90632_REG_STATUS, ®_status);
if(ret < 0)
return ret;
if(reg_status & MLX90632_STAT_DATA_RDY)
break;
MLX90632_DELAY_MS(10);
}
if(tries < 0)
{
return -ETIMEDOUT;
}
return (reg_status & MLX90632_STAT_CYCLE_POS) >> 2;
}
int32_t bsp_Mlx90632ChannelNewSelect(int32_t ret, uint8_t* channel_new, uint8_t* channel_old)
{
switch(ret)
{
case 1:
*channel_new = 1;
*channel_old = 2;
break;
case 2:
*channel_new = 2;
*channel_old = 1;
break;
default:
return -EINVAL;
}
return 0;
}
int32_t bsp_Mlx90632ReadTempAmbientRaw(int16_t* ambient_new_raw, int16_t* ambient_old_raw)
{
int32_t ret;
uint16_t read_tmp;
ret = bsp_Mlx90632ReadWord(MLX90632_RAM_3(1), &read_tmp);
if(ret < 0)
return ret;
*ambient_new_raw = (int16_t)read_tmp;
ret = bsp_Mlx90632ReadWord(MLX90632_RAM_3(2), &read_tmp);
if(ret < 0)
return ret;
*ambient_old_raw = (int16_t)read_tmp;
return ret;
}
int32_t bsp_Mlx90632ReadTempObjectRaw(int32_t start_measurement_ret,
int16_t* object_new_raw, int16_t* object_old_raw)
{
int32_t ret;
uint16_t read_tmp;
int16_t read;
uint8_t channel, channel_old;
ret = bsp_Mlx90632ChannelNewSelect(start_measurement_ret, &channel, &channel_old);
if(ret != 0)
return -EINVAL;
ret = bsp_Mlx90632ReadWord(MLX90632_RAM_2(channel), &read_tmp);
if(ret < 0)
return ret;
read = (int16_t)read_tmp;
ret = bsp_Mlx90632ReadWord(MLX90632_RAM_1(channel), &read_tmp);
if(ret < 0)
return ret;
*object_new_raw = (read + (int16_t)read_tmp) / 2;
ret = bsp_Mlx90632ReadWord(MLX90632_RAM_2(channel_old), &read_tmp);
if(ret < 0)
return ret;
read = (int16_t)read_tmp;
ret = bsp_Mlx90632ReadWord(MLX90632_RAM_1(channel_old), &read_tmp);
if(ret < 0)
return ret;
*object_old_raw = (read + (int16_t)read_tmp) / 2;
return ret;
}
int32_t bsp_Mlx90632ReadTempRaw(int16_t* ambient_new_raw, int16_t* ambient_old_raw,
int16_t* object_new_raw, int16_t* object_old_raw)
{
int32_t ret, start_measurement_ret;
start_measurement_ret = bsp_Mlx90632StartMeasurement();
if(start_measurement_ret < 0)
return start_measurement_ret;
ret = bsp_Mlx90632ReadTempAmbientRaw(ambient_new_raw, ambient_old_raw);
if(ret < 0)
return ret;
ret = bsp_Mlx90632ReadTempObjectRaw(start_measurement_ret, object_new_raw, object_old_raw);
return ret;
}
double bsp_Mlx90632PreprocessTempAmbient(int16_t ambient_new_raw, int16_t ambient_old_raw, int16_t Gb)
{
double VR_Ta, kGb;
kGb = ((double)Gb) / 1024.0;
VR_Ta = ambient_old_raw + kGb * (ambient_new_raw / (MLX90632_REF_3));
return ((ambient_new_raw / (MLX90632_REF_3)) / VR_Ta) * 524288.0;
}
double bsp_Mlx90632PreprocessTempObject(int16_t object_new_raw, int16_t object_old_raw,
int16_t ambient_new_raw, int16_t ambient_old_raw,
int16_t Ka)
{
double VR_IR, kKa;
kKa = ((double)Ka) / 1024.0;
VR_IR = ambient_old_raw + kKa * (ambient_new_raw / (MLX90632_REF_3));
return ((((object_new_raw + object_old_raw) / 2) / (MLX90632_REF_12)) / VR_IR) * 524288.0;
}
double bsp_Mlx90632CalcTempAmbient(int16_t ambient_new_raw, int16_t ambient_old_raw, int32_t P_T,
int32_t P_R, int32_t P_G, int32_t P_O, int16_t Gb)
{
double Asub, Bsub, Ablock, Bblock, Cblock, AMB;
AMB = bsp_Mlx90632PreprocessTempAmbient(ambient_new_raw, ambient_old_raw, Gb);
Asub = ((double)P_T) / (double)17592186044416.0;
Bsub = (double)AMB - ((double)P_R / (double)256.0);
Ablock = Asub * (Bsub * Bsub);
Bblock = (Bsub / (double)P_G) * (double)1048576.0;
Cblock = (double)P_O / (double)256.0;
return Bblock + Ablock + Cblock;
}
static double bsp_Mlx90632CalcTempObjectIteration(double prev_object_temp, int32_t object, double TAdut,
int32_t Ga, int32_t Fa, int32_t Fb, int16_t Ha, int16_t Hb,
double emissivity)
{
double calcedGa, calcedGb, calcedFa, TAdut4, first_sqrt;
double KsTAtmp, Alpha_corr;
double Ha_customer, Hb_customer;
Ha_customer = Ha / ((double)16384.0);
Hb_customer = Hb / ((double)1024.0);
calcedGa = ((double)Ga * (prev_object_temp - 25)) / ((double)68719476736.0);
KsTAtmp = (double)Fb * (TAdut - 25);
calcedGb = KsTAtmp / ((double)68719476736.0);
Alpha_corr = (((double)(Fa * POW10)) * Ha_customer * (double)(1 + calcedGa + calcedGb)) /
((double)70368744177664.0);
calcedFa = object / (emissivity * (Alpha_corr / POW10));
TAdut4 = (TAdut + 273.15) * (TAdut + 273.15) * (TAdut + 273.15) * (TAdut + 273.15);
first_sqrt = sqrt(calcedFa + TAdut4);
return sqrt(first_sqrt) - 273.15 - Hb_customer;
}
void bsp_Mlx90632SetEmissivity(double value)
{
emissivity = value;
}
double bsp_mlx90632GetEmissivity(void)
{
if(emissivity == 0.0)
{
return 1.0;
}
else
{
return emissivity;
}
}
double bsp_Mlx90632CalcTempObject(int32_t object, int32_t ambient,
int32_t Ea, int32_t Eb, int32_t Ga, int32_t Fa, int32_t Fb,
int16_t Ha, int16_t Hb)
{
double kEa, kEb, TAdut;
double temp = 25.0;
double tmp_emi = bsp_mlx90632GetEmissivity();
int8_t i;
kEa = ((double)Ea) / ((double)65536.0);
kEb = ((double)Eb) / ((double)256.0);
TAdut = (((double)ambient) - kEb) / kEa + 25;
for(i = 0; i < 5; ++i)
{
temp = bsp_Mlx90632CalcTempObjectIteration(temp, object, TAdut, Ga, Fa, Fb, Ha, Hb, tmp_emi);
}
return temp;
}
#ifndef __BSP_MLX90632_H__
#define __BSP_MLX90632_H__
#include "stm32f10x.h"
#include "bsp_timer.h"
#define MLX90632_TEMP_READ_ERR_CODE -99
#ifndef ETIMEDOUT
#define ETIMEDOUT 110
#endif
#ifndef EINVAL
#define EINVAL 22
#endif
#ifndef EPROTONOSUPPORT
#define EPROTONOSUPPORT 93
#endif
typedef struct __mlx90632calibrationpar
{
int32_t PR;
int32_t PG;
int32_t PO;
int32_t PT;
int32_t Ea;
int32_t Eb;
int32_t Fa;
int32_t Fb;
int32_t Ga;
int16_t Gb;
int16_t Ha;
int16_t Hb;
int16_t Ka;
}stMlx90632CalibraParTypeDef;
#define MLX90632_ADDR 0x3A
#define MLX90632_ADDR_WR (MLX90632_ADDR << 1)
#define BITS_PER_LONG 32
#ifndef BIT
#define BIT(x) (1UL << (x))
#endif
#ifndef GENMASK
#ifndef BITS_PER_LONG
#warning "Using default BITS_PER_LONG value"
#define BITS_PER_LONG 64
#endif
#define GENMASK(h, l) \
(((~0UL) << (l)) & (~0UL >> (BITS_PER_LONG - 1 - (h))))
#endif
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
#endif
#define MLX90632_ADDR_RAM 0x4000
#define MLX90632_ADDR_EEPROM 0x2480
#define MLX90632_EE_CTRL 0x24d4
#define MLX90632_EE_CONTROL MLX90632_EE_CTRL
#define MLX90632_EE_I2C_ADDRESS 0x24d5
#define MLX90632_EE_VERSION 0x240b
#define MLX90632_EE_P_R 0x240c
#define MLX90632_EE_P_G 0x240e
#define MLX90632_EE_P_T 0x2410
#define MLX90632_EE_P_O 0x2412
#define MLX90632_EE_Aa 0x2414
#define MLX90632_EE_Ab 0x2416
#define MLX90632_EE_Ba 0x2418
#define MLX90632_EE_Bb 0x241a
#define MLX90632_EE_Ca 0x241c
#define MLX90632_EE_Cb 0x241e
#define MLX90632_EE_Da 0x2420
#define MLX90632_EE_Db 0x2422
#define MLX90632_EE_Ea 0x2424
#define MLX90632_EE_Eb 0x2426
#define MLX90632_EE_Fa 0x2428
#define MLX90632_EE_Fb 0x242a
#define MLX90632_EE_Ga 0x242c
#define MLX90632_EE_Gb 0x242e
#define MLX90632_EE_Ka 0x242f
#define MLX90632_EE_Ha 0x2481
#define MLX90632_EE_Hb 0x2482
#define MLX90632_REG_I2C_ADDR 0x3000
#define MLX90632_REG_CTRL 0x3001
#define MLX90632_CFG_SOC_SHIFT 3
#define MLX90632_CFG_SOC_MASK BIT(MLX90632_CFG_SOC_SHIFT)
#define MLX90632_CFG_PWR_MASK GENMASK(2, 1)
#define MLX90632_PWR_STATUS(ctrl_val) (ctrl_val << 1)
#define MLX90632_PWR_STATUS_HALT MLX90632_PWR_STATUS(0)
#define MLX90632_PWR_STATUS_SLEEP_STEP MLX90632_PWR_STATUS(1)
#define MLX90632_PWR_STATUS_STEP MLX90632_PWR_STATUS(2)
#define MLX90632_PWR_STATUS_CONTINUOUS MLX90632_PWR_STATUS(3)
#define MLX90632_REG_STATUS 0x3fff
#define MLX90632_STAT_BUSY BIT(10)
#define MLX90632_STAT_EE_BUSY BIT(9)
#define MLX90632_STAT_BRST BIT(8)
#define MLX90632_STAT_CYCLE_POS GENMASK(6, 2)
#define MLX90632_STAT_DATA_RDY BIT(0)
#define MLX90632_RAM_1(meas_num) (MLX90632_ADDR_RAM + 3 * meas_num)
#define MLX90632_RAM_2(meas_num) (MLX90632_ADDR_RAM + 3 * meas_num + 1)
#define MLX90632_RAM_3(meas_num) (MLX90632_ADDR_RAM + 3 * meas_num + 2)
#define MLX90632_TIMING_EEPROM 100
#define MLX90632_EEPROM_VERSION 0x105
#define MLX90632_EEPROM_WRITE_KEY 0x554C
#define MLX90632_RESET_CMD 0x0006
#define MLX90632_MAX_MEAS_NUM 31
#define MLX90632_EE_SEED 0x3f6d
#define MLX90632_REF_12 12.0
#define MLX90632_REF_3 12.0
int8_t bsp_Mlx90632Init(void);
int8_t bsp_Mlx90632ReadCalibraParFromEeprom(stMlx90632CalibraParTypeDef *pPar);
void bsp_Mlx90632ReadCalibraParInit(stMlx90632CalibraParTypeDef *pPar);
int bsp_Mlx90632StartMeasurement(void);
int32_t bsp_Mlx90632ChannelNewSelect(int32_t ret, uint8_t *channel_new, uint8_t *channel_old);
int32_t bsp_Mlx90632ReadTempAmbientRaw(int16_t *ambient_new_raw, int16_t *ambient_old_raw);
void bsp_Mlx90632SetEmissivity(double value);
double bsp_Mlx90632CalcTempObject(int32_t object, int32_t ambient,
int32_t Ea, int32_t Eb, int32_t Ga, int32_t Fa, int32_t Fb,
int16_t Ha, int16_t Hb);
double bsp_Mlx90632CalcTempAmbient(int16_t ambient_new_raw, int16_t ambient_old_raw, int32_t P_T,
int32_t P_R, int32_t P_G, int32_t P_O, int16_t Gb);
double bsp_Mlx90632PreprocessTempObject(int16_t object_new_raw, int16_t object_old_raw,
int16_t ambient_new_raw, int16_t ambient_old_raw,
int16_t Ka);
double bsp_Mlx90632PreprocessTempAmbient(int16_t ambient_new_raw, int16_t ambient_old_raw, int16_t Gb);
int32_t bsp_Mlx90632ReadTempRaw(int16_t *ambient_new_raw, int16_t *ambient_old_raw,
int16_t *object_new_raw, int16_t *object_old_raw);
extern stMlx90632CalibraParTypeDef stMlxCalibraPar;
#endif
#include "includes.h"
#include "app_var.h"
#include "bsp_mlx90632.h"
#define EXAMPLE_NAME "STM32F103XXX_MLX90632_Demo"
#define EXAMPLE_DATE "2022-05-02"
#define DEMO_VER "1.0.0"
double pre_ambient, pre_object, ambient, object;
stMlx90632CalibraParTypeDef stmlxCalibraPar = {0};
void app_SeggerRttInit(void);
static void app_ShowPowerOnInfo(void);
int main(void)
{
int16_t ambient_new_raw;
int16_t ambient_old_raw;
int16_t object_new_raw;
int16_t object_old_raw;
bsp_Init();
bsp_Mlx90632Init();
app_SeggerRttInit();
app_ShowPowerOnInfo();
bsp_StartAutoTimer( 0,1000 );
while(1)
{
bsp_Idle();
if(bsp_CheckTimer(0)) {
bsp_LedToggle(1);
bsp_Mlx90632ReadTempRaw(&ambient_new_raw, &ambient_old_raw, &object_new_raw, &object_old_raw);
pre_ambient = bsp_Mlx90632PreprocessTempAmbient(ambient_new_raw, ambient_old_raw, stMlxCalibraPar.Gb);
pre_object = bsp_Mlx90632PreprocessTempObject(object_new_raw, object_old_raw, ambient_new_raw, ambient_old_raw, stMlxCalibraPar.Ka);
bsp_Mlx90632SetEmissivity(1.0);
ambient = bsp_Mlx90632CalcTempAmbient(ambient_new_raw, ambient_old_raw, stMlxCalibraPar.PT, stMlxCalibraPar.PR, stMlxCalibraPar.PG, stMlxCalibraPar.PO, stMlxCalibraPar.Gb);
object = bsp_Mlx90632CalcTempObject(pre_object, pre_ambient, stMlxCalibraPar.Ea, stMlxCalibraPar.Eb, stMlxCalibraPar.Ga, stMlxCalibraPar.Fa, stMlxCalibraPar.Fb, stMlxCalibraPar.Ha, stMlxCalibraPar.Hb);
printf("MLX90632 Measure Object Temp:%f ℃,Ambient Temp:%f\n",object,ambient);
}
}
}
void app_SeggerRttInit(void)
{
SEGGER_RTT_ConfigUpBuffer(0, "RTTUP", NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
SEGGER_RTT_ConfigDownBuffer(0, "RTTDOWN", NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP);
}
static void app_ShowPowerOnInfo(void)
{
SEGGER_RTT_SetTerminal(0);
SEGGER_RTT_printf(0,"\n\r");
SEGGER_RTT_printf(0,"*************************************************************\n\r");
SEGGER_RTT_printf(0,"* 例程名称 : %s\r\n", EXAMPLE_NAME);
SEGGER_RTT_printf(0,"* 例程版本 : %s\r\n", DEMO_VER);
SEGGER_RTT_printf(0,"* 发布日期 : %s\r\n", EXAMPLE_DATE);
SEGGER_RTT_printf(0,"* 固件库版本 : V%d.%d.%d (STM32F10x_StdPeriph_Driver)\r\n", __STM32F10X_STDPERIPH_VERSION_MAIN,
__STM32F10X_STDPERIPH_VERSION_SUB1,__STM32F10X_STDPERIPH_VERSION_SUB2);
SEGGER_RTT_printf(0,"* \r\n");
SEGGER_RTT_printf(0,"* Email : wangyao@zhiyigroup.cn \r\n");
SEGGER_RTT_printf(0,"* 淘宝店: zhisheng.taobao.com\r\n");
SEGGER_RTT_printf(0,"* 技术支持QQ群 : 539041646 \r\n");
SEGGER_RTT_printf(0,"* Copyright www.zhiyigroup.cn 至一电子科技\r\n");
SEGGER_RTT_printf(0,"*************************************************************\n\r");
printf("\n\r");
printf("*************************************************************\n");
printf("* 例程名称 : %s\r\n", EXAMPLE_NAME);
printf("* 例程版本 : %s\r\n", DEMO_VER);
printf("* 发布日期 : %s\r\n", EXAMPLE_DATE);
printf("* --------------------------\r\n");
printf("* 接线方式 \r\n");
printf("* VCC ---- 3.3VDC~5VDC \r\n");
printf("* GND ---- GND \r\n");
printf("* SCL ---- PC4 \r\n");
printf("* SDA ---- PC5 \r\n");
printf("* 串口使用 UASRT1(PA9/PA10) \r\n");
printf("* --------------------------\r\n");
printf("* 固件库版本 : V%d.%d.%d (STM32F10x_StdPeriph_Driver)\r\n", __STM32F10X_STDPERIPH_VERSION_MAIN,
__STM32F10X_STDPERIPH_VERSION_SUB1,__STM32F10X_STDPERIPH_VERSION_SUB2);
printf("* \r\n");
printf("* Email : wangyao@zhiyigroup.cn \r\n");
printf("* 淘宝店: zhisheng.taobao.com\r\n");
printf("* 技术支持QQ群 : 539041646 \r\n");
printf("* Copyright www.zhiyigroup.cn 至一电子科技\r\n");
printf("*************************************************************\n\r");
}
完整的工程
STM32F1 使用标准库函数读取MLX90632非接触式温度传感器的完整工程可点击此处下载(有积分或者是会员的小伙伴可以支持一下!)
PS:鉴于积分实在有点糟心,所以我把工程上传到 Gitee|Github 上了,没有积分的小伙伴可以直接去下载
结束语
如果觉得文章对您有帮助,请关注、点赞,谢谢!
|