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)数据存储在芯片的EEPROM中,并根据手机的需求,通过通讯线传递给手机.那么手机就得到了这块电池的准确容量。

在库仑计芯片的存储器里面通常有如下的基本电池信息
▲电池的初始容量(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)

  
  Qlsb:累积电荷(寄存器C,D)的最低有效位(qLSB);
  Rsense:外部检测电阻值;
  M:可编程的预分频器(1-128);
  Imax:应用的最大电流;

请注意,当预分频器设置为其默认值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)8<<28;}
#define SDA_OUT()       {GPIOB->CRL &= 0X0FFFFFFF; GPIOB->CRL |= (u32)3<<28;}
#endif#if _IIC2
#define SDA_IN()        {GPIOB->CRH &= 0XFFFF0FFF; GPIOB->CRH |= (u32)8<<12;}
#define SDA_OUT()       {GPIOB->CRH &= 0XFFFF0FFF; GPIOB->CRH |= (u32)3<<12;}
#endif#define IIC1_SCL_High     writeGpioHigh(IIC1_SCL)
#define IIC1_SCL_Low        writeGpioLow(IIC1_SCL)
#define IIC1_SDA_High   writeGpioHigh(IIC1_SDA)
#define IIC1_SDA_Low        writeGpioLow(IIC1_SDA)#define IIC2_SCL_High writeGpioHigh(IIC2_SCL)
#define IIC2_SCL_Low        writeGpioLow(IIC2_SCL)
#define IIC2_SDA_High   writeGpioHigh(IIC2_SDA)
#define IIC2_SDA_Low        writeGpioLow(IIC2_SDA)void iicStart(void)
{SDA_OUT();     //sda线输出IIC1_SCL_High;IIC1_SDA_High;delayNop(2);IIC1_SDA_Low;delayNop(2);IIC1_SCL_Low;   //钳住I2C总线,准备发送或接收数据
}void iicStop(void)
{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 < 8; i++){if( (byte&0x80) == 0x80 ){IIC1_SDA_High;}else{IIC1_SDA_Low;}byte <<= 1;delayNop(2);IIC1_SCL_High;delayNop(2);IIC1_SCL_Low;delayNop(2);}
}//读1个字节(高位开始读),ack=1时,发送ACK,ack=0,发送nACK
//在C语言中x<<=1等于x=x<<1,是把x左移1位以后值保存回x里,x发生变化了
u8 iicRead_Byte(unsigned char ack)
{u8 i;u8 recvByte = 0;SDA_IN();for(i = 0; i < 8; i++){IIC1_SCL_Low;delayNop(2);recvByte <<= 1;//高位开始读,所以左移if( GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7) == Bit_SET ){recvByte |= 0x01; }delayNop(2);     }if(ack){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);//11001000delayNop(5);if(iicWaitAck() == 0 ){iicStop();return;}iicWrite_Byte(ADDR_B);//o1hdelayNop(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);//11001000delayNop(3);if(iicWaitAck() == 0 ){iicStop();return;}iicWrite_Byte(addrRegister);//o2h / 04h / 06hdelayNop(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);//11001000delayNop(5);if(iicWaitAck() == 0 ){iicStop();return 0;}iicWrite_Byte(ADDR_A);//o0hdelayNop(5);if(iicWaitAck() == 0 ){iicStop();return 0;}iicStart();iicWrite_Byte(ADDR_DeviceRead);//11001001delayNop(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);//11001000delayNop(3);if(iicWaitAck() == 0 ){iicStop();return 0;}iicWrite_Byte(addrRegister);//o2h / 04h / 06hdelayNop(3);if(iicWaitAck() == 0 ){iicStop();return 0;}iicStart();iicWrite_Byte(ADDR_DeviceRead);//11001001delayNop(3);if(iicWaitAck() == 0 ){iicStop();return 0;}Qmsb = iicRead_Byte(1);Qlsb= iicRead_Byte(0);iicStop();receTwoByte = (Qmsb<<8) | Qlsb;return receTwoByte;
}float Qlsb = 0;
float QBAT = 0;
float Rsense = 50;
float M = 128;
void getbatteryCapacity(void)
{u16 recvData = 0;u8 C = 0;u8 D = 0;recvData = LTC2941_readTwoByte(ADDR_C);C = recvData >> 8;D = recvData&0x00ff;Qlsb = 0.085*(50/Rsense)*(M/128);QBAT = Qlsb*recvData;   //得到电荷量后,进行电量显示
}//电池百分比:   当前电量值除以总额度电量值;
u8 getbatteryPercent(void)
{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阈值。}}

电池电量检测方法-库仑计-基于LTC2941相关推荐

  1. c语言 电池电量检测,基于单片机的锂离子电池电量检测系统设计(本科).doc

    基于单片机的锂离子电池电量检测系统设计(本科) 南 昌 工 程 学 院 毕 业 设 计 (论 文) 机械与电气工程学院 系(院) 电气工程及其自动化 专业 毕业设计(论文)题目 基于单片机的锂离子电池 ...

  2. android蓝牙查看电池容量_Android查看电池电量的方法(基于BroadcastReceiver)

    本文实例讲述了Android查看电池电量的方法.分享给大家供大家参考,具体如下: 程序如下: import android.app.Activity; import android.app.Dialo ...

  3. android 电池电量广播,Android查看电池电量的方法(基于BroadcastReceiver)

    本文实例讲述了Android查看电池电量的方法.分享给大家供大家参考,具体如下: 程序如下: import android.app.Activity; import android.app.Dialo ...

  4. 干电池电量采集_一种电池电量采集方法与流程

    本发明涉及电池参数采集技术领域,尤其涉及一种电池电量采集方法. 背景技术: 目前,在使用电池的产品上,通常使用电量计来获取电池电量的精确数值.而由于电量计的成本较高,还有一些低成本的产品上,还会通过采 ...

  5. 【开发教程5】开源蓝牙心率防水运动手环-电池电量检测

    蓝牙心率防水运动手环  --疯壳·智能穿戴开发系列 电池电量检测 1  ADC 简介 ADC(Analog-to-Digital Converter),模/数转换器或者模数转换器,是指将连续变化的模拟 ...

  6. 三种传统电量检测方法对比分析

    关注同名微信公众号"混沌无形",有趣好文! 原文链接:https://mp.weixin.qq.com/s/INtVyE4xrWl1n0mG_INgZA 图 1 电池放电曲线. S ...

  7. 干电池电量采集_干电池电量检测方法

    检测普通锌锰干电池的电量是否充足,通常有两种方法. 第一种方法是通过测量电池瞬时短路电流来估算电池的内阻,进而判断电池电量是否充足; 这种方法的最大优点是简便,用万用表的大电流档就可直接判断出干电池的 ...

  8. UPS电池容量检测方法

    UPS电池长时间使用后,容量会变小,使UPS失去延时作用.为了避免这种现象发生,可以使用以下方法检查电池容量.电池容量减小主要表现为内阻增大,知道这一点,就很容只找到检测方法. 1.用万用表测电池电压 ...

  9. STM32实现水下四旋翼(八)传感任务4——电池电量检测

    目录 一. 电压检测原理 二. ADC读电压驱动代码 三. 传感任务增加读电压应用代码 一. 电压检测原理 电压检测是为了检测机器人的电池电量,锂电池的电量与电压值是呈正相关的.锂电池是严禁过放的,不 ...

  10. android 检测电量变化,Android电池电量检测

    电池的信息,电压,温度,充电状态等等,都是由BatteryService来提供的.电池的这些信息是BatteryService通过广播 主动把数据传送给所关心的应用程序. 应用如果想要接收到Batte ...

最新文章

  1. Spring Boot(七):Mybatis 多数据源最简解决方案
  2. ARM处理器寻址方式 之 堆栈寻址
  3. 电脑word在哪_新的电脑应该安装哪些软件?只需这9个足够你用一生!
  4. mysql 共享表空间存储_MySQL InnoDB共享表空间
  5. python中怎样创建字典内建函数_python中常用的字典内建函数
  6. 2019-2020新闻自动挂机阅读脚本应用开发
  7. HT1621B显示驱动LCD显示驱动芯片- SSOP48
  8. java进程通信方式
  9. c语言输出菱形for循环_使用c语言输出菱形
  10. linux 关闭屏幕键盘 软键盘
  11. matlab 双曲正割脉冲,matlab画双曲正割(急)!!!!!!!!!!!!!!!!!!!!!!...
  12. 12.QT + OpenCV打包成应用(以及QT图标问题详细) --- OpenCV从零开始到图像(人脸 + 物体)识别系列
  13. EXCEL表格-数据拆分及分列
  14. php 抓取网页内容与图片
  15. python获取网页内容 不打开_网页抓取python不返回任何内容
  16. c#.net连接access数据库
  17. 苹果CMS内容管理系统 - 苹果CMS官方网站
  18. MySQL 自增 ID 超大问题查询
  19. h5 默认为移动端页面_20条移动前端H5页面开发规范,h5开发必看文档
  20. 基于STM32,TB6612,TCRT5000的简易红外循迹小车

热门文章

  1. 做Java软件开发有前途吗?
  2. python 去除txt文本内容重复值
  3. phpstudy没有安装VC11、VC14运行库
  4. CentOS6.9安装AliSQL
  5. 如何在数字化领域脱颖而出?TOGAF®认证为你的职业成长赋能
  6. VS2008+Vassistx使用技巧
  7. JVM内存模型1.8
  8. 如何快速合并多个PDF文件或图片为一个PDF文件?
  9. J1939广播DM1报文
  10. Platform SDK and SB2