1 理论介绍
1.1 引言
一般来说,测温方式可分为接触式和非接触式,接触式测温只能测量被测物体与测温传感器达到热平衡后的温度,所以响应时间长,且极易受环境温度的影响;而红外测温是根据被测物体的红外辐射能量来确定物体的温度,不与被测物体接触,具有影响动被测物体温度分布场,温度分辨率高、响应速度快、测温范围广、不受测温上限的限制、稳定性好等特点,近年来在家庭自动化、汽车电子、航空和军事上得到越来越广泛的应用。
本文以MLX90614DDA为例介绍其原理和应用。
MLX90614 系列模块是一组通用的红外测温模块。 在出厂前该模块已进行校验及线性化,具有非接触、体积小、精度高,成本低等优点。被测目标温度和环境温度能通过单通道输出,并有两种输出接口,适合于汽车空调、室内暖气、家用电器、手持设备以及医疗设备应用等。
1.2 测温原理
物体红外辐射能量的大小和波长的分布与其表面温度关系密切。因此,通过对物体自身红外辐射的测量,能准确地确定其表面温度,红外测温就是利用这一原理测量温度的。红外测温器由光学系统、光电探测器、信号放大器和信号处理及输出等部分组成。 光学系统汇聚其视场内的目标红外辐射能量,视场的大小由测温仪的光学零件及其位置确定。红外能量聚焦在光电探测器上并转变为相应的电信号。该信号经过放大器和信号处理电路,并按照仪器内的算法和目标发射率校正后转变为被测目标的温度值。
PWM 的全称是 Pulse Width Modulation(脉冲宽度调制)即通过调节脉冲的周期、宽度,以达到变压、变频的目的,数字式脉宽调制方式中,数字是控制信号,通过改变高低电平数的比值达到改变占空比的目的, PWM 控制电路在开关稳压电源、不间断电源( UPS)以及直流电机调速,交流电机变频调速等控制电路中有着广泛应用。
SMBus ( System Management Bus,)是 1995 年由 intel 公司提出的一种高效同步串行总线,SMBus 只有两根信号线:双向数据线和时钟信号线,容许 CPU 与各种外围接口器件以串行方式进行通信、交换信息,即可以提高传输速度也可以减小器件的资源占用,另外即使在没有SMBus 接口的单片机上也可利用软件进行模拟。
Melexis 公司生产的 MLX90614 系列测温模块是应用非常方便的红外测温装置,其所有的模块都在出厂前进行了校验,并且可以直接输出线性或准线性信号,具有很好的互换性,免去了复杂的校正过程。
该模块以 81101 热电元件作为红外感应部分。输出是被测物体温度( TO)与传感器自身温度( Ta)共同作用的结果,理想情况下热电元件的输出电压为:
Vir = A(To4 – Ta4)
其中温度单位均为 Kelvin, A 为元件的灵敏度常数。
目标温度和环境温度由 81101 内置的热电偶测定测量,从 81101 中输出的两路温度信号分别经内部 MLX90302 器件上高性能、低噪声的斩波稳态放大器放大再经一个 17-bit 的模数转换器( ADC)和强大的数字信号处理(DSP)单元后输出。
该系列模块的温度解析度可达 0.01°C,体积小巧,被测目标和环境温度能通过单通道(由 MLX90302 内的状态机控制)输出,有两种输出方式: PWM 输出、可编程 SMBus 输出,适于多种应用环境,下面以 MLX90614 为例,重点介绍其特性和使用方法。
通过 SMBus 编程可以更改模块 EEPROM 内的预设值并按照应用要求进行配置,并可以读出 EEPROM 内的配置信息;还可以读出模块 RAM 内温度等数据。
MLX90614 有适用于 3 伏和 5 伏电源操作的两种类型。由于 3 伏型其小于 2 毫安的电流消耗,它非常适用于手提装置和电池动力装置。为此,传感器也具有一个节能“休眠”模式,此时电流消耗可低于 2 毫安。对于 12 伏汽车电池直接供电的情况, 5 伏型包含的电子部件可与几个外部元件一起在较高电压下运行。
1.3 MLX90614 协议
1.3.1 MLX90614 的 SMBus 协议
MLX90614 的 SMBus 协议如下:

Figure SMBus 的数据包组成
1.3.2 读器件
读器件命令决定是读 RAM 或 EEPROM)数据格式。

Figure 读器件命令
1.3.3 写器件
写器件命令决定是写 RAM 或 EEPROM)数据格式。

Figure 写器件命令
1.3.4 数据传输时序
数据传输时序如下:

Figure 数据传输时序
PWM/SDA 上的数据在 SCL 变为低电平 300n 后即可改变,数据在 SCL 的上升沿被捕获。 16 位数据分两次传输,每次传一个字节。每个字节都是按照高位(MSB)在前,低位(LSB)在后的格式传输,两个字节中间的第九个时钟是应答时钟。
1.4 MCU接口电路
MLX90614AAA 与单片机连接的硬件电路如下图所示。 SCL、 PWM/SDA 管脚直接连接MCU 的普通 I/O 口即可,由于 MLX90614AAA 的输入输出接口是漏级开路( OD)结构,需要加上拉电阻。多个 MLX90614 可以用于一个系统中,每个 MLX90614 对应一个不同地址,通过地址的不同而访问不同的 MLX90614,最多可以达到 127 个。

Figure MLX90614DDA 与MCU连接电路
1.5 软件流程图
多个 MLX90614 可以用于一个系统中,通过地址不同区分器件,器件默认的地址为 5AH,因此在多 MLX90614 系统中,需要给每个 MLX90614 分配一个不同的地址,在只有一个MLX90614 的系统中, MLX90614 识别地址 00h,即在单个 MLX90614 系统中,可以使用该地址访问它。

Figure 读写数据流程
发送和接收数据是以字节为单位进行的,程序流程如下图所示。每次发送一个字节(按位发送,发送 8 个位就是一个字节),然后就判断对方是否有应答,如果有应答,就接着发送下一个字节;如果没有应答,多次重发该字节,直到有应答,就接着发送下一个字节,如果多次重发后,仍然没有应答,就结束。接收数据时,每次接收一个字节(按位接收,接收 8 个位就是一个字节),然后向对方发送一个应答信号,然后就可以继续接收下一个字节。

Figure 发送和接收字节流程图
从MLX90614 种读出的数据是 16 位的,由高 8 位( DataH)和低 8 位( DataL)两部分组成,其中RAM地址 07H单元存储的是TOBJ1数据,数据范围从 0x27AD到 0x7FFF,表示的温度范围是-70.01℃到+382.19℃。
从 MLX90614 中读出的数据(DataH:DataL)换算为温度数据(T,单位为℃ )如下所示:
T= (DataH:DataL)*0.02-273.15
例如: DataH:DataL=0x27AD,代入式中 T=-70.01℃
2 实验详解
2.1 实验目的
1) 通过实验掌握RA-Eco-RA4M2芯片I2C 的配置方法
2) 掌握温度传感器MLX90614的原理与使用
2.2 实验设备
硬件:PC 机一台;RA-Eco-RA4M2开发板一套;MLX90614一个
软件:Windows 10系统,Keil5集成开发环境、串口助手
2.3 硬件连接
MLX90614接口电路如下:

Figure MLX90614接口电路
MLX90614接到RA4M2的IIC0,SCL和SDA分别接的是P400和P401引脚。

Figure RA4M2的IIC0接口
2.4 MLX90614数据读取
2.4.1 RA Smart Configurator配置I2C
打开RA Smart Configurator,根据硬件连接,I2C使用的是IIC0,因此在配置界面里面依次打开“Pins->Peripherals->Connectivity:IIC>IIC0”配置IIC模块,选择开发板所用的IIC引脚,这里SCL和SDA分别接的是P400和P401引脚。

Figure I2C引脚设置
接下来就是添加I2C的stack。

Figure 添加I2C的stack步骤
接下来需要配置I2C的参数。

Figure I2C参数设置
这里可以设置I2C的参数,我这里设置I2C的变量名、通道以及从机地址,I2C的编号和Channel编号是一一对应的,因此需要设置为3,回调函数依据C语言命名规范任意编译一个就行。
值得注意的是,这里的从机地址是7位,代码中自动左移了。
然后让软件自动生成配置代码即可。
2.4.2 MLX90614采集温度代码实现
R_IIC_MASTER_Open()函数为执行IIC初始化,开启配置如下所示。
err =R_IIC_MASTER_Open(&g_i2c_master0_ctrl, &g_i2c_master0_cfg);
assert(FSP_SUCCESS == err);
R_IIC_MASTER_Write()函数是向IIC设备中写入数据,写入格式如下所示。
err = R_IIC_MASTER_Write(&g_i2c_device_ctrl_1, &g_i2c_tx_buffer[0], I2C_BUFFER_SIZE_BYTES, false);
assert(FSP_SUCCESS == err);
R_IIC_MASTER_Read()函数是向IIC设备中读数据,读数据的格式如下所示。
err = R_IIC_MASTER_Read(&g_i2c_device_ctrl_1, &g_i2c_rx_buffer[0], I2C_BUFFER_SIZE_BYTES, false);
assert(FSP_SUCCESS == err);
在前文已经介绍了MLX90614的时序,接下来通过RA4M2来读取温度值。
void BSP_MLX90614_Init(i2c_master_ctrl_t * const p_api_ctrl, i2c_master_cfg_t const * const p_cfg)
{
fsp_err_t err;
err = R_IIC_MASTER_Open(p_api_ctrl, p_cfg);
assert(FSP_SUCCESS == err);
}
int8_t BSP_MLX90614_ReadReg(i2c_master_ctrl_t * const p_api_ctrl, uint8_t regAddr, uint16_t *pReadData)
{
uint8_t writeBuf[1] = {0};
uint8_t readBuf[3] = {0};
uint8_t ValBuf[6] = {0};
uint8_t prcRegVal = 0;
ValBuf[0] = MLX90614_ADDR << 1;
ValBuf[1] = (uint8_t)(regAddr);
ValBuf[2] = (MLX90614_ADDR << 1) | 0x01;
fsp_err_t err;
writeBuf[0] = (uint8_t)(regAddr);
err = R_IIC_MASTER_Write(p_api_ctrl, writeBuf, 1, true);
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MILLISECONDS);
err = R_IIC_MASTER_Read(p_api_ctrl, readBuf, 3 , false);
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MILLISECONDS);
err = R_IIC_MASTER_Write(p_api_ctrl, writeBuf, 1, true);
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MILLISECONDS);
err = R_IIC_MASTER_Read(p_api_ctrl, readBuf, 3 , false);
if (err != FSP_SUCCESS)
{
return -1;
}
else
{
ValBuf[3] = readBuf[0];
ValBuf[4] = readBuf[1];
ValBuf[5] = readBuf[2];
prcRegVal = CRC8_Calc(ValBuf, 5);
if(prcRegVal == ValBuf[5])
{
*pReadData = (uint16_t)((readBuf[1] << 8) + readBuf[0]);
}
}
return 0;
}
float BSP_MLX90614_ReadTemp(i2c_master_ctrl_t * const p_api_ctrl)
{
float temp;
uint16_t data;
if( 0 == BSP_MLX90614_ReadReg(p_api_ctrl, MLX90614_TOBJ1, &data))
{
temp = (float)(data * 0.02f - 273.15f);
}
else
{
temp = MLX90614_TEMP_READ_ERR_CODE;
}
return temp;
}
最后看下hal_entry函数。
/*******************************************************************************************************************//**
* main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used. This function
* is called by main() when no RTOS is used.
**********************************************************************************************************************/
void hal_entry(void)
{
float fTemperature = 0;
/* TODO: add your own code here */
SysTick_Init(); //初始化系统时钟
R_SCI_UART_Open (g_uart9.p_ctrl, g_uart9.p_cfg);
// init mlx90614
BSP_MLX90614_Init(&g_i2c_master0_ctrl, &g_i2c_master0_cfg);
while(1)
{
Delay_ms(500);
R_IOPORT_PinWrite(&g_ioport_ctrl, GPIO_LED1, BSP_IO_LEVEL_HIGH);
Delay_ms(500);
R_IOPORT_PinWrite(&g_ioport_ctrl, GPIO_LED1, BSP_IO_LEVEL_LOW);
fTemperature = BSP_MLX90614_ReadTemp(&g_i2c_master0_ctrl);
if(MLX90614_TEMP_READ_ERR_CODE != fTemperature)
{
printf("MLX90614 Measure Temp: %f ℃\r\n",fTemperature);
}
else
{
printf("MLX90614 Measure Temp Error!\r\n");
}
}
#if BSP_TZ_SECURE_BUILD
/* Enter non-secure code */
R_BSP_NonSecureEnter();
#endif
}
2.5 实验现象
连接设备,打开串口助手,如下图所示。
