展讯充电管理模块浅析

电池在电子产品中所占的地位就不用说了。不过电池在物理接口上比较简单,就两条线:正极、负极,这个小学生科普知识都知道;不过真正用到电子产品中时,有关电池方面的东西还是有点多的。

参考文档:

http://m.blog.csdn.net/blog/Baiduluckyboy/8813662

http://blog.csdn.net/xubin341719/article/details/8497830

从三个方面介绍:

android 电池(一):锂电池充电基本原理篇

android 电池(二):android关机充电流程、充电画面以及电量显示

android 电池(三):android电池系统

需要格外关注的文件sprd_power.c;sprd_8825_charge.c/sprd_8825_charge.h

充电驱动核心文件:power_supply_core.cpower_supply_sysfs.c

相关充电管理ic驱动代码bq27x00_battery.c,max17040_battery.c  ...

展讯充电管理ic模块集成在芯片内部,由各种寄存器直接操作!

一、锂电池充电基本原理篇

电池充电最重要的就是这三步:

A charge cycle begins whenthe voltage atVCHG pin rises above 4.5v . If the VBAT is lessthan 1.1v,the charger entersactive charge mode. Inthis mode, charger supplies approximately 5mA chargecurrent  to active the battery. If  the VBAT is more than 1.1v and less than 2.7v, the charger enters small currentcharge mode. In this mode, charger supplies approximately 50mA charge currentto bringthe battery voltage upto a safe level for full current charging. WhenVBAT voltage rises above 2.7v, the chargers enters full current charge mode andcharger uses a constant-current algorithm in both mode.  When VBAT approaches the final float voltage(4.2v), charger enters constant-voltage mode and the charge current beginstodecrease. When the charge current dropsto thetermination current(50mA~100mA)set bythesoftware,  the charge cycle ends, andtheend voltage could be very accurate if calibrated by the software or ATE.     

--摘自展讯TIGER externaldevicespec.pdf

锂离子电池一般都带有管理芯片和充电控制芯片。其中管理芯片中有一系列的寄存器,存有容量、温度、ID、充电状态、放电次数等数值。这些数值在使用中会逐渐变化。使用说明中的“使用一个月左右应该全充放一次”的做法主要的作用应该就是修正这些寄存器里不当的值。

第一步:判断电压<1.1V,要先进行预充电,5ma电流;

第二步:判断1.1V<电压<2.7V,要先进行预充电,50ma电流;

第三步:判断 2.7V<电压<4.2V,恒流充电500ma-800ma电流;

#defineSPRD_USB_CHG_CUR         SPRD_CHG_CUR_500MA

#if defined(CONFIG_COMB_PRODUCT_S6)

#defineSPRD_AC_CHG_CUR           SPRD_CHG_CUR_800MA

#else

#defineSPRD_AC_CHG_CUR           SPRD_CHG_CUR_600MA

#endif

/*batterystatus define*/

这里可以设置充电电流的大小!

第四步:判断电压>4.2V,恒压充电,电压为4.2V,电流随电压的增加而减少,直到充满。

voidsprd_set_sw(struct sprd_battery_data *data, int switchpoint)

{

BUG_ON(switchpoint > 31);

sci_adi_write(ANA_CHGR_CTRL1,

((switchpoint <<CHGR_SW_POINT_SHIFT) &

CHGR_SW_POINT_MSK),(CHGR_SW_POINT_MSK));

}

uint32_tsprd_get_sw(struct sprd_battery_data *data)

{

return ((sci_adi_read(ANA_CHGR_CTRL1)& CHGR_SW_POINT_MSK) >>

CHGR_SW_POINT_SHIFT);

}

uint32_tsprd_adjust_sw(struct sprd_battery_data * data, bool up_or_down)

{

uint8_t current_switchpoint;

uint8_t shift_bit;

uint8_t chg_switchpoint;

chg_switchpoint =

(sci_adi_read(ANA_CHGR_CTRL1) & CHGR_SW_POINT_MSK) >>

CHGR_SW_POINT_SHIFT;

shift_bit = chg_switchpoint >> 4;

current_switchpoint = chg_switchpoint& 0x0F;

if (up_or_down) {

if (shift_bit > 0) {

if(current_switchpoint < 0xF) {

current_switchpoint += 1;

}

} else {

if(current_switchpoint > 0) {

current_switchpoint-= 1;

} else {

shift_bit =1;

}

}

} else {

if (shift_bit > 0) {

if(current_switchpoint > 0) {

current_switchpoint-= 1;

} else {

shift_bit =0;

}

} else {

if(current_switchpoint < 0xF) {

current_switchpoint+= 1;

}

}

}

chg_switchpoint = (shift_bit <<4) | current_switchpoint;

sci_adi_write(ANA_CHGR_CTRL1,

((chg_switchpoint <<CHGR_SW_POINT_SHIFT) &

CHGR_SW_POINT_MSK),(CHGR_SW_POINT_MSK));

return chg_switchpoint;

}

展讯在CC_CV转换做的是自适应的swithpoint,也可以手动设置swithpoint,也可以读取软件设置的转换点!

电池温度检测:

#ifdef CONFIG_BATTERY_TEMP_DECT

temp_value =sci_adc_get_value(ADC_CHANNEL_TEMP, false);

if (temp_value < 0)

goto out;

put_temp_value(battery_data,temp_value);

temp_value =get_temp_value(battery_data);

temp =sprd_adc_to_temp(battery_data, temp_value);

/*abs is to get absolute value*/

if(abs(battery_data->temp - temp) > 2) {

battery_data->temp= temp;

battery_notify= 1;

}

if (temp >OTP_OVER_HIGH || temp < OTP_OVER_LOW) {

battery_data->over_temp_flag= 1;

battery_notify= 1;

printk(KERN_ERR"battery temperature out temp:%d\n", temp);

charge_stop(battery_data);

}

if (!battery_data->charging&& !battery_data->in_precharge &&

(usb_online || ac_online) &&battery_data->over_temp_flag) {

if (temp >OTP_RESUME_LOW || temp < OTP_RESUME_HIGH) {

printk(KERN_ERR

"battery recovery temperaturetemp:%d\n", temp);

battery_notify= 1;

battery_data->over_temp_flag= 0;

if(ac_online)

enable_ac_charge(battery_data);

else

enable_usb_charge(battery_data);

}

}

#endif

当电池温度变化过大时,软件可中断充电!

电源状态的监控是用uevent事件实现的。Linux内核中,供电部分的框架(drivers/power目录下,power_supply_core,power_supply_sysfs)提供了uevent机制,驱动可以在电源状态发生变化时发送uevent事件到用户空间,从而通知系统做相应的处理。(对于内核空间与用户空间的uevent通信,用的始终是NETLINK_KOBJECT_UEVENT这个socket通道)。

二、android正常开机流程、关机充电流程

在写这篇文章之前我们先看两个流程:正常开机流程,关机充电系统启动流程

1、正常开机流程,按开机键。

可大致分成三部分

(1)、OS_level:UBOOT、kenrel、init这三步完成系统启动;

(2)、Android_level:这部分完成android部的初始化;

(3)、Home Screen:这部分就是我们看到的launcher部分。

2、关机充电系统启动流程

与前面相比,这个流程只走到init这一部分,就没有往后走了,这部分我们会在后面的代码中分析。

二、关机充电逻辑硬件逻辑

1、插入DC,charger IC从硬件上唤醒系统,相当于长按开机键开机。

DC插入,其实相当于关机状态下“按开机键”开机。第一步要走UBOOT、kernel、android init这一流程。

a:如何判断是DC插入;在函数dwc_otg_pcd_linux.c中usb_detect_works()函数中对usb插入做检测。

b:在cmd_cboot.c中有定义函数决定到底是什么方式启动开机,这个参数相当重要,这个参数决定系统是正常启动、还是关机充电状态。

三、android电池系统

创建相关的驱动交互驱动节点:

static intsprd_battery_probe(struct platform_device *pdev)

{

int ret = -ENODEV;

struct sprd_battery_data *data;

int adc_value;

int voltage_value;

int i;

struct resource *res = NULL;

unsigned int efuse_cal_data[2] = { 0 };

data = kzalloc(sizeof(*data),GFP_KERNEL);

if (data == NULL) {

ret = -ENOMEM;

goto err_data_alloc_failed;

}

… …

}

staticstruct platform_driver sprd_battery_device = {

.probe = sprd_battery_probe,

.remove = sprd_battery_remove,

.resume = sprd_battery_resume,

.driver = {

.name = "sprd-battery"}

};

static int__init sprd_battery_init(void)

{

#ifdefCHGR_STEADY

device_create(class_create(THIS_MODULE, "battery_capcity_dev"), NULL,MKDEV(register_chrdev(0,"battery_capcity_dev",&battery_capcity_fops),0),0, "battery_capcity_dev",0);

#endif

#ifdefined(CONFIG_GPIO_SWITCH_USB_HEADSET_SUPPORT)

if (GPIO_HEADSET_USB_SWITCH > 0) {

gpio_request(GPIO_HEADSET_USB_SWITCH,"usb headset switch 137");

pr_err("failed to allocgpio %d\n", GPIO_HEADSET_USB_SWITCH);

}

#endif

returnplatform_driver_register(&sprd_battery_device);

}}

module_init(sprd_battery_init);

module_exit(sprd_battery_exit);

向上层传输电池相关信息:

#ifdefCHGR_STEADY

static intbattery_capcity_open(struct inode *ind, struct file *filp)

{

return 0;

}

staticssize_t  battery_capcity_read(struct file*filp, char *buf, size_t size, loff_t *lofp)

{

int res = -1;

char tmp=50;

printk("<0>copybattery_capcity to the user space\n");

down_interruptible(&(battery_data->capacity_sema));

res = copy_to_user(buf,&battery_data->capcity_reference, size);

if (res == 0)

{

return size;

}

else

{

return 0;

}

}

staticssize_t  battery_capcity_write(structfile *filp, const char *buf, size_t size, loff_t *lofp)

{

int res = -1;

char tmp;

printk("write test databattery_capcity\n");

down_interruptible(&(battery_data->capacity_sema));

res =copy_from_user(&battery_data->capcity_reference, buf, size);

if (res == 0)

{

return size;

}

else

{

return 0;

}

}

structfile_operations battery_capcity_fops =

{

.owner=THIS_MODULE,

.open = battery_capcity_open,

.read = battery_capcity_read,

.write =  battery_capcity_write,

};

#endif

Java部分主要是BatteryService,作为电池及充电相关的服务,它的主要功能就是监听power_supply的uenvnt事件,读取sysfs中电池信息,然后通过intent广播给所有相关Activity。

JNI部分提供接口给上层的 battery_service.java 调用,直接读取设备文件,取得信息后,用来更新battery状态。

驱动部分kernel部分又可分为两部分:power_supply_core以及具体芯片的battery driver。

展讯电源管理芯片ic集成在芯片内部,由具体的寄存器操作,power_supply_core主要提供统一设备文件的创建以及发送power_supply相关的uevent;battery driver主要提供具体的电池信息。

....未完待续.....

展讯充电管理模块浅析(一)相关推荐

  1. [置顶] 展讯充电管理模块浅析(一)

    展讯充电管理模块浅析 电池在电子产品中所占的地位就不用说了.不过电池在物理接口上比较简单,就两条线:正极.负极,这个小学生科普知识都知道:不过真正用到电子产品中时,有关电池方面的东西还是有点多的. 参 ...

  2. 展讯sprd_battery.c 充电驱动

    sprd_battery.c 是充电驱动,这个是充电功能的核心内容,电量显示策略.温度检测策略.充电保护机制等功能在这里实现,功能实现与硬件细节剥离,调用通用接口实现逻辑控制: 1 sprdbat_p ...

  3. 58-硅谷课堂4-腾讯云点播管理模块

    58-硅谷课堂4-腾讯云点播管理模块-- 笔记 笔记内容来源与尚硅谷教学视频 文章目录 58-硅谷课堂4-腾讯云点播管理模块-- 笔记 笔记中涉及资源: 一.后台管理系统-点播管理模块 ①:点播管理 ...

  4. SM5202高性能版TP4056,SOP8/EMSOP8线性1A单节锂电充电管理芯片SM5202性能浅析

    SM5202高性能版TP4056,SOP8/EMSOP8线性1A单节锂电充电管理芯片SM5202性能浅析 市面上锂电充电管理芯片种类繁多,良莠不齐,泉州海川半导体在今年上半年推出了一款性价比极优的1A ...

  5. day09-硅谷课堂-腾讯云点播管理模块(三)

    硅谷课堂第九天-点播管理模块(三) 文章目录 硅谷课堂第九天-点播管理模块(三) 一.点播管理模块-课程统计 1.课程统计需求 2.课程统计接口 2.1.创建相关代码 videoVisitor表: 2 ...

  6. 直播课堂系统11--腾讯云点播管理模块(三)

    目录 点播管理模块-课程统计 需求 编写mapper 编写Service controller Echarts组建 前端 效果展示 整合腾讯云点播 点播管理模块-课程统计 需求 编写mapper 课程 ...

  7. 无人机项目跟踪记录七十一------电源充电管理芯片LTC4054模块

    下图为充电管理电路部分: 从左向右,J2为航空锂电池的接插头,连接3.7伏的锂电池.S1为六管脚两档的拨动开关,断开时2脚和5脚导通.1.6脚导通,3.4脚导通,2脚5脚与4脚导通,这时连接usb到电 ...

  8. 展讯UIS8910FF

    目录 1. 产品简介 1.1. 文档约定 2.功能特性 2.1. 特性列表 2.2. 系统框架 3.物理接口 3.1. 管脚分布 1. 产品简介 展讯UIS8910FF系列模组是基于紫光展锐 LTE平 ...

  9. python3 logging模块_Python3之logging模块浅析

    Python3之logging模块浅析 很多程序都有记录日志的需求,并且日志中包含的信息即有正常的程序访问日志,还可能有错误.警告等信息输出,python的logging模块提供了标准的日志接口,你可 ...

最新文章

  1. 西安4年java多少时间_西安学习java一般要多久
  2. javacurrentmap_Java ConcurrentHashMap.forEach方法代码示例
  3. Ajax Beta 2.0 中 AtlasToolKit Library 控件 Accordion 后台添加
  4. python自动化办公入门书籍-Python如此神奇,让繁琐工作自动化 (文中含Python基础)...
  5. DOSBox安装流程
  6. 【服务器系统设计】socket的阻塞模式和非阻塞模式总结
  7. 看一看golang的官方包:strings
  8. MATLAB 中的randn函数
  9. 中国建筑设计行业市场调查研究及发展前景展望报告(2022-2028年)
  10. linux下搜索文件名,Linux系统中怎么搜索文件命令大全
  11. Linux 远程工具
  12. Python爬虫响应码为404错误
  13. 如何自学大数据开发?
  14. 【 梯度下降算法 Gradient-Descend 数学推导与源码详解 深度学习 Pytorch笔记 B站刘二大人(2/10)】
  15. 人工智能常用评估指标
  16. html:点击图片放大到全屏,再次点击缩回
  17. e63 安装java_如何从电脑上下载游戏到诺基亚E63手机上?
  18. c语言源代码万年历,万年历-C语言源代码.pdf
  19. 《失控》(凯文·凯利)阅读分享
  20. 计算机计算出负数,cfa计算器 负数

热门文章

  1. kali中间人攻击----盗取账号和密码
  2. Java读取文件内容,返回字符串
  3. 格式工厂为保持输出视频质量与大小,自动裁剪视频长度
  4. 华为G520联通版解锁,ROOT,RECOVERY、卡刷及删除定制软件教程
  5. Qt实现 登录界面(酷炫)
  6. 苹果手机邮箱添加服务器,iPhone怎么添加邮箱账户?iPhone X添加邮箱账户方法
  7. 【go语言圣经】 初识 go
  8. [西川善司]3D图形技术概念和渲染管线的处理
  9. 文件夹批量改名,如何在文件夹改名后恢复成原来名称。
  10. 十年程序员血与泪:千万别重构代码!