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

2023-05-16

【本帖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

 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • Ubuntu22.04系统中关闭图形界面的方法

    实际上本方法不仅仅适用于Ubuntu22 04版本 xff0c 应该也适用于20 04等其他版本 关闭图形界面 xff0c 启用tty终端登录的方法如下 xff1a systemctl set default multi user targ
  • VUE3入门第三篇:创建应用

    安装框架 pn span class token function install span vue 64 latest 安装效果 PS D span class token punctuation span DATA span class
  • VUE3入门基础:input元素的type属性值说明

    说明 在Vue 3中 xff0c lt input gt 元素的type属性可以设置不同的类型 xff0c 以适应不同的输入需求 常见的type属性取值如下 xff1a text xff1a 默认值 xff0c 用于输入文本 passwor
  • Docker WIndows最新版(4.17.x)修改镜像存储路径

    一般情况 在 Docker Desktop 4 17 0 版本中 xff0c 可以按照以下步骤来修改 Docker 镜像存储路径 打开 Docker Desktop 应用程序 xff0c 单击顶部菜单栏中的 Docker Desktop 菜
  • Nginx限制请求方式

    在nginx的配置文件中 xff0c 将location 下的IF条件中的 request method参数设置允许的请求类型 仅允许Get server span class token punctuation span span cla
  • Nginx实现一个IP访问总流量限制

    在 Nginx 中 xff0c 可以使用 ngx http limit req module 模块配合 ngx http limit conn module 模块实现基于 IP 的流量和连接数控制 具体来说 xff0c 可以按照如下步骤实现
  • CentOS - node命令not found解决

    背景 xff1a 前几天在阿里云部署了一个node项目 xff0c node版本 v12 10 0 每次重新远程连接 xff0c 输入node v pm2 v 显示 command not found xff1b 每次必须先输入 nvm u
  • 用Java实现天天酷跑(附源码),这个真的有点强了!

    点击上方 阿拉奇学Java xff0c 选择 置顶或者星标 每天早晨00点00分 与你相约 xff01 首先 xff0c 写一个需求文档 xff1a 一 项目名称 xff1a 天天酷跑 xff08 RunDay xff09 二 功能介绍 x
  • SpringBoot开源在线考试系统

    推荐一款在线考试系统 xff1b 基于 SpringBoot 43 Mybatis 43 Shiro 43 mysql 43 redis构建的智慧云智能教育平台 架构上使用完全前后端分离 支持多种题型 xff1a 选择题 多选题 判断题 填
  • 微信闪退Bug罪魁祸首竟是二维码引擎,附源代码分析

    建议别尝试 xff1a 转发这个二维码到群里 xff0c 3秒后你会回来骂我 xff08 抖m求骂 xff09 近日 xff0c 网传微信识别上方二维码就会出现闪退BUG xff0c 小编也忍不住尝试了一下 xff0c 果然 xff0c 一
  • java多线程之线程安全(重点,难点)

    由于操作系统中 线程的调度是抢占式执行的 或者说是随机的 这就造成线程调度执行时 线程的执行顺序是不确定的 虽然有一些代码在这种执行顺序不同的情况下也不会运行出错 但是还有一部分代码会因为执行顺序发生改变而受到影响 这就会造成程序出现Bug
  • React-Native: DatePickerIOS设置选择24小时

    原帖 xff1a https github com mmazzarolo react native modal datetime picker DatePickerIOS选择24小时的方法 xff1a How to set 24 hours
  • 使用chatgpt实现微信聊天小程序(秒回复),github开源(附带链接)

    前言 我在前一段时间突发奇想 xff0c 就使用java来调用chatgpt的接口 xff0c 然后写了一个简单小程序 xff0c 也上了热榜第一 xff0c java调用chatgpt接口 xff0c 实现专属于自己的人工智能助手 xff
  • HttpPost 携带参数的请求方式

    一 HTTP请求 Http的几种请求方式对应程序包中的HttpGet HttpHead HttpPost HttpPut HttpDelete HttpTrace and HttpOptions xff0c 这些类均实现了HttpUriRe
  • mysql 根据时间范围查询

    时间格式为 第一种写法 xff1a select from test where create time between 39 2019 03 05 13 04 07 39 and 39 2019 03 08 13 04 07 39 第二种
  • java 根据条件从List中筛选出符合条件的集合

    1 list 你要在里面筛选的对象集合 存放格式例如 list add user1 list add user2 list add user3 2 xff1a tableColumnName xff1a user 里面的属性字段 xff1a
  • Es QueryBuilder 简单查询

    1 matchQuery String name Object text matchQuery 34 filedname 34 34 value 34 匹配单个字段 xff0c 匹配字段名为filedname 值为value的文档 单个匹配
  • Mysql 查询区分大小写的两种方法

    oracle中查询默认是区分大小写的 xff0c 但是在mysql中默认不区分大小写 解决办法 xff1a mysql可以在SQL语句中加入 binary来区分大小写 BINARY不是函数 xff0c 是类型转换运算符 xff0c 它用来强
  • 微信小程序实现登录页面

    wxml文件 xff1a lt view class 61 34 container 34 gt lt view class 61 34 login icon 34 gt lt image class 61 34 login img 34
  • 锂电池充电IC-TP4056电路设计详解

    首先 xff0c 先介绍下TP4056 TP4056是一款完整的单节锂离子电池采用恒定电流 恒定电压线性充电器 其底部带有散热片的SOP8封装与较少的外部元件数目使得TP4056成为便携式应用的理想选择 TP4056可以适合USB电源和适配

随机推荐

  • mysql无法插入中文的解决办法:修改数据库编码为utf-8

    mysql无法插入中文的解决办法 1 无法插入中文原因 mysql数据库的默认编码是latin1 xff0c 可以使用下面代码查看数据库编码 show variables like 34 character 34 发现有两处的编码是lati
  • 为Debian 10.2 安装图形化桌面环境

    首先先下载x window的内核 xff1a apt get u install x window system core 下载登录管理界面gdm或kdm xff1a apt get u install gdm gdm themes 下载G
  • C# System.BadImageFormatException 解决方法

    出现System BadImageFormatException 异常有两种情况 xff1a 程序目标平台不一致 amp 引用dll文件的系统平台不一致 异常参考 xff1a BadImageFormatException 程序目标平台不一
  • leetcode452

    题目 xff1a 在二维空间中有许多球形的气球 对于每个气球 xff0c 提供的输入是水平方向上 xff0c 气球直径的开始和结束坐标 由于它是水平的 xff0c 所以y坐标并不重要 xff0c 因此只要知道开始和结束的x坐标就足够了 开始
  • UVA-11300

    span class token macro property span class token directive hash span span class token directive keyword include span spa
  • UVA-11520 Fill the Square

    思路 xff1a 因为要求是字典序 xff0c 这道题的第一反应就是从A Z选取字母 xff0c 在正方形中从上到下 xff0c 从左到右这样的顺序去填字母 xff0c 一旦判断这个字母旁边没有和它一样的 xff0c 那么就证明这个字母就是
  • UVA10881 Piotr‘s Ants

    span class token macro property span class token directive hash span span class token directive keyword include span spa
  • -bash: conda: command not found

    其实是因为你没有加路径 执行一条 export PATH 61 PATH usr local miniconda2 bin 就OK啦 额 其实还不行 你要给conda加一个软链接 转换python2和3要创建虚拟环境
  • Sequence2Sequence 学习

    转载至 https blog csdn net MebiuW article details 52832847 1 前言 这个深度学习 xff0c 其实是来自每周Paper笔记的整理版 xff0c 即文章的主要内容其实是我对一篇文章的整理
  • Foreign Exchange (UVA - 10763)

    include lt iostream gt include lt bits stdc 43 43 h gt define maxn 500002 using namespace std int N1 maxn int N2 maxn in
  • 如何正确安装Microsoft Office 2019

    昨天作死 xff0c 因为Excel经常弹出一些奇奇怪怪的弹窗 xff0c 我去百度搜索 xff0c 没有找到答案 然后我发现大家都说最有效的办法是卸载了重新安装 xff0c 于是一键就卸载完了 然而 xff0c 最让我担心的事情发生了 x
  • 如何用java打印出JSON文件

    应老师要求 xff0c 需要打印出被剪枝的结点 xff0c 临时上网上查了资料 xff0c 我们需要下面的东西 xff1a 1 org json jar 下载之后把所有文件单独放在项目新建的文件夹org json下即可 2 我们需要知道两个
  • 关于apt update 的产生的一个问题

    E Release file for http mirrors 163 com ubuntu dists bionic updates InRelease is not valid yet invalid for another 1天 12
  • python在打开GBK格式的txt文件时无法用UTF-8格式读取

    如标题 xff0c 可以曲线救国 xff0c 把GBK文件转换成UTF 8文件 方法 xff1a 打开记事本 xff0c 点击另存为 xff0c 下面有编码 xff0c 选择UTF 8即可 美滋滋
  • dpkg和pip在ubuntu下查找所安装的包

    目录 原因结论 原因 这些天在弄ubuntu的时候 xff0c 想查看一些包的版本 xff0c 然后上网查了一下如何去做 一开始 xff0c 我就搜到利用下面这个语句 dpkg span class token operator span
  • Docker容器挂载本地共享文件夹

    Docker挂载本地目录的方法 Docker容器启动时 xff0c 我们可以使用 v参数来挂载主机下的一个目录 比如 xff0c 我需要启动一个ubuntu的容器 xff0c 并把 opt文件挂载在这个容器上做共享文件夹 a3551444f
  • 【论文解读 ICEIT2022】Heterogeneous Graph Based Knowledge Tracing基于异构图的知识追踪

    文章目录 摘要1 引言2 相关工作2 1 知识追踪2 2 异构图嵌入 3 基于异构图嵌入的知识追踪4 实验5 结论 依然是两阶段 摘要 最近 xff0c 随着在线辅导系统的发展 xff0c 对知识追踪 Knowledge Tracing 的
  • 【AAAI22】Interpretable Knowledge Tracing: Simple and Efficient Student Modeling with Causal Relations

    文章目录 摘要1 引言 可解释的知识追踪 xff1a 简单高效的因果关系学生建模 摘要 智能辅导系统在未来的学习环境中已变得至关重要 知识追踪是该系统的重要组成部分 它是关于推断学生的技能掌握和预测他们的表现 xff0c 以相应地调整课程
  • stm32CubeIDE 在自己工程中添加.c 和.h文件

    stm32CubeIDE发布已经有一段时间了 xff0c 网上也出现了好多使用教程 xff0c 但是大多数教程都是从软件的安装 gt 汉化 gt 改软件皮肤 gt 新建工程 gt 在工程的main 函数添加自己的测试代码 gt 设置调试配置
  • 快充芯片IP5328P的寄存器数据读写[用于DIY数显快充充电宝]

    本帖DIY因为有一定的危险性 xff0c 非专业人员请勿自行尝试 如有侵权 联系删除 IP5328P是一款最大18W的快充芯片 xff0c 主要用于快充充电宝的产品 xff0c 基本支持市面上绝大部分主流的快充协议 因为能看到本帖的想必都是