本帖最后由 电子阔少 于 2021-7-3 22:14 编辑

一个有关电池容量检测芯片的使用,1-wire总线的驱动代码  给需要帮助的人
电池容量检测芯片ds2780底层驱动(STM32源程序与资料)
制作出来的实物图如下:

360截图20210703215825301.jpg
1991M02X22手上有两块华硕手机的电池,都是报废的,已经有点鼓了,电池已经没什么容量了,但是里面的保护板应该还是好的
尤其是原厂电池,保护板应该不会偷工减料,就拆了出来准备留做备用,报废电池芯留着是个隐患,还是早些扔掉的好。
拆完了发现,这个保护板有点特别,上面是三个芯片,两个SSOP-8,一个SOT23-6,而且电池是4线输出的,
仔细观察,一个芯片上面写着2780,旁边还有一个0.02Ω 电阻,这不是MAXIM的电量计芯片DS2780嘛,想不到居然在这里碰到了。
DS2780用于测量可充电锂离子和锂离子聚合物电池的电压、温度和电流,并估算剩余电量。用于计算的电池特性参数和应用参数存储在片上EEPROM中。根据电流温度特性、放电速率、存储电荷与应用参数对可用电量进行估算。要知道,有些电池的放电曲线非常平缓,单纯靠测量电池端电压判断电池容量并不准确,而这个芯片可以计量经过电池的电量,充进多少电,放出多少电,里面还有多少电,它都能记录下来,配合设备上的MCU就可以很精确的知道电池里的剩余电量了。
有点像银行存款,存入多少,取出多少,账户里省多少,一看账单一清二楚。
360截图20210703215918669.jpg
就是这么个保护板
360截图20210703215949020.jpg
还剩下一个电池,先别拆了,通过已经拆下的保护板测出了DS2780的信号线端口,
按此给电池上焊上线,红色正极,黑色负极,蓝色数据线DQ
360截图20210703220028193.jpg
360截图20210703220053767.jpg
DS2780采用1-Wire接口,一根线完成通信,好像是美信的独家专利
为了能够接驳电脑,专门跑去买了一颗UART转1-Wire芯片,DS2480
现做了一个UART转1-Wire模块,DS2480目前已经停产了,市场上货源不多
这颗花了我18大洋
360截图20210703220125936.jpg


上位机的软件采用美信官方的DS2780评估板测试软件
显示电池电压,电流,容量等信息,还能对DS2780内部EEPROM进行读写
设置电池参数等
接上电,软件很快就显示出了电池信息
现在电池空载
电压3.8552V,电流1.9531mA,剩余容量564.6875mAhr,温度29.25摄氏度
容量还有大约一半,这个电池标称是1300mAh的
360截图20210703220233885.jpg
用万用表测量了下电池电压,3.85V,看来还是很准确的
360截图20210703220455431.jpg
接了一个10Ω 10W电阻对电池放电
360截图20210703220523609.jpg
放电时软件显示的信息
360截图20210703220554989.jpg
放电半小时后
360截图20210703220645576.jpg
又过了大约1小时,放完电了,这个电池的保护板在电池电压降到3.3V左右时开始保护
自动切断电路,空载的电池电压在3.6V,电池里还剩余大约162mAhr的电量。
360截图20210703220725383.jpg


下面看看充电,这是USB的5V通过一个10Ω电阻给锂电池充电
电流120mA,剩余电量也开始回升


360截图20210703220752534.jpg
360截图20210703220820509.jpg
用USB直接充电速度太慢,而且不安全,接入自制的TP4056充电板
设定的是400mA,显示385mA,是设定电阻的误差引起的


360截图20210703220854146.jpg


这个软件还能记录文本日志
可以根据需要调整采样时间
这是记录下来的电池充放电情况,这里全是放电记录
360截图20210703221057522.jpg
充电进行中,电池电压接近4.1V,充电电流明显下降
可以看出,已经充进去600mAhr的电量
360截图20210703221131160.jpg


电池电压接近4.2V,电流持续下降中,充入大约800mAhr的电量,按这么算
这个电池容量在1000mAh左右,是标称容量的76%左右
看起来损耗不多,但是智能手机已经没法用了
360截图20210703221200080.jpg


最后是DS2780电路图,这个芯片的外围电路很简单,而且只需要一根
信号线就可以和上位机通信了。
查了一下,这个芯片价格在15-20元左右,要是熟悉单片机编程,用这个芯片来监测锂电池应该还是不错的
结束!谢谢赏评!


STM32单片机源程序如下:
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "lcd.h"
#include "usart.h"         
#include "ds18b20.h"


int main(void)
{         
        u8 t=0;                           
        short temperature;               

        delay_init();                     //延时函数初始化         
        NVIC_Configuration();          //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
        uart_init(9600);                 //串口初始化为9600
         LED_Init();                             //LED端口初始化
        LCD_Init();                    //LCD初始化
        KEY_Init();                                 //KEY初始化

//          POINT_COLOR=RED;//设置字体为红色
//         LCD_ShowString(60,50,200,16,16,"WarShip STM32");        
//         LCD_ShowString(60,70,200,16,16,"DS18B20 TEST");        
//         LCD_ShowString(60,90,200,16,16,"ATOM@ALIENTEK");
//         LCD_ShowString(60,110,200,16,16,"2012/9/12");                  


         while(DS18B20_Init())        //DS18B20初始化        
        {
//                 LCD_ShowString(60,130,200,16,16,"DS18B20 Error");
//                 delay_ms(200);
//                 LCD_Fill(60,130,239,130+16,WHITE);
                 delay_ms(200);
                printf("not find");
        }                        
//writeacr();

//         LCD_ShowString(60,130,200,16,16,"DS18B20 OK");
//         POINT_COLOR=BLUE;//设置字体为蓝色
//          LCD_ShowString(60,150,200,16,16,"Temp:   . C");         
        while(1)
        {                        
                 if(t%10==0)//每100ms读取一次
                {               
                        printf("\t%d", current());


//                         temperature=DS18B20_Get_Temp();
//                         printf("%d\t",temperature);
//                         if(temperature<0)
//                         {
//                                 LCD_ShowChar(60+40,150,'-',16,0);                        //显示负号
//                                 temperature=-temperature;                                        //转为正数
//                         }else LCD_ShowChar(60+40,150,' ',16,0);                        //去掉负号
//                         LCD_ShowNum(60+40+8,150,temperature/10,2,16);        //显示正数部分            
//                            LCD_ShowNum(60+40+32,150,temperature%10,1,16);        //显示小数部分                    
                }                                   
                 delay_ms(10);
                t++;
                if(t==20)
                {
                        t=0;
                        LED0=!LED0;
                }
        }
}