【精选】电池电量检测方法 | 您所在的位置:网站首页 › vivox20plus电池电量检测怎么查 › 【精选】电池电量检测方法 |
1. 电池电量格数的定义:
一般手机设计待机电量时, 比如有**4格5档(4-3-2-1-0)**的电量指示。 由于要考虑到电池使用一段时间(比如1年)后, 其放电平台会降低,上述的比例肯定会失调。 所以需要考虑一点点这方面的余量.以新电池的60%-40%-20%-5%这样的比例进行设计。 4.20V~3.90V满格 3.90V~3.80V三格 3.80V~3.72V两格 3.72V~3.65V一格 3.65以下,低电压告警。 虽然在使用新电池时, 第一格会待机比较长的时间, 最后一格待机比较短。但是当这个电池使用个一年半载后, 其容量分布就比较接近均分的情况。 2 .库伦计 2.1基本内容mAh:电池容量的计量单位; 库仑的国际标准单位为电流乘于时间的安培秒. 1mAh=0.001安培*3600秒=3.6安培秒=3.6库仑; 库仑计的芯片,即电量计量芯片是装在手机电池里面的,通常是与锂离子电池的保护线路设计在一起。 2.2库伦计工作原理
在库仑计芯片的存储器里面通常有如下的基本电池信息 ▲电池的初始容量(mAh),即额定容量,一个电池完全充放后得到的容量 ▲电池的当前容量(mAh),处于使用状态是的电池容量 ▲当前流经的电流(mA),即手机的电流损耗 例子:一块额定容量为600mAh的电池,如果当前电池容量只有456mAh,手机就显示 456/600=76%; 电池额定容量调整 1、电池循环充电次数(电池使用率)会影响到电池的额定容量 如:比如初始容量是600mAh的电池,在100次循环以后,其实际容量已经变成500mAh了,如果在进行容量显示是仍然按照600mAh这个数来计算的话,势必造成电池永远充不饱这个问题.。 解决措施:库仑计的里面还有一个容量对使用次数调整的算法,会根据电池循环次数调整其实际容量。 2、电池使用温度会影响到电池的可用容量 如:比如在25度时,电池可以得到几乎100%的可用容量,而在0度是,电池只能放出80%的可用容量。 解决措施:库仑计里面还有一个容量对温度调整的算法,会根据电池的实际温度进行可用容量调整; 请您定期的对你所用的电池进行一次完全的充分,以便库仑计进行容量调整和归一化的进行.确保库仑计一直工作在最佳状态。 基于LTC2941芯片进行库仑计法检测电池电量对于这个将不会做过多的说明;一切的说明都不如直接看芯片手册;总的来说就是使用IIC通信进行读写芯片中相应的寄存器; 这里只做简要说明,具体看后面上传的中英文芯片数据手册; 1)、LTC2941芯片寄存器 A:状态寄存器; B:控制寄存器; C:累积电荷寄存器(高八位); D:累积电荷寄存器(低八位); E:充电阈值高MSB; F:充电阈值高LSB; G:充电阈值低MSB; H:充电阈值低LSB; (寄存器的描述请看手册) 2)、电池容量计算公式 QBAT = qLSB(C*256 + D) 请注意,当预分频器设置为其默认值M =128时,1mAh = 3.6A•s=3.6C(库仑)。 3)、IIC驱动程序; //系统时钟为24M时 //count = 200时,时间约等于100us void delayNop(u32 count) { while(count -- > 0) { __NOP(); } }注意:经过测试,该IIC通讯读写有问题;建议自己修改,但是下面的LTC2941的时序没有问题; /*****************************IIC通信协议***************************/ #define _IIC1 1 #define _IIC2 0 #define IIC1_SCL PB6 #define IIC1_SDA PB7 #define IIC2_SCL PB10 #define IIC2_SDA PB11 #if _IIC1 #define SDA_IN() {GPIOB->CRL &= 0X0FFFFFFF; GPIOB->CRL |= (u32)8CRL |= (u32)3CRH |= (u32)8CRH |= (u32)3 SDA_OUT(); //sda线输出 IIC1_SDA_Low; IIC1_SCL_Low; delayNop(2); IIC1_SCL_High; IIC1_SDA_High; delayNop(2); } u8 iicWaitAck(void) { u8 errorAck = 0; SDA_IN(); IIC1_SCL_High; delayNop(2); IIC1_SDA_High; delayNop(2); while( GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7) == Bit_SET ) { errorAck++; if(errorAck > 250) { iicStop(); return 0; } } IIC1_SCL_Low; return 1; } //产生应答 void iicACK(void) { IIC1_SCL_Low; SDA_OUT(); IIC1_SDA_Low; delayNop(2); IIC1_SCL_High; delayNop(2); IIC1_SCL_Low; } void iicNOack(void) { IIC1_SCL_Low; SDA_OUT(); IIC1_SDA_High; delayNop(2); IIC1_SCL_High; delayNop(2); IIC1_SCL_Low; } void iicWrite_Byte(u8 byte) { u8 i; SDA_OUT(); IIC1_SCL_Low; for(i = 0; i IIC1_SDA_High; } else { IIC1_SDA_Low; } byte IIC1_SCL_Low; delayNop(2); recvByte iicACK(); } else { iicNOack(); } return recvByte; } /***************************** LTC2941 ***************************/ #define ADDR_DeviceWrite 0xC8 #define ADDR_DeviceRead 0xC9 //A:状态寄存器 #define ADDR_A 0x00 //B:控制寄存器 #define ADDR_B 0x01 //CD:累积电荷寄存器 #define ADDR_C 0x02 #define ADDR_D 0x03 //EF:充电阀值高 #define ADDR_E 0x04 #define ADDR_F 0x05 //GH:充电阀值低 #define ADDR_G 0x06 #define ADDR_H 0x07 //对寄存器B进行写0xFC操作; //警报电压:3v(11) //预分频:128(111) //充电完成模式(10); //关掉模拟;(0) void LTC2941_writeB(u8 data) { iicStart(); iicWrite_Byte(ADDR_DeviceWrite);//11001000 delayNop(5); if(iicWaitAck() == 0 ) { iicStop(); return; } iicWrite_Byte(ADDR_B);//o1h delayNop(5); if(iicWaitAck() == 0 ) { iicStop(); return; } iicWrite_Byte(data); delayNop(5); if(iicWaitAck() == 0 ) { iicStop(); return; } iicStop(); } //对寄存器CD EF GF 进行写操作; //CD默认:7FFF; 充电完成后:FFFF //EF:电池满电量提醒:4200mv //GH:电池低电量提醒:3600mv void LTC2941_writeTwoByte(u8 addrRegister, u8 Qmsb, u8 Qlsb) { iicStart(); iicWrite_Byte(ADDR_DeviceWrite);//11001000 delayNop(3); if(iicWaitAck() == 0 ) { iicStop(); return; } iicWrite_Byte(addrRegister);//o2h / 04h / 06h delayNop(3); if(iicWaitAck() == 0 ) { iicStop(); return; } iicWrite_Byte(Qmsb); delayNop(3); if(iicWaitAck() == 0 ) { iicStop(); return; } iicWrite_Byte(Qlsb); delayNop(5); if(iicWaitAck() == 0 ) { iicStop(); return; } iicStop(); } //A[7]:芯片识别; 1 : LTC2941; 0 : LTC2942; //A[5]:指示累积电荷的值达到顶部或底部。 //A[3]:指示累积电荷值超过了电荷阈值上限。 //A[2]:指示累积电荷值下降到电量阈值下限以下。 //A[1]:VBAT警报指示电池电压(SENSE-)下降低于选定的VBAT阈值。 //A[0]: u8 LTC2941_readA(void) { u8 receByte = 0; iicStart(); iicWrite_Byte(ADDR_DeviceWrite);//11001000 delayNop(5); if(iicWaitAck() == 0 ) { iicStop(); return 0; } iicWrite_Byte(ADDR_A);//o0h delayNop(5); if(iicWaitAck() == 0 ) { iicStop(); return 0; } iicStart(); iicWrite_Byte(ADDR_DeviceRead);//11001001 delayNop(5); if(iicWaitAck() == 0 ) { iicStop(); return 0; } receByte = iicRead_Byte(0); iicStop(); return receByte; } u16 LTC2941_readTwoByte(u8 addrRegister) { u16 receTwoByte = 0; u16 Qmsb = 0; u8 Qlsb = 0; iicStart(); iicWrite_Byte(ADDR_DeviceWrite);//11001000 delayNop(3); if(iicWaitAck() == 0 ) { iicStop(); return 0; } iicWrite_Byte(addrRegister);//o2h / 04h / 06h delayNop(3); if(iicWaitAck() == 0 ) { iicStop(); return 0; } iicStart(); iicWrite_Byte(ADDR_DeviceRead);//11001001 delayNop(3); if(iicWaitAck() == 0 ) { iicStop(); return 0; } Qmsb = iicRead_Byte(1); Qlsb= iicRead_Byte(0); iicStop(); receTwoByte = (Qmsb u16 currentBAT = 0;//当前电量值 u16 rateBAT = 0;//额定电量值 currentBAT = LTC2941_readTwoByte(ADDR_C); rateBAT = LTC2941_readTwoByte(ADDR_E); return (u8)currentBAT/rateBAT; } void batteryWarn(void) { u8 receA = 0; u8 batteryHigh; u8 batteryLow; u8 batteryVeryLow; receA = LTC2941_readA(); batteryVeryLow = (receA&0x02); batteryLow = (receA&0x04); batteryHigh = (receA&0x08); if(batteryLow) { //低电量提醒 } if(batteryHigh) { //电池满电状态 } if(batteryVeryLow) { //警报指示电池电压(SENSE-)下降低于选定的VBAT阈值。 } } |
CopyRight 2018-2019 实验室设备网 版权所有 |