快充芯片IP5328P的寄存器数据读写[用于DIY数显快充充电宝]

【本帖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)															//如果功率>0
			if(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;									//12V
			case 0x03:voltage.VIN=9;break;									//9V
			case 0x01:voltage.VIN=7;break;									//7V
			case 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;								//12V
			case 0x03:voltage.TypeC=9;break;								//9V
			case 0x01:voltage.TypeC=7;break;								//7V
			case 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

 

 

 

  • 30
    点赞
  • 82
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 19
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超级网吧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值