敏源M117温度传感器IIC驱动编写以及数据读取流程
提示:敏源M117遵循标准的IIC协议,上电后需要先配置寄存器为连续转换后方可读取,若上电之后直接进行单次读取,读取的数据均为0XFF,此点已经经过验证。且IIC地址存在读写位配置,故在发送地址时需要左移1位并或上读写位指令
一、写寄存器时序与验证程序
敏源传感器遵循标准IIC协议,上电后须发送寄存器配置命令,此例子为配置为一秒读取一次
此为敏源M117传感器配置寄存器说明
由手册可知,若需要配置传感器每秒转换一次需写指令0x5206后将寄存器值0x08写入,所以时序图如下:
睁大眼睛看清楚:敏源传感器M117的地址为0x44,但是发送出去之后是0x88,是因为在发送地址时将地址左移了1位,若不左移传感器不会产生ACK应答,因为是写,所以10001000最后一位是0,这点必须注意。
解释:0x88是寄存器地址,0x5206是写指令,后面0x08是需要配置的数据,看上面寄存器的图,配置寄存器每秒转换一次,0xFF是写指令的固定格式,后面的0x1A是CRC8的校验码,这个校验码需要注意,手册上有详细说明:
这个在计算时要注意不是固定格式的crc8,需要配置为:
计算出来是0x1A,每位写入都需要收到ACK应答,到此,写寄存器成功,下面贴出简单的测试程序,此程序为模拟IIC。
/*配置寄存器为一秒转换一次*/
StastI2c();
/*地址需要左移一位*/
SendByte((M117_I2C_ADDRESS << 1));
SendByte(WRITE_CONFIG >> 8);
/*发送写寄存器指令*/
SendByte((uint8_t)WRITE_CONFIG);
SendByte(CFG_MPS_1);
/*固定值*/
SendByte(0xFF);
/*CRC8校验码*/
SendByte(0x1A);
StopI2c();
二、读寄存器时序与验证程序
提示:会写就会读,按照手册指令一个一个来
按照标准手册将数据发送后读出来的寄存器配置为0x09,0x08,0x09对应为:
0x08对应为:
很明显,我们之前写入的0x08已经成功写入,此时,M117会每秒开始转换一次温度数据,我们只需要发送一次温度读取指令后就可以反复发送读字头即可一直读取温度数据。
下面贴上测试程序:
/*读寄存器配置*/
StastI2c();
/*地址左移1位写指令*/
SendByte((M117_I2C_ADDRESS << 1));
/*读取寄存器指令*/
SendByte(READ_STATUSCONFIG >> 8);
SendByte((uint8_t)READ_STATUSCONFIG);
StastI2c();
/*地址左移1位读指令*/
SendByte((M117_I2C_ADDRESS << 1) | 0x01);
/*读数据*/
ReviceByte();
/*应答*/
AskI2c(0);
ReviceByte();
AskI2c(0);
ReviceByte();
AskI2c(0);
/*IIC停止*/
StopI2c();
三、读温度数据与验证程序
发送温度传唤指令后即可持续读到数据,波形如下:
0x88为写指令,0xcc44为温度转换指令,0x89为地址或上读位(如果看不懂就可以回家种地了),0xF4和0xC6就是读取回来的温度数据,能看到0xC6后面是NAK而不是ACK是因为在读取到温度数据后还有CRC8校验,但是我不想读了所以直接返回无应答,手册上写着是可以这样干的:
下面贴上测试程序:
/*开始温度数据读取*/
StastI2c();
/*地址需要左移一位*/
SendByte((M117_I2C_ADDRESS << 1) | 0);
SendByte(CONVERT_T >> 8);
SendByte((uint8_t)CONVERT_T);
StopI2c();
睁大眼睛看清楚,上面的是在读取完寄存器配置后只需要发送一次的温度读取指令,只需要发送一次!
下面的是需要循环发送读取命令,需要发送地址或上读指令,也就是地址左移1为后|0x01,然后给M117提供时钟信号即可持续读到温度传感器数据。
/*
Name:M117Write
----------------------
Des: M117读数据
Ref:
Paras:
Author:zx
Date:2025年04月10日
*/
float M117ReadTemperature(void)
{
int16_t iTemp = 0;
uint8_t u8buf[2];
float ftemp = 0;
StastI2c();
SendByte((M117_I2C_ADDRESS << 1) | 0x01);
u8buf[0] = ReviceByte();
AskI2c(0);
u8buf[1] = ReviceByte();
AskI2c(1);
StopI2c();
iTemp = (u8buf[0] << 8) | u8buf[1];
ftemp = (float)iTemp / 256.0 + 40.0;
return ftemp;
}
将温度数据读取出来后因为温度数据是以二进制补码的形式进行存储,并且0x00表示为40℃,所以我们需要将数据/256.0并且加上40.0即为真实温度值。这个手册里面也有,如下:
技术细节
编写的时候要严格注意时序,因为M117对时序的高低电平持续时间以及温度转换时间都是有严格要求的。下面附图:
最后贴上实际测试的图:
小结
记录一下,毕竟费了好大的劲。
2025.04.11