MCU和BQ40Z50采用IO模拟SMBS方式,进行通讯,访问RelativeStateOfCharge ()信息,发现返回的数据全是0xffff
代码如下
#define I2CDLY 10
#define I2C_WRADD 0x16
#define I2C_RDADD 0x17
void delayus(u16 us)
{
for(u16 i=0;i<us;i++)
{
for(u8 j=0;j<100;j++);
}
}
void I2C_Start()
{
SET_SDAOut(); //设置SDA为输出
SDA_H();
delayus(I2CDLY);
SCL_H();
delayus(I2CDLY);
SDA_L();
delayus(I2CDLY);
}
void I2C_Stop()
{
SET_SDAOut();
SDA_L();
delayus(I2CDLY);
SCL_H();
delayus(I2CDLY);
SDA_H();
delayus(I2CDLY);
}
//主设备设置Nak信号,表示在接受数据时,主接收到数据Ng
void I2C_SetNak()
{
SET_SDAOut();
SCL_L();
delayus(I2CDLY);
SDA_H();
delayus(I2CDLY);
SCL_H();
delayus(I2CDLY);
}
//主设备设置Nak信号,表示在接受数据时,主接收到数据Ng
void I2C_SetAck()
{
SET_SDAOut();
SCL_L();
delayus(I2CDLY);
SDA_H();
delayus(I2CDLY);
SCL_H();
delayus(I2CDLY);
}
//返回0,表示异常,返回1表示正常,=0,Nak,=1 ACK
u8 I2C_GetAck()
{
u8 status = 0;
SET_SDAIn(); ////设置SDA为输入,主机释放总线,
delayus(I2CDLY);
SCL_L();
delayus(I2CDLY);
SCL_H();
if(SDA_InR==0) status=1; //从设备接受到数据后,返回Ack信号,表示接受数据OK
else status=0; //当返回数据为高时,或从设备未返回数据,则表示从设备接受数据NG
delayus(I2CDLY);
return(status);
}
void I2C_SendByte(u8 send_data)
{
SET_SDAOut();
for(u8 i=0;i<8;i++)
{
SCL_L();
delayus(I2CDLY);
if((send_data<<i)&0x80) SDA_H();
else SDA_L();
delayus(I2CDLY);
SCL_H();
delayus(I2CDLY);
}
SCL_L();
}
void I2C_GetByte(u8 *get_data)
{
u8 i2cdata=0;
SET_SDAIn(); //主机释放总线,
for(u8 i=0;i<8;i++)
{
delayus(I2CDLY);
SCL_L();
delayus(I2CDLY);
SCL_H();
delayus(I2CDLY);
i2cdata<<=1;
if(SDA_InR) i2cdata +=1;
}
*get_data = i2cdata;
}
void BatterI2CInit()
{
//以下采用IO口模拟I2C
SET_SCLOut(); //slk out
SET_SDAOut(); //SDA out
SDA_H(); //SDA设置为H
SCL_H(); //SCL设置为H
}
/*******************************************************************************
//returns the predicted remaining battery capacity as a percentage.
//读取相对剩余电量百分比%
*******************************************************************************/
u16 RelativeStateOfCharge()
{
u8 tempdata[2];
u16 relativecharge=0;
I2C_Start();
I2C_SendByte(I2C_WRADD);
I2C_GetAck();
I2C_SendByte(SBSCMD_GET_RL_CHARGE);
I2C_GetAck();
I2C_Start();
I2C_SendByte(I2C_RDADD);
I2C_GetAck();
I2C_GetByte(&tempdata[0]);
I2C_SetAck();
I2C_GetByte(&tempdata[1]);
I2C_SetNak();
I2C_Stop();
relativecharge = tempdata[0];
relativecharge = (relativecharge<<8)+tempdata[1];
return(relativecharge);
}