原子哥 我这程序不够完美呀 连续发送命令 总是有读错和读不到的时候呀 【读电池BQ芯片数据的】 求原子哥给个完美的SMBUS模拟程序呀 ……
下面是我的程序
void Delay(void) //延时子程序
{
// unsigned char i;
// _nop_();
// i = 25;
// while (--i);
//
_nop_(); //约0.000001秒 1微秒
_nop_();
_nop_();
_nop_();
_nop_();
_nop_(); //约0.000001秒 1微秒
_nop_();
_nop_();
_nop_(); //约0.000001秒 1微秒
}
void SMBUS_Init()
{
SMBC=1;
SMBD=1;
}
void Star(void) //开始子程序 当SMBC为高电平时,SMBD上出现一个下降沿。该条件启动一次传输过程
{
SMBD=1;
Delay();
SMBC=1;
Delay();
SMBD=0;
Delay();
SMBC=0;
}
void Stop(void) //停止子程序 当SMBC为高电平时,SMBD上出现一个上升沿。该条件停止一次传输过程
{
SMBC=0;
Delay();
SMBD=0;
Delay();
SMBC=1;
Delay();
SMBD=1;
Delay();
}
u8 Ackw(void) //ACKNOWLEDGE写子程序 SMBC为高时,采样到SMBD为低电平
{
unsigned char a=0;
SMBC=0;
Delay();
SMBD=1;
Delay();
SMBC=1;
Delay();
while(SMBD)
{
a++;
ack=0;
/****
if(a==250) // 向串口发送EE,表示发送出错,未收到确认。利用串口助手可以看到
{
ADAPTER++;
if(ADAPTER==20)
{
ERROR=0xEE;
ADAPTER=0;
}
else
ERROR=0;
ack=1;
SelectUART_or_485(&SM_Error,1); //失败,则通过串口向PC发送一个字节0xEE
break;
}
****/
if(a==250) // 向串口发送EE,表示发送出错,未收到确认。利用串口助手可以看到
{
Stop();
SelectUART_or_485(&SM_Error,1); //失败,则通过串口向PC发送一个字节0xEE
return 1;
}
}
SMBC=0;
return 0;
}
void Ackr(void) //ACKNOWLEDGE读子程序 SMBC为高时,采样到SMBD为低电平
{
SMBC=0;
Delay();
SMBD=0;
Delay();
SMBC=1;
Delay();
SMBC=0;
}
void Nack(void) //NOT ACKNOWLEDGE子程序 SMBC为高电平时,采样到SMBD为高电平
{
SMBC=0;
Delay();
SMBD=1;
Delay();
SMBC=1;
Delay();
SMBC=0;
}
void Send(unsigned char b) //发送子程序 将b按从最高位到最低位的顺序,逐位的发送给bq2040
{
unsigned char i,x,y,z;
z=0x80;
for(i=1;i<9;i++)
{
x=b&z; // 读最高位数据
if(x==0)
y=0; //为 0就 y=0
else
y=1; //否则 y=1
SMBC=0;
Delay();
SMBD=y; //把一个位数据送入SMBus数据线
Delay();
SMBC=1;
Delay();
z>>=1; //把高位的1右移一位
//SMBC=0;//每次读完或写完都把时钟端拉低
}
}
unsigned char Receive(void) //接收子程序 将bq2040中的数据逐位的读出
{
unsigned char i,g=0x00;
for(i=1;i<9;i++)
{
SMBC=0;
Delay();
SMBD=1;
Delay();
SMBC=1;
Delay();
g<<=1; //g左移一位
if(SMBD) //如果SMBD==1,g++
{ g++;
}
}
Ackr(); //接收确认
//SMBC=0;//每次读完或写完都把时钟端拉低
return g; //8次循环后g=0xFF
}
/****
u8 Read_Byte(unsigned char Command) //
{
u8 TempByte;
Star(); //开始
Send(BQ_AddrW); //发送器件地址0x16 00010110
Ackw(); //发送确认
Send(Command); //发送读剩余电量指令
Ackw(); //发送确认
Star();
Send(BQ_AddrR);
Ackw(); //发送确认
TempByte=Receive(); //接收剩余电量低8位数据 调用Receive();返回值就是 0xFF
Ackr(); //接收确认
Nack(); //非确认
Stop(); //结束
return TempByte;
}
****/
void Read_Word(unsigned char Command) //
{
Star(); //开始
Send(BQ_AddrW); //发送器件地址0x16 00010110
Ackw(); //发送确认
Send(Command); //发送读剩余电量指令
Ackw(); //发送确认
Star();
Send(BQ_AddrR);
Ackw(); //发送确认
ReceiveData_L=Receive(); //接收剩余电量低8位数据 调用Receive();返回值就是 0xFF
Ackr(); //接收确认
ReceiveData_H=Receive(); //接收剩余电量高8位数据 调用Receive();返回值就是 0xFF
Ackr();
Nack(); //非确认
Stop(); //结束
}
/****
void Read_Block(u8 Command,u8 *pBuffer)
{
u8 tempReadCount=0;
Star(); //开始
Send(BQ_AddrW); //发送器件地址0x16 00010110
Ackw(); //发送确认
if(ack) //未确认则重新发送
return;
Send(Command); //发送要读取的块指令
Ackw(); //发送确认
if(ack) //未确认则重新发送
return; //遇到return函数就返回
Star();
Send(BQ_AddrR);
Ackw(); //发送确认
if(ack) //未确认则重新发送
return;
SMB_ReadCount=Receive();//首先,接收从机向主机发送的读取字节数量
Ackr(); //接收确认
tempReadCount=SMB_ReadCount;
while(tempReadCount)
{
*pBuffer++=Receive();
Ackr();
tempReadCount--;
}
Nack(); //非确认
Stop(); //结束
}
****/
//读块
void Read_Block(u8 Command,u8 *pBuffer)
{
u8 tempReadCount=0;
u8 tempReceiveByteData=0;
//u8 xdata ReceiveArray[32];
Star(); //开始
Send(BQ_AddrW); //发送器件地址0x16 00010110
Ackw(); //发送确认
Send(Command); //发送要读取的块指令
Ackw(); //发送确认
Star();
Send(BQ_AddrR);
Ackw(); //发送确认
tempReadCount=Receive();//首先,接收从机向主机发送的读取字节数量
if(tempReadCount>0x20) tempReadCount=0; //大于16进制20 即十进制32个 元素 就清为零
SMB_ReadCount=tempReadCount; //接收确认了,再赋值
while(tempReadCount)
{
//*pBuffer++=Read_Byte(Command++);
tempReceiveByteData=Receive();
//Ackr();
*pBuffer++=tempReceiveByteData;
tempReadCount--;
}
// while(tempReadCount)
// {
//
// tempReceiveByteArray[i]=Receive();
// Ackr();
// i++;
//
// }
// pBuffer=(u8 *)&tempReceiveByteArray[0];
Nack(); //非确认
Stop(); //结束
}
/****
void Write_Byte(unsigned char Command,unsigned char WriteByte)
{
Star(); //开始
Send(BQ_AddrW); //发送器件地址0x16 00010110
Ackw(); //发送确认
if(ack) //未确认则重新发送
return;
Send(Command); //发送读剩余电量指令
Ackw(); //发送确认
if(ack) //未确认则重新发送
return; //遇到return函数就返回
Send(WriteByte); //发送读剩余电量指令
Ackw(); //发送确认
if(ack) //未确认则重新发送
return; //遇到return函数就返回
Stop(); //结束
}
****/
void Write_Word(u8 Command,u16 WriteWord)
{
unsigned char WrLowByte,WrHighByte;
Star(); //开始
Send(BQ_AddrW); //发送器件地址0x16 00010110
Ackw(); //发送确认
Send(Command); //发送要读取的块指令
Ackw(); //发送确认
WrLowByte=WriteWord&0xff; //取要写字的低字节
WrHighByte=(WriteWord&0xff00)>>8; //取要写字的高字节
Send(WrLowByte);
Ackw(); //发送确认
Send(WrHighByte);
Ackw(); //发送确认
Stop(); //结束
}
void Write_Block(unsigned char Command,unsigned char WriteNum,unsigned char *p_WrBlock)
{
unsigned char i=0;
Star(); //开始
Send(BQ_AddrW); //发送器件地址0x16 00010110
Ackw(); //发送确认
Send(Command); //发送要读取的块指令
Ackw(); //发送确认
Send(WriteNum); //发送要写入的字节数量
Ackw(); //发送确认
while(WriteNum--)
{
Send(p_WrBlock[i]); //从第4个字节开始发送数据 WriteNum个
Ackw(); //发送确认
i++;
}
Stop(); //结束
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
普通IO口模拟SMBUS的通信程序有吗 ? 自己写的总是不完美
一周热门 更多>