ARDUINO和bq3060的通信
前言
手头的一台平板式笔记本的电池因为充电口松动接触不良造成容量严重亏损,开后盖看到智能电池内部使用的是ti的bq3060电池管理芯片,上网查阅都是单片机与之通信的文章,因为手头有很多闲置的arduino教学实验器材,顺手拿一块过来参照相关文章的介绍,模拟SMBus通信格式,理顺时序关系,很快就成功实现了Arduino和bq3060的通信。再次展现了Arduino轻便简洁上手块的强大功能,以下是我的代码介绍。
一、SMBus简介
SMBus(System Management Bus)是Intel与Duracell共同制定的接口,多用于笔记本和电池之间的通信管理,协议类似于I2C接口,但是有比较严格的应答时序,一般不能直接使用I2C协议。我猜测遇到挫折的朋友基本上都是应答时序没有吃透的缘故,个别贡献的文章也多在应答时序埋坑,当然也应该要感谢这些做出贡献的朋友!
二、核心代码
1.通信开始
代码如下:
void SMBus_Start(){//模拟SMBus协议的启动函数,参考SMBus通信协议
digitalWrite(SDA1 , 1);//预置空闲状态
digitalWrite(SCL1 , 1); delayMicroseconds(1); //时钟线高电平
digitalWrite(SDA1 , 0); delayMicroseconds(1); //拉低数据线,SMBus启动
digitalWrite(SCL1 , 0); delayMicroseconds(12); //时钟线低电平,太小偶尔会出错
}
2.结束通信
代码如下:
void SMBus_Stop(){ //SMBus停止函数,参考SMBus通信协议
digitalWrite(SCL1 , 0); //delayMicroseconds(1);
digitalWrite(SDA1 , 0); delayMicroseconds(1);
digitalWrite(SCL1 , 1); delayMicroseconds(1);
digitalWrite(SDA1 , 1); //数据线拉高,释放总线
}
3.等待应答
代码如下:
void SMBus_CheckAck(){//从应答函数,等待bq3060应答
unsigned char i;
pinMode(SDA1, INPUT_PULLUP);
digitalWrite(SCL1 , 1);
while (digitalRead(SDA1));// 检测有无应答
pinMode(SDA1, OUTPUT);
digitalWrite(SCL1 , 0);
delayMicroseconds(100);
}
4.发送应答
代码如下:
void SMBus_SendAck(bool n){
unsigned char i;
if (n) {
digitalWrite(SDA1 , 1);
delayMicroseconds(1);
}
else {
digitalWrite(SDA1 , 0);
delayMicroseconds(1);
}
digitalWrite(SCL1 , 1);
delayMicroseconds(1);
digitalWrite(SCL1 , 0);
delayMicroseconds(100);
}
5.读取1个字节
代码如下:
unsigned char SMBus_ReadByte(){
unsigned char i, k = 0;
pinMode(SDA1, INPUT_PULLUP);
for ( i = 0; i < 8; i++ )
{
digitalWrite(SCL1 , 1);
delayMicroseconds(1);
k = (k << 1) | digitalRead(SDA1); //按位读取
digitalWrite(SCL1 , 0);
delayMicroseconds(1);
}
pinMode(SDA1, OUTPUT);
return k;
}
6.写入1个字节
代码如下:
void SMBus_WriteByte(unsigned char data){
unsigned char i;
temp = data;
for (i = 0; i < 8; i++) //按位写入
{
digitalWrite(SCL1 , 0);
delayMicroseconds(1);
if ((data << i) & 0x80) {
digitalWrite(SDA1 , 1);
}
else {
digitalWrite(SDA1 , 0);
}
delayMicroseconds(1);
digitalWrite(SCL1 , 1);
delayMicroseconds(1);
}
digitalWrite(SCL1 , 0);
delayMicroseconds(1);
digitalWrite(SDA1 , 1);//拉高数据线,释放总线
delayMicroseconds(1);
}
7.通信测试
代码如下:
unsigned int SMBus_ReadTest(unsigned char addr)//参考bq3060通信格式
unsigned char dataH, dataL;
unsigned int DATA;
SMBus_Start();//启动协议
SMBus_WriteByte(DEV_ADDW);//设备地址
SMBus_CheckAck();//等待应答
SMBus_WriteByte(addr);//Reg地址
SMBus_CheckAck();//等待应答
SMBus_Start();//再次启动
SMBus_WriteByte(DEV_ADDR);//设备地址
SMBus_CheckAck();//等待应答
dataL = SMBus_ReadByte();//读取低字节
SMBus_SendAck(0);//发送应答
dataH = SMBus_ReadByte();// << 8; //读取高字节
SMBus_SendAck(1);//发送应答
SMBus_Stop();//停止读取
DATA=(dataH<<8)+dataL;
return DATA;//返回数据
}
总结
本文仅仅简单介绍了Arduino和bq3060的通信核心代码,只要是遵循SMBus协议的同类芯片,大同小异都可以使用。
本文参考了以下文章和链接,并致谢贡献者:
SMBus接口协议