由于国内手持及便携设备大体可以分成两个部份, 一是智能手机, 二式平板计算机/MID。针对这两个市场的应用, 目前这两个区块的主要参考设计还是由AP厂家来提供。例如智能手机的Qualcomm, Broadcom, MTK, nVIdia, Samsung, Hisilicon(海思)等, 以及平板计算机/MID的全志, 炬力, 瑞芯微, 中星微等。
由于国内大部的手持及便携式设备厂家在开发新的产品时, 都必须仰赖AP厂提供技术支持, 所以对原厂的参考设计, 除了布线之外, 对元器件的使用大多不做更动。所以只要原厂的参考设计用了某一厂家的电量计, 或是如Qualcomm, Broadcom, MTK等用了自己PMIC内的库仑计, 再通过AP的计算来实现电量计功能。目前在市场上由于苹果手机及平板的原始设计用的是TI的方案, 所以在市场上, TI可以说是在电量计耕耘最久, 市场占有率最大的厂商。其次是由于Samsung大量采用Maxim的电量计方案, 所以Maxim可以说是保有电量计市场二哥的位置。
其余的无论是把库仑计放在PMIC内, 亦或是如Cellwise的加上自学习功能的电量计, 都是最近这两年进到市场的方案。之所以会有这个趋势, 最重要的原因是消费者开始要求设备的电量指示的精度。这个要求反应在所有手持及便携式设备的操作系统(iOS, Android, Windows Phone), 还有各类的APP上。由这个趋势也可以清楚的看出, 电量计在手持及便携式设备上所扮演的角色也越来越重要了。
下面以美信MAX17040芯片为代表,做详细说明。
1.MAX17040的工作原理
电量计MAX17040,他通过芯片去测量电池电量,芯片本身集成的电路比较复杂,同时可以通过软件上的一些算法去实现一些处理,是测量出的电量更加准确。还有一个好处,就是他之接输出数字量,通过IIC直接读取,我们在电路设计、程序处理上更加的统一化。
如下图所示,MAX17040和电池盒主控的关系,一个AD脚接到电池VBAT ,检测到的电量信息,通过IIC传到主控。
下面是电路图,电路接口比较简单,VBAT ,接到max17040的CELL,IIC接到主控的IIC2接口,这个我们在程序中要配置。看这个器件比较简单吧。
看下max17040的内部结构,其实这也是一个AD转换的过程,单独一颗芯片去实现,这样看起来比较专业些。CELL接口,其实就是一个ADC转换的引脚,我们可以看到芯片内部有自己的时钟(time base),IIC控制器之类的,通过CELL采集到的模拟量,转换成数字量,传输给主控。
通过上面的介绍Max17040的硬件、原理我们基本上都了解了,比较简单,下面我们就重点去分析下驱动程序。
2.MAX17040 总体流程
电量计的工作流程比较简单,max17040通过CELL ADC转换引脚,把电池的相关信息,实时读取,存入max17040相应的寄存器,驱动申请一个定时器,记时结束,通过IIC去读取电池状态信息,和老的电池信息对比,如果用变化上报,然后重新计时;这样循环操作,流程如下所示:
3.MAX17040这个电量计驱动,我们主要用到以下知识
【1】IIC的注册
IIC这个总线,在工作中用的比较多,TP、CAMERA、电量计、充电IC、音频芯片、电源管理芯片、基本所有的传感器,所以这大家要仔细看下,后面有时间的话单独列一片介绍下IIC,从单片机时代都用的比较多,看来条总线的生命力很强,像C语言一样,很难被同类的东西替代到,至少现在应该是这样的。
看下他结构体的初始化与驱动的申请,这个比较统一,这里就不再解释了。
IIC驱动的注册:
在arch/arm/mach-exynos/mach-smdk4x12.c中,IC平台驱动的注册:
下图就是我们IIC驱动注册生成的文件;
/sys/bus/i2c/drivers/max17040
【2】linux 中定时器的使用
定时器,就是定一个时间, 比如:申请一个10秒定时器,linux系统开始计时,到10秒,请示器清零重新计时并发出信号告知系统计时完成,系统接到这个信号,做相应的处理;
【3】任务初始化宏
任务结构体的初始化完成后,接下来要将任务安排进工作队列。 可采用多种方法来完成这一操作。 首先,利用 queue_work 简单地将任务安排进工作队列(这将任务绑定到当前的 CPU)。 或者,可以通过 queue_work_on 来指定处理程序在哪个 CPU 上运行。 两个附加的函数为延迟任务提供相同的功能(其结构体装入结构体 work_struct 之中,并有一个 计时器用于任务延迟 )。
【4】linux定时器调度队列
【5】max17040测到电量后如何上传到系统(这个电池系统中有简要的分析);
4中的定时器记时完成,就可以调度队列,chip->work执行:max17040_work函数,把改读取的信息上传,我们看下max17040_work函数的实现:
保存老的电池信息,如电量、AC、USB是否插入
读取电池新的状态信息
如果电池信息有变化,就上报系统
power_supply_changed这个函数比较重要, 我们后面分析;
如果用PM2301充电IC,USB充电功能不用
这个是由于我们的系统耗电比较大,用USB充电时,电流过小,所以出现越充越少的现象,所以这个功能给去掉了。
如果有DC插入,则跟新充电状态
【6】AC、USB充电状态怎么更新到应用
如上面所说,通过power_supply_changed上报;
【7】电池曲线的测量与加入
电池曲线,就是电池的冲放电信息,就是用专业的设备,对电池连续充放电几天,测出一个比较平均的值。然后转换成针对电量IC(如我们用的max17040)的数字量,填入一个数组中,如下图所示:
下面数据时针对电池曲线的数字量,和相关参数。如上图所示,为160小时的电池信息,包括:不同颜色分别代表不同的曲线:
如temperature ,reference SOC ,fuel gauge SOC,Vcell,Empty Voltage
数据表格如下:
加入驱动中的值:
/driver/power/max17040_common.c中