Other Parts Discussed in Thread: BQ40Z50, EV2400
SMBus通信采用IO推挽输出模拟时序方式进行设计,但出现同样的两块板子一块读的很稳定一块完全不能读,但采用IT的通信盒都可以读取。数据读取过程的ACK都有回复,但是最后的数据都读到0,CRC校验不过,是不是时序有问题?希望大家帮忙看看
void SMB_Start(void)
{
SMB_SDA_OUT();
SMB_SDA = 1;
SMB_SCL = 1;
delay_us(20);
SMB_SDA = 0;
delay_us(20);
SMB_SCL = 0;
}
/**
@breif SMB 停止信号
*/
void SMB_Stop(void)
{
SMB_SDA_OUT();
SMB_SCL = 0;
SMB_SDA = 0;
delay_us(20);
SMB_SDA = 1;
delay_us(5);
SMB_SCL = 1;
delay_us(20);
}
/**
@breif SMB接收应答
*/
int SMB_Wait_Ack(void)
{
uint16_t u16tmptime = 0;
SMB_SDA = 1;
SMB_SCL = 0;
SMB_SDA_IN();
delay_us(35);
SMB_SCL = 1;
delay_us(5);
while(SMB_READ_SDA) // 0应答位
{
u16tmptime ++;
if(u16tmptime > 2500)
{
SMB_Stop();
printf("SMB SDA low timeout \r\n");
return -1;
}
}
delay_us(10);
return 0;
}
/**
@breif SMB发送应答
*/
void SMB_ACK(uint8_t ack)
{
SMB_SDA_OUT();
SMB_SCL = 0;
if(ack) // 应答
{
SMB_SDA = 0;
}
else
{
SMB_SDA = 1;
}
delay_us(25);
SMB_SCL = 0;
delay_us(7);
SMB_SCL = 1;
delay_us(25);
SMB_SCL = 0;
delay_us(10);
}
/**
@breif 写字节数据
*/
void SMB_HostWriteByte(uint8_t dat)
{
uint8_t i = 0;
delay_us(5);
SMB_SCL = 0;
SMB_SDA_OUT();
for(i=0;i<8;i++)
{
if(dat & 0x80)
{
SMB_SDA = 1;
}
else
{
SMB_SDA = 0;
}
dat <<= 1;
delay_us(25);
SMB_SCL = 1;
delay_us(25);
SMB_SCL = 0;
delay_us(5);
}
}
/**
@breif 读字节数据
*/
uint8_t SMB_HostReadByte(uint8_t u8ack)
{
unsigned char i=0,dat = 0;
SMB_SDA_IN();
SMB_SCL = 0;
delay_us(50);
for(i=0;i<8;i++)
{
SMB_SCL = 0;
delay_us(20);
dat <<= 1;
SMB_SCL = 1;
delay_us(20);
if(SMB_READ_SDA == 1)
dat |= 0x01;
SMB_SCL = 0;
delay_us(5);
}
if(u8ack)
SMB_ACK(1);
else
SMB_ACK(0);
return dat;
}
/**
@breif 完整读一个字节数据
*/
uint8_t SMB_HostRead(uint8_t u8SMB_Address ,uint8_t u8regAddr)
{
uint8_t temp = 0;
int itimeout = 0;
delay_ms(10);
SMB_Start();
SMB_HostWriteByte(u8SMB_Address);
itimeout = SMB_Wait_Ack();
if(itimeout == -1)
{
printf("SMB read time out");
return 0;
}
SMB_HostWriteByte(u8regAddr);
itimeout = SMB_Wait_Ack();
if(itimeout == -1)
{
printf("SMB read time out");
return 0;
}
SMB_Start();
SMB_HostWriteByte(u8SMB_Address + 1);
itimeout = SMB_Wait_Ack();
if(itimeout == -1)
{
printf("SMB read time out");
return 0;
}
temp = SMB_HostReadByte(0);
SMB_Stop();
return temp;
}