MLX90621驱动编写1
- MLX90621为迈来芯厂家的温度传感器,该器件能够进行生成16*4的温度矩阵。其通信方式采用I2C通信。该器件的驱动编写主要是从内部取到的温度数据需要经过多次补偿后才能得到测量的实际的物体温度。故需要根据芯片手册来编写相应地函数来实现MLX90621器件的使用。该器件的驱动编写可以按照以下步骤进行编写:1,最底层的I2C驱动;2 利用I2C来编写对MLX90621的读数据,写数据函数;3,利用编写好的读写函数来编写对MLX90621的操作函数,包括配置函数,读取配置函数,读取RAM函数,读取EEPROM函数等操作函数;4 利用操作函数完成对MLX90621的使用。其他类型的传感器的软件驱动也可以采用这种步骤来对其进行操作。下面进行具体讲解。
1 底层I2C驱动,该部分采用软件模拟的方式来实现。主要包括起始信号,停止信号,读写函数,应答信号和NACK信号。
2 利用I2C来编写对MLX90621的读写数据。图1为MLX90621的写时序图。从时序图可以看出,写入时的数据包括从机地址,写入命令,校验数据和要写入的数据。因此MLX90621的写函数可以如下:
/*Description :MLX90621利用I2C总线写数据
*Param :u8 slaveAddr :地址
:u8 command:命令
:u8 checkvalue:校验数据
:u16 data:要写入的数据
*Return Code :None
*/
int MLX90621_I2CWrite(u8 slaveAddr,u8 command,u8 checkValue,u16 data)
{
u8 i;
u8 sa;
u8 cmd[5]={0,0,0,0,0}; //写入的命令
static u16 dataCheck; //检查数据,检查写入的数据
sa=(slaveAddr<<1); //写入的地址
cmd[0]=command; //要操作的地址
cmd[2] = data & 0x00FF; //低8位
cmd[1] = cmd[2] - checkValue; //低8位减去checkValue
cmd[4] = data >> 8; //高8位
cmd[3] = cmd[4] - checkValue; //高8位减去checkValue
IIC_Start(); //起始信号
IIC_Send_Byte(sa); //发送地址
IIC_Wait_Ack(); //等待ACK
for(i=0;i<5;i++)
{
IIC_Send_Byte(cmd[i]); //发送数据
IIC_Wait_Ack(); //等待ACK
}
IIC_Stop(); //停止信号
MLX90621_I2CRead(slaveAddr,0x02,0X8F+command,0,1,&dataCheck); //将写入的数据读出来
if(dataCheck!=data) //对数据进行校验
{
return -2;
}
return 0;
}
图1 写时序图
在读函数方面为了方便读写RAM和读写EEPROM这里将读RAM和EEPROM分开来操作,读EEPROM的时序图如图2所示,读RAM时序图如图3所示。因此读EEPROM函数如下
/*Description :MLX90621利用I2C总线读取EEPROM数据
*Param :u8 slaveAddr :地址
:u8 startAddress:起始地址
:u16 nMemAddressRead:读取的个数
:u8 *data:存储数据的指针
*Return Code :None
*/
int MLX90621_I2CReadEEPROM(u8 slaveAddr, u8 startAddress, u16 nMemAddressRead, u8 *data)
{
u8 sa;
int cnt=0;
u8 cmd=0;
u8 i2cData[256]={0}; //EEPROM为256个字节
sa = (slaveAddr << 1); //地址偏移
cmd = startAddress; //起始地址
IIC_Start(); //启动信号
IIC_Send_Byte(sa); //发送地址
IIC_Wait_Ack(); //等待回应
IIC_Send_Byte(cmd); //发送起始地址
IIC_Wait_Ack(); //等待回应
//IIC_RepeatedStart(); //重新启动
IIC_Start();
sa=sa|0X01;
IIC_Send_Byte(sa); //发送读命令
IIC_Wait_Ack(); //等待ACK
IIC_ReadBytes(nMemAddressRead,i2cData); //读取数据
IIC_Stop(); //停止信号
for(cnt=0;cnt<nMemAddressRead;cnt++)
{
*data++=i2cData[cnt]; //转移数据
}
return 0;
}
读取RAM的函数如下
/*Description :MLX90621利用I2C总线读取数据
*Param :u8 slaveAddr :地址
:u8 command:命令
:u8 startAddress:起始地址
:u8 addressStep:读取的步长
:u8 nMemAddressRead:读取的个数
:u16 *data:存储数据的指针
*Return Code :None
*/
int MLX90621_I2CRead(u8 slaveAddr, u8 command, u8 startAddress, u8 addressStep, u8 nMemAddressRead, u16 *data)
{
u8 sa;
int cnt=0;
int i=0;
u8 cmd[4]={0,0,0,0};
u8 i2cData[132]={0};
sa=(slaveAddr<<1);
cmd[0] = command;
cmd[1] = startAddress;
cmd[2] = addressStep;
cmd[3] = nMemAddressRead;
IIC_Start(); //起始信号
IIC_Send_Byte(sa); //发送地址
IIC_Wait_Ack(); //等待ACK
for(i=0;i<4;i++)
{
IIC_Send_Byte(cmd[i]); //发送数据
IIC_Wait_Ack(); //等待ACK
}
//IIC_RepeatedStart(); //重新启动
IIC_Start();
sa = sa | 0x01; //读命令
IIC_Send_Byte(sa); //发送出去
IIC_Wait_Ack(); //等待ACK
IIC_ReadBytes((nMemAddressRead << 1), i2cData);//读取数据
IIC_Stop(); //结束后发送停止信号
for(cnt=0; cnt < nMemAddressRead; cnt++)
{
i = cnt << 1;
*data++ = (u16)i2cData[i+1]*256 + (u16)i2cData[i]; //接收的时候先接收低位,再高位
}
return 0;
}
图2 读取EEPROM时序图
图3 读取RAM时序图
3. 编写对MLX90621的操作函数。操作函数如下
/*Description :进行配置,读取EEPROM的值后,直接进行配置
*Param :u8 *eeData 从eeprom数据中读取
*Return Code :None
*/
int MLX90621_Configure(u8 *eeData)
{
int error = 1;
uint16_t value;
error = MLX90621_I2CWrite(0x60, 0x04, 0xAA, eeData[247]); //写入振荡器微调值
if (error != 0)
{
return error;
}
value = 256*eeData[246] + eeData[245];
value = value | 0x0400;
error = MLX90621_I2CWrite(0x60, 0x03, 0x55, value); //写入配置值
return error;
}
/*Description :设置分辨率
*Param :u8 resolution 分辨率
:0x00 15 resolution
:0x01 16 resolution
:0x02 17 resolution
:0x03 18 resolution
*Return Code :None
*/
int MLX90621_SetResolution(u8 resolution)
{
u16 cfgReg;
u16 value;
u16 error;
value = (resolution & 0x03) << 4;
error = MLX90621_GetConfiguration(&cfgReg);
if(error == 0)
{
value = (cfgReg & 0xFFCF) | value;
error = MLX90621_I2CWrite(0x60, 0x03, 0x55, value);
}
return error;
}
int MLX90621_SetRefreshRate(u8 refreshRate)
{
u16 cfgReg;
u16 value;
u16 error;
value =(refreshRate & 0x0F);
error = MLX90621_GetConfiguration(&cfgReg);
if(error == 0)
{
value = (cfgReg & 0xFFF0) | value;
error = MLX90621_I2CWrite(0x60, 0x03, 0x55, value);
}
return error;
}
4 该器件比较复杂的部分是各种补偿值函数的编写,补偿函数见第二部分