|
#include <AT89X51.H>
#include <absacc.h>
#include <intrins.h>
sbit SMBC=P1^6;//sbit SMBC=P1^4; //bq2040中SMbus的時(shí)鐘端
sbit SMBD=P1^7;//sbit SMBD=P1^5; //bq2040中SMbus的數(shù)據(jù)端
sbit led3=P1^3; //LED指示燈的最高位,4位中的第3位,0表示指示燈亮,1表示指示燈滅,即對(duì)讀出數(shù)據(jù)取反
sbit led2=P1^2; //LED指示燈4位中的第2位
sbit led1=P1^1; //LED指示燈4位中的第1位
sbit led0=P1^0; //LED指示燈的最低位,4位中的第0位
sbit power_led=P1^4;//sbit power_led=P1^7;
sbit speaker=P1^5;//sbit speaker=P1^6;
unsigned char bq2040_Command_RC=0x0f; //讀剩余電量的指令
signed char bq2040_Command_C=0x0a; //讀電流的指令
unsigned char bq2040_Command_BS=0x16; //讀電池狀態(tài)
unsigned char ReceiveData_L,ReceiveData_H,Current_H_7,BatteryStatus_L_6,BatteryStatus_L_5;
//從BQ2040接收數(shù)據(jù)的低位,高位,電流正負(fù)位(正表示充電,負(fù)表示放電),電池狀態(tài)充放電判斷(0表示充電,0x40表示放電),電池狀態(tài)滿充判斷(0表示未充滿,0x20表示充滿)
unsigned char ack; //用于判斷接收確認(rèn)是否超時(shí),超時(shí)為1,未超時(shí)為0
unsigned char ADAPTER=0,ERROR; //用于判斷儀器采用電池供電或者采用電源適配器供電
void Delay(void) //延時(shí)子程序
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
//以下函數(shù)詳見(jiàn)SMbus原理
void Star(void) //開(kāi)始子程序 當(dāng)SMBC為高電平時(shí),SMBD上出現(xiàn)一個(gè)下降沿。該條件啟動(dòng)一次傳輸過(guò)程
{
SMBC=0;
Delay();
SMBD=1;
Delay();
SMBC=1;
Delay();
SMBD=0;
Delay();
}
void Stop(void) //停止子程序 當(dāng)SMBC為高電平時(shí),SMBD上出現(xiàn)一個(gè)上升沿。該條件停止一次傳輸過(guò)程
{
SMBC=0;
Delay();
SMBD=0;
Delay();
SMBC=1;
Delay();
SMBD=1;
Delay();
}
void Ackw(void) //ACKNOWLEDGE寫子程序 SMBC為高時(shí),采樣到SMBD為低電平
{
unsigned char a=0;
ack=0;
SMBC=0;
Delay();
SMBD=1;
Delay();
SMBC=1;
Delay();
while(SMBD)
{
a++;
ack=0;
if(a==250) // 向串口發(fā)送EE,表示發(fā)送出錯(cuò),未收到確認(rèn)。利用串口助手可以看到
{
ADAPTER++;
if(ADAPTER==20)
{
ERROR=0xEE;
ADAPTER=0;
}
else
ERROR=0;
ack=1;
SBUF=0xEE;
while(!TI);
TI=0;
break;
}
}
}
void Ackr(void) //ACKNOWLEDGE讀子程序 SMBC為高時(shí),采樣到SMBD為低電平
{
SMBC=0;
Delay();
SMBD=0;
Delay();
SMBC=1;
Delay();
}
void Nack(void) //NOT ACKNOWLEDGE子程序 SMBC為高電平時(shí),采樣到SMBD為高電平
{
SMBC=0;
Delay();
SMBD=1;
Delay();
SMBC=1;
Delay();
}
void Send(unsigned char b) //發(fā)送子程序 將b按從最高位到最低位的順序,逐位的發(fā)送給bq2040
{
unsigned char i,x,y,z;
z=0x80;
for(i=1;i<9;i++)
{
x=b&z;
if(x==0)
y=0;
else
y=1;
SMBC=0;
Delay();
SMBD=y;
Delay();
SMBC=1;
Delay();
z>>=1;
}
}
unsigned char Receive(void) //接收子程序 將bq2040中的數(shù)據(jù)逐位的讀出
{
unsigned char i,g=0x00;
for(i=1;i<9;i++)
{
SMBC=0;
_nop_();
_nop_();
SMBD=1;
Delay();
SMBC=1;
Delay();
g<<=1;
if(SMBD)
g++;
Delay();
}
return g;
}
void Read(unsigned char Command) //讀剩余電量子程序
{
unsigned int a;
Star(); //開(kāi)始
a=0x16;
Send(a); //發(fā)送器件地址0x16
Ackw(); //發(fā)送確認(rèn)
if(ack) //未確認(rèn)則重新發(fā)送
return;
Send(Command); //發(fā)送讀剩余電量指令
Ackw(); //發(fā)送確認(rèn)
if(ack) //未確認(rèn)則重新發(fā)送
return;
Star();
a=0x17; //發(fā)送器件地址0x17
Send(a);
Ackw(); //發(fā)送確認(rèn)
if(ack) //未確認(rèn)則重新發(fā)送
return;
ReceiveData_L=Receive(); //接收剩余電量低8位數(shù)據(jù)
Ackr(); //接收確認(rèn)
ReceiveData_H=Receive(); //接收剩余電量高8位數(shù)據(jù)
Nack(); //非確認(rèn)
Stop(); //結(jié)束
}
void Delay2(void) //4s顯示延時(shí)
{
unsigned char i,j,k;
for(i=0;i<255;i++)
for(j=0;j<255;j++)
for(k=0;k<20;k++);
}
void Delay3(void) //power_led快閃延時(shí)
{
unsigned char i,j,k;
for(i=0;i<100;i++)
for(j=0;j<150;j++)
for(k=0;k<5;k++);
}
void Delay4(void) //power_led特快閃延時(shí),speaker響延時(shí)
{
unsigned char i,j,k;
for(i=0;i<100;i++)
for(j=0;j<150;j++)
for(k=0;k<1;k++);
}
void Delay5(void) //power_led慢閃延時(shí)
{
unsigned char i,j,k;
for(i=0;i<100;i++)
for(j=0;j<150;j++)
for(k=0;k<12;k++);
}
void LedDisplay_Battery(unsigned char h,unsigned char l)
{
unsigned char i;
if(BatteryStatus_L_5==0x20&&BatteryStatus_L_6==0) //充電充滿時(shí),指示燈顯示0 1 0 0=11
{
power_led=0;
speaker=1;
led0=0;
led1=0;
led2=1;
led3=0;
Delay2();
}
else if(Current_H_7==0&&BatteryStatus_L_6==0) //充電時(shí),指示燈顯示0 1 0 1=10
{
power_led=0;
speaker=1;
led0=1;
led1=0;
led2=1;
led3=0;
Delay2();
}
//放電時(shí),指示燈指示電量0-9共10份
else
{
if(h>0x22) //超出電量范圍(當(dāng)讀出的剩余電量16位的高8位大于0x22,即電量大于8960mah時(shí)1,表示錯(cuò)誤,所有燈不亮)
{
power_led=0;
speaker=1;
led0=1;
led1=1;
led2=1;
led3=1;
}
if(h<=0x22&&h>=0x17) //顯示09(當(dāng)剩余電量在5888mah~8960mah之間時(shí),指示燈表示 0 1 1 0=9)
{
power_led=0;
speaker=1;
led0=0;
led1=1;
led2=1;
led3=0;
Delay2();
}
if(h<0x17&&h>=0x15) //顯示08(當(dāng)剩余電量在5376mah~5888mah之間時(shí),指示燈表示 0 1 1 1=8)
{
power_led=0;
speaker=1;
led0=1;
led1=1;
led2=1;
led3=0;
Delay2();
}
if(h<0x15&&h>=0x12) //顯示07(當(dāng)剩余電量在4608mah~5376mah之間時(shí),指示燈表示 1 0 0 0=7)
{
power_led=0;
speaker=1;
led0=0;
led1=0;
led2=0;
led3=1;
Delay2();
}
if(h<0x12&&h>=0x0f) //顯示06(當(dāng)剩余電量在3840mah~4608mah之間時(shí),指示燈表示 1 0 0 1=6)
{
power_led=0;
speaker=1;
led0=1;
led1=0;
led2=0;
led3=1;
Delay2();
}
if(h<0x0f&&h>=0x0d) //顯示05(當(dāng)剩余電量在3328mah~3840mah之間時(shí),指示燈表示 1 0 1 0=5)
{
power_led=0;
speaker=1;
led0=0;
led1=1;
led2=0;
led3=1;
Delay2();
}
if(h<0x0d&&h>=0x0a) //顯示04(當(dāng)剩余電量在2560mah~3328mah之間時(shí),指示燈表示 1 0 1 1=4)
{
power_led=0;
speaker=1;
led0=1;
led1=1;
led2=0;
led3=1;
Delay2();
}
if(h<0x0a&&h>=0x08) //顯示03(當(dāng)剩余電量在2048mah~2560mah之間時(shí),指示燈表示 1 1 0 0=3)
{
power_led=0;
speaker=1;
led0=0;
led1=0;
led2=1;
led3=1;
Delay2();
}
if(h<0x08&&h>=0x05) //顯示02(當(dāng)剩余電量在1280mah~2048mah之間時(shí),指示燈表示 1 1 0 1=2)
{
power_led=0;
speaker=1;
led0=1;
led1=0;
led2=1;
led3=1;
Delay2();
}
if(h<0x05&&h>=0x01) //顯示01(當(dāng)剩余電量在256mah~1280mah之間時(shí),指示燈表示 1 1 1 0=1)
{
power_led=0;
speaker=1;
led0=0;
led1=1;
led2=1;
led3=1;
Delay2();
}
if(h<0x01) //顯示01在閃爍(當(dāng)剩余電量在0mah~256mah之間時(shí),指示燈表示 1 1 1 0=0)
{
//led0=0;
led1=1;
led2=1;
led3=1;
if(l>=0x40&&l<0xa0)
{
speaker=1;
for(i=0;i<15;i++)
{
led0=!led0;
power_led=!power_led;
Delay3();
}
}
else if(l<0x40)
{
speaker=0;
for(i=0;i<15;i++)
{
led0=!led0;
power_led=!power_led;
Delay4();
}
}
else
{
speaker=1;
for(i=0;i<10;i++)
{
led0=!led0;
power_led=!power_led;
Delay5();
}
}
}
}
}
void LedDisplay_Adapter() //燈全亮,表示采用電源適配器供電
{
power_led=0;
speaker=1;
led0=0;
led1=0;
led2=0;
led3=0;
Delay2();
}
main()
{
unsigned char RemainingCapacity_H,RemainingCapacity_L,Current_H,BatteryStatus_L;
TMOD=0x20; //串口波特率9600bps,方式3,無(wú)校驗(yàn),數(shù)據(jù)位8,停止位1.
TH1=0xFD;
TL1=0xFD;
PCON=0x00;
TR1=1;
SCON=0xD8;
power_led=0;
while(1)
{
Read(bq2040_Command_C);
// 向串口發(fā)送當(dāng)前電流,利用串口助手可以看到
if(ack==0) //讀數(shù)據(jù)成功,則執(zhí)行賦值
Current_H=ReceiveData_H;
SBUF=bq2040_Command_C;
while(!TI);
TI=0;
SBUF=Current_H;
while(!TI);
TI=0;
SBUF=ReceiveData_L;
while(!TI);
TI=0;
Current_H_7=Current_H&0x80;
Read(bq2040_Command_BS);
// 向串口發(fā)送電池狀態(tài),利用串口助手可以看到
if(ack==0) //讀數(shù)據(jù)成功,則執(zhí)行賦值
BatteryStatus_L=ReceiveData_L;
SBUF=bq2040_Command_BS;
while(!TI);
TI=0;
SBUF=ReceiveData_H;
while(!TI);
TI=0;
SBUF=BatteryStatus_L;
while(!TI);
TI=0;
BatteryStatus_L_6=BatteryStatus_L&0x40;
BatteryStatus_L_5=BatteryStatus_L&0x20;
Read(bq2040_Command_RC);
// 向串口發(fā)送剩余電量,利用串口助手可以看到
if(ack==0) //讀數(shù)據(jù)成功,則執(zhí)行賦值
{
RemainingCapacity_H=ReceiveData_H;
RemainingCapacity_L=ReceiveData_L;
}
SBUF=bq2040_Command_RC;
while(!TI);
TI=0;
SBUF=RemainingCapacity_H;
while(!TI);
TI=0;
SBUF=RemainingCapacity_L;
while(!TI);
TI=0;
if(ack==0)
LedDisplay_Battery(RemainingCapacity_H,RemainingCapacity_L);
else if(ERROR==0xEE)
LedDisplay_Adapter();
}
}
|
評(píng)分
-
查看全部評(píng)分
|