【本帖DIY因为有一定的危险性,非专业人员请勿自行尝试】 【如有侵权 联系删除】
IP5328P是一款最大18W的快充芯片,主要用于快充充电宝的产品,基本支持市面上绝大部分主流的快充协议。
因为能看到本帖的想必都是对这个芯片很了解了,所以就不过多赘述了,接下详细介绍此贴的由来、过程及结果。[后面我会附加此芯片的中文手册,不了解的可以看手册]
★缘起:
在某宝捡电子垃圾时偶然发现一款快充充电板的尾料在低价售卖,虽是18年的产品,但是相比同参数新品快充板的几十块钱来说,这个板子的3.8元那可简直是太香了。又因本人有几个普通充电宝,充电速度相对于快充充电器实在是缓慢至极,故平时极少使用,如果拿来改装为快充充电宝岂不快哉!
★过程及改装方法:
对于DIY,如果是仅仅将电路板连接到电池上,那就太拉跨了。电路板自带4个led灯做为电量显示,显然对这一设计我并不满足,于是乎有了改为数显的想法。在看数据手册的过程中发现IP5328P自带IIC功能,可以读取其内部的各种参数,官方经典的电路(led灯显示模式)如下。在改为IIC时有两种接法,我选择的是IIC模式1,在原来的电路上,将R2和R7去掉,将LED1引脚和LED2引脚分别通过3.3K电阻用芯片的VREG进行上拉。VREG是IP5328P芯片自带的一个3.3V 30ma的LDO输出,在使用IIC模式时,为了保证稳定请尽量使用VREG作为上拉电源,因为在芯片激活时,会首先检测LED1和LED2的电平,如果为高则进入IIC模式。需要注意的是,手册上写着LED3引脚可以接单片机作为唤醒引脚或用来指示是否正在工作,但是此引脚又是设置电池电压的引脚,接入不同的电阻下拉会设置不同的电池电压,实测中如果直接接单片机引脚,会导致电压设置改变,在对4.2V电池进行充电时终止电压并不是4.2V,而是大大高于4.2V,这样是非常危险的,很容易过冲发生爆炸!如果没有万分把握、经过实际测试或其他方式连接,请勿使用此引脚!
重要的事情说3遍:
这样是非常危险的,很容易过冲发生爆炸!
这样是非常危险的,很容易过冲发生爆炸!
这样是非常危险的,很容易过冲发生爆炸!
作为IIC模式使用时,LED1引脚即为IIC的时钟引脚SLK,LED2引脚即为IIC的数据引脚SDA,芯片的IIC读写时序在数据手册可以找的到,很容易看懂,我就不赘述了,直接上代码吧。使用的单片机是大家常用的stm32f103c8t6,SDA连接到PB8,SLK连接到PB9。主要的几个文件如下。
○i2c.c[iic的时序驱动文件]
#include "i2c.h"/** I2C 总线接口 */
#define I2C_PORT GPIOB
#define SDA_Pin GPIO_Pin_8
#define SCL_Pin GPIO_Pin_9#define FAILURE 0
#define SUCCESS 1//配置SDA信号线为输入模式
void SDA_Input_Mode()
{GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = SDA_Pin;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(I2C_PORT, &GPIO_InitStructure);
}//配置SDA信号线为输出模式
void SDA_Output_Mode()
{GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = SDA_Pin;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_Init(I2C_PORT, &GPIO_InitStructure);
}//
void SDA_Output( uint16_t val )
{if ( val ) {GPIO_SetBits(I2C_PORT,SDA_Pin);} else {GPIO_ResetBits(I2C_PORT,SDA_Pin);}
}//
void SCL_Output( uint16_t val )
{if ( val ) {GPIO_SetBits(I2C_PORT,SCL_Pin);} else {GPIO_ResetBits(I2C_PORT,SCL_Pin);}
}//
uint8_t SDA_Input()
{return GPIO_ReadInputDataBit( I2C_PORT, SDA_Pin);
}//延时程序
void delay1(unsigned int n)
{unsigned int i;for ( i=0;i<n;++i);
}//I2C总线启动
void I2CStart(void)
{SCL_Output(0);delay1(500);SDA_Output(1);delay1(500);SCL_Output(1);delay1(500);SDA_Output(0);delay1(500);SCL_Output(0);delay1(500);
}//I2C总线停止
void I2CStop(void)
{SCL_Output(0); delay1(500);SDA_Output(0); delay1(500);SCL_Output(1); delay1(500);SDA_Output(1); delay1(500);}//等待应答
unsigned char I2CWaitAck(void)
{unsigned short cErrTime = 5;SDA_Input_Mode(); delay1(500);SCL_Output(1);delay1(500);while(SDA_Input()){cErrTime--;delay1(500);if (0 == cErrTime){SDA_Output_Mode();
// I2CStop();return FAILURE;}}SDA_Output_Mode();SCL_Output(0);delay1(500); return SUCCESS;
}//发送应答位
void I2CSendAck(void)
{SDA_Output(0);delay1(500);delay1(500);SCL_Output(1); delay1(500);SCL_Output(0); delay1(500);}//
void I2CSendNotAck(void)
{SDA_Output(1);delay1(500);SCL_Output(1); delay1(500);SCL_Output(0); delay1(500);}//通过I2C总线发送一个字节数据
void I2CSendByte(unsigned char cSendByte)
{unsigned char i = 8;while (i--){SCL_Output(0);delay1(500); SDA_Output(cSendByte & 0x80); delay1(500);cSendByte += cSendByte;delay1(500); SCL_Output(1);delay1(500); }SCL_Output(0);delay1(500);
}//从I2C总线接收一个字节数据
unsigned char I2CReceiveByte(void)
{unsigned char i = 8;unsigned char cR_Byte = 0;SDA_Input_Mode(); while (i--){cR_Byte += cR_Byte;SCL_Output(0);delay1(500); delay1(500); SCL_Output(1);delay1(500); cR_Byte |= SDA_Input(); }SCL_Output(0);delay1(500); SDA_Output_Mode();return cR_Byte;
}//I2C总线初始化
void i2c_init()
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);GPIO_InitStructure.GPIO_Pin = SDA_Pin | SCL_Pin;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // **GPIO_Init(I2C_PORT, &GPIO_InitStructure);}
○i2c.h
#ifndef __I2C_H__
#define __I2C_H__#include "stm32f10x.h"void i2c_init(void);
void delay1(unsigned int n);void SCL_Output( uint16_t val );
void SDA_Output( uint16_t val );void I2CStart(void);
void I2CStop(void);
void I2CSendAck(void);
void I2CSendNotAck(void);
unsigned char I2CWaitAck(void);void I2CSendByte(unsigned char cSendByte);
unsigned char I2CReceiveByte(void);#endif
○ip5328p.c[IP5328P芯片的读写实现和常用参数获取]
/**** ****/
/**** 说明: 根据IP5328P (with reg) V1.0编写 ****/
/**** 寄存器手册来自51黑电子论坛 ID:没有你 ****/
/**** 程序功能并不完全,仅写自认常用功能函数,可自行扩展 ****/
/**** 作者: 超级网吧 ****/
/**** 时间: 2020-10-04 ****/
/**** ****/#include "i2c.h"
#include "ip5328p.h"//写寄存器(8bit)
//reg:寄存器地址
//data:待写入数据
void IP5328P_Write(unsigned char reg,unsigned char data)
{I2CStart(); //起始信号I2CSendByte(0xEA); //写从机地址I2CWaitAck(); //等待应答I2CSendByte(reg); //待写入数据寄存器地址I2CWaitAck(); //等待应答I2CSendByte(data); //写入数据I2CWaitAck(); //等待应答I2CStop(); //停止信号
}//读寄存器(8bit)
//reg:寄存器地址
//data:待写入数据
unsigned char IP5328P_Read(unsigned char reg)
{unsigned char R_dat;I2CStart(); //起始信号I2CSendByte(0xEA); //写从机地址I2CWaitAck(); //等待应答(在未收到应答时 未做处理 可自行添加)I2CSendByte(reg); //待写入数据寄存器地址I2CWaitAck(); //等待应答(在未收到应答时 未做处理 可自行添加)I2CStart(); //当作重启信号 I2CSendByte(0xEB); //写入从机地址 开启读操作I2CWaitAck(); //等待应答 (在未收到应答时 未做处理 可自行添加)R_dat=I2CReceiveByte(); //接收8bit数据I2CSendNotAck(); //发送mNACK信号 停止接收I2CStop(); //停止信号return R_dat;
}//读取电池电量显示级别(只能读到对应电量的LED个数)
//返回:0001 1111:4课灯亮 0000 1111:3课灯亮 0000 0111:2课灯亮 0000 0011:1课灯亮
// 0000 0001:放电时低电闪灯 0000 0000:关机
unsigned char IP5328P_Electricity(void)
{int dat;dat=IP5328P_Read(0xDB); //获取电量指示级别return dat;
}/**************************************************读取芯片参数功能函数********************************************************///读取电池两端的真实电压值
//返回float型的电压值(小数)
float IP5328P_BatVoltage(void)
{int dat;float BatVoltage=0.0f;dat=IP5328P_Read(0x64); //获取电池电压低8位BatVoltage += dat;dat=IP5328P_Read(0x65); //获取电池电压高8位BatVoltage = (dat<<8)+BatVoltage; //高低位合并if(BatVoltage==0xffff) return 0; //如果读到0xffff,此时芯片未激活 读取值错误BatVoltage = BatVoltage*0.00026855+2.6; //计算为实际电压值return BatVoltage;
}//读取电池输入或输出电流
//返回float型的电流值(小数) 单位ma
float IP5328P_BatCurrent(void)
{int dat;float Current=0.0f;dat=IP5328P_Read(0x66); //获取电池电流低8位Current += dat;dat=IP5328P_Read(0x67); //获取电池电流高8位Current = (dat<<8)+Current; //高低位合并if(Current>32767)Current=65535-Current; //将负值电流转为正值Current = Current*0.00127883; //计算为实际电流值return Current;
}//读取电池电压经过电芯内阻和电芯电流进行补偿后的电压
//返回float型的电压值(小数)
float IP5328P_BatOCV(void)
{int dat;float BatVoltage=0.0f;dat=IP5328P_Read(0x7A); //获取电池电压低8位BatVoltage += dat;dat=IP5328P_Read(0x7B); //获取电池电压高8位BatVoltage = (dat<<8)+BatVoltage; //高低位合并if(BatVoltage==0xffff) return 0; //如果读到0xffff,此时芯片未激活 读取值错误BatVoltage = BatVoltage*0.00026855+2.6; //计算为实际电压值return BatVoltage;
}//获取Type-C接口连接状态
//返回:0x00未连接
// 0x01连接手机等需供电设备(充电宝在放电)
// 0x02连接电源适配器(充电宝在充电)
unsigned char IP5328P_TypeC_Flag(void)
{unsigned char flag=0,dat=0;dat=IP5328P_Read(0xB8);if(dat==0xff)return 0; //如果读到0xff,芯片未激活if(dat>>1&0x01)flag=0x01;if(dat>>5&0x01)flag=0x02;return flag;
}//获取Type-C连接的适配器输出能力
//返回:0x00 芯片未激活
// 0x01标准USB
// 0x02输出能力1.5A
// 0x03输出能力3.0A
unsigned char IP5328P_TypeC_Ability(void)
{unsigned char flag=0,dat=0;dat=IP5328P_Read(0xFF);if(dat==0xff)return 0; //如果读到0xff,芯片未激活if(dat>>5&0x01)flag=0x01;if(dat>>6&0x01)flag=0x02;if(dat>>7&0x01)flag=0x03;return flag;
}/********************以下电流读取有条件限制*********************************/
/*********大体可以理解为当有多个接口同时开启时才可以读取********************/
/***************其中,VBUS是TYPE-C口,VIN是安卓口***************************///读取Type-C输入或输出电流
//返回float型的电流值(小数) 单位ma
//条件:需要在充电状态 VINOK 和 VBUSOK 同时有效且 VBUS MOS开启时;
// 或者VBUS MOS开启的同时有其他MOS也开启时,该ADC才会启动
// (以上符号状态都可用寄存器读取)
float IP5328P_TypeC_Current(void)
{int dat;float Current=0.0f;dat=IP5328P_Read(0x6E); //获取电流低8位Current += dat;dat=IP5328P_Read(0x6F); //获取电流高8位Current = (dat<<8)+Current; //高低位合并if(Current>32767)Current=65535-Current; //将负值电流转为正值Current = Current*0.0006394; //计算为实际电流值return Current;
}//读取安卓口输入电流
//返回float型的电流值(小数) 单位ma
//条件:需要在充电状态 VINOK 和VBUSOK 同时有效且 VIN MOS开启时该 ADC才会启动
// (以上符号状态都可用寄存器读取)
float IP5328P_VIN_Current(void)
{int dat;float Current=0.0f;dat=IP5328P_Read(0x6D); //获取电流低8位Current += dat;dat=IP5328P_Read(0x6C); //获取电流高8位Current = (dat<<8)+Current; //高低位合并if(Current>32767)Current=65535-Current; //将负值电流转为正值Current = Current*0.0006394; //计算为实际电流值return Current;
}//读取OUT1输出电流
//返回float型的电流值(小数) 单位ma
//条件:需要在 OUT1 MOS 开启的同时有其他 MOS 也开启时,该 ADC 才会启动;
// (以上符号状态都可用寄存器读取)
float IP5328P_OUT1_Current(void)
{int dat;float Current=0.0f;dat=IP5328P_Read(0x70); //获取电流低8位Current += dat;dat=IP5328P_Read(0x71); //获取电流高8位Current = (dat<<8)+Current; //高低位合并if(Current>32767)Current=65535-Current; //将负值电流转为正值Current = Current*0.0006394; //计算为实际电流值return Current;
}//读取OUT2输出电流
//返回float型的电流值(小数) 单位ma
//条件:需要在 OUT1 MOS 开启的同时有其他 MOS 也开启时,该 ADC 才会启动;
// (以上符号状态都可用寄存器读取)
float IP5328P_OUT2_Current(void)
{int dat;float Current=0.0f;dat=IP5328P_Read(0x72); //获取电流低8位Current += dat;dat=IP5328P_Read(0x73); //获取电流高8位Current = (dat<<8)+Current; //高低位合并if(Current>32767)Current=65535-Current; //将负值电流转为正值Current = Current*0.0006394; //计算为实际电流值return Current;
}/********************以上电流读取有条件限制*********************************///获取当前电源功率
//返回float型的功率值(小数)
float IP5328P_Power(void)
{int dat;float Power=0.0f;dat=IP5328P_Read(0x7C); //获取功率低8位Power += dat;dat=IP5328P_Read(0x7D); //获取功率高8位Power = (dat<<8)+Power; //高低位合并if(Power==0xffff) return 0; //如果读到0xffff,此时芯片未激活 读取值错误Power = Power*0.00844; //计算为实际功率值return Power;
}//获取芯片当前电源状态
//第四位:0:放电 1:充电
//2:0位 :000:待机 001:5V充电 010:单口同充同放 011:多口同充同放
// 100:高压快充充电 101:5V放电 110:多口5V放电 111:高压快充放电
//其他位:无效位
unsigned char IP5328P_SYS_Status(void)
{unsigned char flag=0;flag=IP5328P_Read(0xD1);if(flag==0xff)return 0;return flag;
}//获取输入电压有效状态以及按键是否被按下
//返回:7:6无效位
// 5 VBUSOK: 1 TYPE-C接口电压有效(充放电都会有效) 0 接口电压无效
// 4 VINOK : 1 安卓口接口电压有效 0 安卓口接口电压无效
// 3:1无效位
// 0 key_in: 0按键按下 1按键未按下
unsigned char IP5328P_KEY_IN(void)
{unsigned char flag=0;flag=IP5328P_Read(0xD2);if(flag==0xff)return 0;return flag;
}//获取安卓口和TYPE-C的输入电压
//返回:7:6无效位
// 5:3 TYPE-C_STATE:000-5V,001-7V,011-9V,111-12V
// 2:0 VIN_STATE :000-5V,001-7V,011-9V,111-12V
unsigned char IP5328P_VinTypeC_State(void)
{unsigned char flag=0;flag=IP5328P_Read(0xD5);if(flag==0xff)return 0;return flag;
}//获取充电状态
//返回:7: 0可能刚好是在停充检测,也可能是充满了,也可能是异常保护了 1 正在充电
// 6: 0未充满 1充满
// 5: 0恒压恒流总计时未超时 1恒压恒流总计时超时
// 4: 0恒压计时未超时 1恒压计时超时
// 3: 0涓流计时未超时 1涓流计时超时
// 2:0 000空闲 001涓流充电 010恒流充电 011恒压充电 100停充检测 101电池充满结束 110超时
unsigned char IP5328P_GHG_State(void)
{unsigned char flag=0;flag=IP5328P_Read(0xD7);return flag;
}//获取MOS状态
//返回:7: 0当前安卓口在充电 1当前TYPE-C在充电
// 6: 0安卓口电压无效 1安卓口电压有效
// 5: 0TYPE-C电压无效 1TYPE-C电压有效
// 4: 0VIN MOS(安卓)未开启 1VIN MOS(安卓)开启
// 3: 无效位
// 2: 0VBUS MOS(TYPE-C)未开启 1VBUS MOS(TYPE-C)开启
// 1: 0VOUT2 MOS未开启 1VOUT2 MOS开启
// 0: 0VOUT1 MOS未开启 1VOUT1 MOS开启
unsigned char IP5328P_MOS_ON(void)
{unsigned char flag=0;flag=IP5328P_Read(0xE5);if(flag==0xff)return 0;return flag;
}//获取升压输出电压值范围
//返回:7:4 无效位
// 3: 0无效 1输出电压10-12V
// 2: 0无效 1输出电压8-10V
// 1: 0无效 1输出电压6-8V
// 0: 0非快充 1快充
unsigned char IP5328P_BOOST(void)
{unsigned char flag=0;flag=IP5328P_Read(0xFB);if(flag==0xff)return 0;return flag;
}//获取QC快充是否使能(不是是否正在使用,而是说这个功能可以用)
//返回:7:4 无效位
// 3: 0非快充 1TYPE-C快充使能
// 2: 0非快充 1安卓口快充使能
// 1: 0非快充 1OUT2快充开使能
// 0: 0非快充 1OUT1快充开使能
unsigned char IP5328P_QC_State(void)
{unsigned char flag=0;flag=IP5328P_Read(0x3E);if(flag==0xff)return 0;return flag;
}//获取快充是否可以被使用(不是是否正在使用,而是说这个功能可以用)
//返回:7: MTK PE 1.1 RX 支持的最大电压设置 0 12V 1 9V
// 6: MTK PE2.0 RX 使能 0 失能 1 使能
// 5: MTK PE1.1 RX 使能 0 失能 1 使能
// 4: SFCP SRC(展讯)使能 0 失能 1 使能
// 3: AFC SRC(三星) 使能 0 失能 1 使能
// 2: FCP SRC(华为) 使能 0 失能 1 使能
// 1: QC3.0 SRC 使能 0 失能 1 使能
// 0: QC2.0 SRC 使能 0 失能 1 使能
unsigned char IP5328P_DCP_DIG(void)
{unsigned char flag=0;flag=IP5328P_Read(0xA2);if(flag==0xff)return 0;return flag;
}/*----------------------------------------------读取芯片参数功能函数-end-----------------------------------------------------*//**************************************************写芯片参数功能函数********************************************************///设置电池低电关机电压(关机后需重新充电才可启动)
//输入:0x30 3.00V-3.10V
// 0x20 2.90V-3.00V
// 0x10 2.81V-2.89V
// 0x00 2.73V-2.81V
void IP5328P_BAT_LOW(unsigned char dat)
{if(dat==0x30||dat==0x20||dat==0x10||dat==0x00)//为保证器件不出错,确认指令正确后在写入IP5328P_Write(0x10,dat);
}//设置SYS4
//输入:chg2bst:拔出充电自动开启升压输出 0不开启 1开启
// swclk2 :使能I2C2待机时钟(使能后待机可读数据) 0不开启 1开启
// swclk1 :使能I2C1待机时钟(使能后待机可读数据) 0不开启 1开启
void IP5328P_SYS_CTL14(unsigned char chg2bst,unsigned char swclk2,unsigned char swclk1)
{unsigned char dat=0x00;if(chg2bst)dat|=0x40;if(swclk2)dat|=0x08;if(swclk1)dat|=0x04;IP5328P_Write(0x0E,dat);
}/*------------------------------------------------写芯片参数功能函数-end----------------------------------------------------*//*---------------------------------------------------获取常用参数-----------------------------------------------------------*/float power; //总功率
Interface mos_state; //各接口开启状态结构体
Interface current; //各接口电流结构体
Interface voltage; //各接口电压结构体//获取常用参数
//包括:总功率、各接口电压、各接口电流、各接口开启状态
void read_Parameters(void)
{unsigned char mos,Sys_status,Bat_Grade,GHG_State,TypeC_VIN_voltage,boost;
/*----------------------------------------------获取参数----------------------------------------------------------*/ mos=IP5328P_MOS_ON(); //获取接口状态power=IP5328P_Power(); //获取功率TypeC_VIN_voltage=IP5328P_VinTypeC_State(); //获取安卓口和TYPE-C电压current.TypeC=IP5328P_TypeC_Current(); //获取Type-C电流值current.VIN=IP5328P_VIN_Current(); //获取VIN电流值current.OUT1=IP5328P_OUT1_Current(); //获取VOUT1电流值current.OUT2=IP5328P_OUT2_Current(); //获取VOUT2电流值boost=IP5328P_BOOST(); //获取升压值
// Sys_status=IP5328P_SYS_Status(); //获取系统状态
// Bat_Grade=IP5328P_Electricity(); //获取电量等级
// GHG_State=IP5328P_GHG_State(); //获取充电状态
/*--------------------------------------------处理接口状态--------------------------------------------------------*/mos_state.OUT1=mos&0x01; //获得OUT1开启状态 [因为按下按键激活时,OUT1会开启输出,但可能并没有连接]mos_state.OUT2=mos>>1&0x01; //获得OUT2开启状态mos_state.TypeC=mos>>2&0x01; //获得TypeC开启状态mos_state.VIN=mos>>4&0x01; //获得VIN开启状态if(mos_state.OUT1) //纠正OUT1开启状态 [因为按下按键激活时,OUT1会开启输出,但可能并没有连接]{if(power<=0.2)mos_state.OUT1=0; //如果功率为0则未连接if(power>0) //如果功率>0if(mos_state.OUT2||mos_state.TypeC||mos_state.VIN) //且有其他接口开启if(current.OUT1==0)mos_state.OUT1=0; //如果OUT1电流还是为0,则证明OUT1接口实际未开启}
/*--------------------------------------------处理接口电压--------------------------------------------------------*/if(mos_state.VIN){ //如果VIN接口是开启的switch(TypeC_VIN_voltage&0x07) //VIN电压{case 0x07:voltage.VIN=12;break; //12Vcase 0x03:voltage.VIN=9;break; //9Vcase 0x01:voltage.VIN=7;break; //7Vcase 0x00:voltage.VIN=5;break; //5V} }else voltage.VIN=0; //其他if(mos_state.TypeC){ //如果TYPE-C接口是开启的switch(TypeC_VIN_voltage>>3&0x07) //TYPE-C电压{case 0x07:voltage.TypeC=12;break; //12Vcase 0x03:voltage.TypeC=9;break; //9Vcase 0x01:voltage.TypeC=7;break; //7Vcase 0x00:voltage.TypeC=5;break; //5V}}else voltage.TypeC=0; //其他if(mos_state.OUT1){ //如果接口开启if(current.OUT1)voltage.OUT1=5; //如果接口有电流else{ //如果接口无电流if(boost>1&0x01)voltage.OUT1=5; //电压值就是升压值if(boost>2&0x01)voltage.OUT1=9; //电压值就是升压值if(boost>3&0x01)voltage.OUT1=12; //电压值就是升压值} }else voltage.OUT1=0; //如果接口未开启if(mos_state.OUT2){ //如果接口开启if(current.OUT2)voltage.OUT2=5; //如果接口有电流else{ //如果接口无电流if(boost>1&0x01)voltage.OUT2=5; //电压值就是升压值if(boost>2&0x01)voltage.OUT2=9; //电压值就是升压值if(boost>3&0x01)voltage.OUT2=12; //电压值就是升压值} }else voltage.OUT2=0; //如果接口未开启
/*--------------------------------------------处理接口电流--------------------------------------------------------*/if(current.OUT1==0&&mos_state.OUT1)current.OUT1=power/voltage.OUT1; //如果电流为0,可能是仅插入一个接口,此时电流需要用功率换算if(current.OUT2==0&&mos_state.OUT2)current.OUT2=power/voltage.OUT2; //如果电流为0,可能是仅插入一个接口,此时电流需要用功率换算if(current.TypeC==0&&mos_state.TypeC)current.TypeC=power/voltage.TypeC; //如果电流为0,可能是仅插入一个接口,此时电流需要用功率换算if(current.VIN==0&&mos_state.VIN)current.VIN=power/voltage.VIN; //如果电流为0,可能是仅插入一个接口,此时电流需要用功率换算
/*--------------------------------------------处理xxxx--------------------------------------------------------*/}/*---------------------------------------------------获取常用参数-----------------------------------------------------------*/
○ip5328p.h
#ifndef __IP5328P_H__
#define __IP5328P_H__extern float power; //总功率typedef struct{unsigned char OUT1; //OUT1接口unsigned char OUT2; //OUT2接口unsigned char TypeC; //TypeC接口unsigned char VIN; //VIN(安卓口)
}Interface;extern Interface mos_state; //各接口开启状态结构体
extern Interface current; //各接口电流结构体
extern Interface voltage; //各接口电压结构体//基础操作函数
void IP5328P_Write(unsigned char reg,unsigned char data); //写IP5328P寄存器数据
unsigned char IP5328P_Read(unsigned char reg); //读IP5328P寄存器数据//功能函数
/**************************************读参数*****************************************************************/
float IP5328P_BatVoltage(void); //读电池两端电压值
float IP5328P_BatOCV(void); //电池电压经过电芯内阻和电芯电流进行补偿后的电压
float IP5328P_BatCurrent(void); //读取电池电流
float IP5328P_TypeC_Current(void); //读取TYPE-C输入输出电流
float IP5328P_VIN_Current(void); //读取安卓口的输入电流
float IP5328P_OUT1_Current(void); //读取OUT1输出电流
float IP5328P_OUT2_Current(void); //读取OUT2输出电流
float IP5328P_Power(void); //获取功率
unsigned char IP5328P_TypeC_Flag(void); //获取Type-C接口连接状态
unsigned char IP5328P_TypeC_Ability(void); //获取Type-C连接的适配器输出能力
unsigned char IP5328P_Electricity(void); //获取电量指示级别
unsigned char IP5328P_SYS_Status(void); //获取电源状态
unsigned char IP5328P_VinTypeC_State(void); //获取安卓口和TYPE-C的输入电压
unsigned char IP5328P_GHG_State(void); //获取充电状态
unsigned char IP5328P_MOS_ON(void); //获取MOS开启状态
unsigned char IP5328P_BOOST(void); //获取升压输出电压值范围
unsigned char IP5328P_QC_State(void); //获取QC快充是否使能(不是是否正在使用,而是说这个功能是否可以用)
unsigned char IP5328P_DCP_DIG(void); //获取获取快充是否使能(不是是否正在使用,而是说这个功能是否可以用)/**************************************写参数*****************************************************************/
void IP5328P_BAT_LOW(unsigned char dat); //设置电池低电关机电压
void IP5328P_SYS_CTL14(unsigned char chg2bst,unsigned char swclk2,unsigned char swclk1);//设置SYS4/***********************************获取常用参数***************************************************************/
void read_Parameters(void); #endif
使用时可以这样,如:
#include "lcd.h"
#include "delay.h"
#include "ip5328p.h"
#include "i2c.h"void main(void)
{LCD_Init(); //LCD初始化i2c_init();Show_Str(0,30,BLUE,BLACK," OUT2 TYPE-C VIN OUT1",16,0);while(1){read_Parameters(); //获取参数/*-----------------------------------获取电池电压电流----------------------------------*/sprintf(buf, "BAT:%1.2fV %1.2fA", IP5328P_BatVoltage(),IP5328P_BatCurrent()); //电池两端的电压和电流Show_Str(0,0,BLUE,BLACK,buf,16,0);
/*-----------------------------------接口状态--------------------------------------*/ sprintf(buf, " %1d %1d %1d %1d ",mos_state.OUT2,mos_state.TypeC,mos_state.VIN,mos_state.OUT1); Show_Str(0,50,BLUE,BLACK,buf,16,0);
/*-----------------------------------获取接口电压----------------------------------*/sprintf(buf, " %2dV %2dV %2dV %2dV",voltage.OUT2,voltage.TypeC,voltage.VIN,voltage.OUT1);Show_Str(0,70,BLUE,BLACK,buf,16,0);
/*-----------------------------------获取电池电压电流----------------------------------*/sprintf(buf, " %1.2fA %1.2fA %1.2fA %1.2fA",current.OUT2,current.TypeC,current.VIN,current.OUT1);Show_Str(0,90,BLUE,BLACK,buf,16,0);
/*-----------------------------------获取电源功率----------------------------------*/sprintf(buf, "Power:%2.1fW ",power);Show_Str(150,0,BLUE,BLACK,buf,16,0);delay_ms(100);}
}
★结果:
外壳是花4块钱买的,电池用了5节2600mAh的18650,壳子上的孔是用打磨文玩那种手持小电磨钻的,屏幕是135*240的IPS彩屏,加了个开关机电路[真开关机,直接断电那种],用一个按键控制,按下按键开机等待10S自动断电。实际测试中,TYPE-C给充电宝充电能达到稳定的16W,OUT1输出给手机能到18W,虽然数据是通过芯片寄存器读出的,准确性未知,但是最起码基本满足了数据手册的标称值。不过在给手机充电时,确实也是很快的,与我手机的快充充电器并无二致[本人手机也是18W快充的,所以此快充板完全满足我的使用需求]。
具体的程序和资料我放到了gitee上,保证所有人都可以免费下载:https://gitee.com/chaojiwangba/IP5328P