PD等多协议快充诱骗触发器SINK(“Power Z 弟弟 Power Low”)DIY

提到快充协议都会想到USB PD快充,实际市面上还有很多主流的快充协议,比如华为的FCP、SCP,三星的AFC,OPPO的VOOC,高通的QC,VIVO的Flash Charge等……,如此之多的快充协议该如何来辨别?相信很多电粉和相关的开发人员应该都知道PowerZ这款性能强悍的诱骗产品,支持QC2.0、QC3.0、VOOC、SCP、SSCP、PD等协议的触发。本期将使用CH543制作一个简易版的诱骗器Power Low。

以上是利用CH543设计的简易版电路原理图,可通过DM、DP、CC来实现主要的诱骗功能,通过DM、DP来触发QC、AFC、FCP等协议,通过CC触发PD协议。屏幕显示采用SPI驱动的TFT:ST7735S(占用片外和片内资源,后续将更换成I2C驱动的屏)。设计中还使用了Power Z一样的三档拨轮开关,用来选择档位和功能操作等。整体电路设计下来参考价格在15元左右,主要是TFT比较贵,不然可以将成本压缩在10元以内。
因为某些快充协议属于私有协议,处于未公开状态,第三方需要取得授权才可以使用,所以本次将围绕USB PD快充的诱骗触发来讲解。首先诱骗器的定位是Sink受电端,所以CC引脚上必须要有5.1K的下拉电阻,才能让Source供电端进行识别送电。系统默认请求5V电压,可通过三挡拨轮开关进行选择Fixed或者PPS,同时可以调节选择请求不同的电压。具体的实物效果如下:

很Power Low  Low  Low  Low  Low ……

以下为PD通讯协商过程,利用PD中断来解析Source发送的协议包,收到SourceCap包时会将具体内容进行缓存在PDO_BUF中:

/*******************************************************************************
* Function Name  : PD_PHY_ISR(void)
* Description    : PD中断处理函数
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void PD_PHY_ISR(void) interrupt INT_NO_USBPD using 1
{
/*接收到复位信息中断*/
	if ( PIF_RX_RST ) {
		PD_PHY_HRST_ISR();		//收到HRST
		PD_PHY_RX_INIT();
	}
/*数据包接受完成中断*/
	if ( PIF_RX_ACT ){
			PIF_RX_ACT = 0;
		if ( (UPD_INT_FG & MASK_PD_STAT) == PD_RX_SOP0 ) {     	//收到HRST或SOP数据
		  	Union_Header = (_Union_Header *)PD_RX_BUF;          //强制转化			
			if ( PD_PHY_STAT.WaitingGoodCRC ) {	                  //是否在等待GoodCRC
				if(Union_Header->HeaderStruct.MsgType == GoodCRC){  //判断收到的消息是否为GOODCRC
					PD_PHY_STAT.WaitingGoodCRC = 0;	  	 
					PD_PHY_Clear_Flag();                              //清除标志函数
					PD_PROT_ISR();      					
				}
			}else {		
					switch(Union_Header->HeaderStruct.MsgType)
					{						 
						case SourceCap:	
							  	memcpy(PDO_BUF,PD_RX_BUF,sizeof(PD_RX_BUF)); 
						    	Versions = Union_Header->HeaderStruct.SpecRev;
						      SourceCapNDO = Union_Header->HeaderStruct.NDO;
                  RecvPDOFlag = 1;              //修改RecvPDOFlag = 1 开启解析PDO,为0则关闭,若开启后本次回复GOODCRC时间会适当延长,此处默认开启
								  PD_PHY_STAT.SendingRequest = 1;
								 break;
						case Accept:	               
								 break;
						case Reject:
								 break;
						case PS_RDY:
							   RecvPS_RDYFlag = 1;
								 break;	 
						case GetSinkCap:
								 MsgID++;
								 PD_PHY_STAT.SendingSinkCap = 1;	  
								 break;		 
					  case SourceCap_VDM: 
						     MsgID++;
						     PD_PHY_STAT.SendingNotSup = 1;
								 break;	
						default :
						break;	
					}
						mDelayuS(10);
					  PD_PHY_STAT.SendingGoodCRC = 1;	//置发送GoodCRC标志位
						PD_PHY_TX_GoodCRC();			    	//回复GoodCRC	
			}	
	}else PD_PHY_RX_INIT();
}
/*数据包发送完成中断 */
	if ( PIF_TX_END ) {		
	  	PIF_TX_END = 0;
			if(CCSel == 1){  //发送完成关闭低压
				CC1_CTRL &= ~bCC_LVO;	
			}else if(CCSel == 2){
			 CC2_CTRL &= ~bCC_LVO;	
			}
		if ( PD_PHY_STAT.SendingGoodCRC ==1 ) {                       
			PD_PHY_STAT.SendingGoodCRC = 0;
			PD_PROT_ISR(); //GoodCRC发送完成,向Prot转交数据
		}else {			/*开始接收GoodCRC*/
					PD_PHY_STAT.WaitingGoodCRC = 1;	
					Timer_Counter = Save_Counter;
					PD_PHY_RX_INIT();	
		}
	}
}

本段用来解析Source支持PD协议的具体档位,发生在一次PD协商结束时,此时RecvPS_RDYFlag = 1,解析上述缓存在PDO_BUF中的SourceCap包,并显示在屏幕(后续会精简优化代码):


/*******************************************************************************
* Function Name  : Analysis_PDO(void)
* Description    : 解析PDO、PPS函数
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void Analysis_PDO(void)
{
	UINT8 Temp;
	UINT16 PDO_Value = 0;
 if(RecvPDOFlag == 1){
    LCD_Fill(0,0,159,12,CYAN);
		LCD_DrawLine(0,0,159,0,CYAN);
		LCD_DrawLine(0,0,0,127,CYAN);
		LCD_DrawLine(159,0,159,127,CYAN);
		LCD_DrawLine(0,127,159,127,CYAN);
		if(Versions == 2) //判断PD版本
		{
			LCD_ShowString(3,0,"Power Delivery 3.0",BLACK,CYAN,12,0);
		}else{
			LCD_ShowString(3,0,"Power Delivery 2.0",BLACK,CYAN,12,0);
		}
	 
    Union_Header = (_Union_Header *)PDO_BUF;  //解析SourceCap
		for(Temp=0;Temp<SourceCapNDO;Temp++)//pdo的档位
		{
		 Union_SrcCap = (_Union_SrcCap*)(&PDO_BUF[2+(Temp*4)]);
		 if((Union_SrcCap->SrcCapStruct.DataH8>>6)== 0x00)  //表示固定档
		 {
			 PDO_Value =((((Union_SrcCap->SrcCapStruct.VoltH4<<6)+( Union_SrcCap->SrcCapStruct.VoltL6))*50)/100);
			 if( PDO_Value/10 >= 10) //电压
			 {
				  LCD_ShowFloatNum1(108-7*6,(Temp+1)*12,(float)PDO_Value/10,4,CYAN,BLACK,12);
			 }else{
				 LCD_ShowFloatNum1(108-6*6,(Temp+1)*12,(float)PDO_Value/10,3,CYAN,BLACK,12);
			 }
			  PDO_Value=((((Union_SrcCap->SrcCapStruct.CurrentH2<<8)+( Union_SrcCap->SrcCapStruct.CurrentL8))*10)/10); //电流
			  LCD_ShowFloatNum1(120,(Temp+1)*12,(float)PDO_Value/100,3,CYAN,BLACK,12);
			 
			    LCD_ShowString(108,(Temp+1)*12,"@",CYAN,BLACK,12,0);
				 	LCD_ShowString(3,(Temp+1)*12,"< > Fix",CYAN,BLACK,12,0);
				  LCD_ShowIntNum(10,(Temp+1)*12,Temp+1,1,CYAN,BLACK,12);
				  LCD_ShowString(108-2*6,(Temp+1)*12,"V",CYAN,BLACK,12,0);
				  LCD_ShowString(145,(Temp+1)*12,"A",CYAN,BLACK,12,0);
			 
		 }else if((Union_SrcCap->SrcCapStruct.DataH8>>6)== 0x03){//表示PPS
				Union_PPS_SrcCap = (_Union_PPS_SrcCap*)(&PDO_BUF[2+(Temp*4)]);  //转换为PPS                         
		       
					PDO_Value = (Union_PPS_SrcCap->SRC_Cap_PPS_Struct.VoltMin);  
          if(PDO_Value/10 >= 10)
					{
						 LCD_ShowFloatNum1(111-10*6,(Temp+1)*12,(float)PDO_Value/10,4,CYAN,BLACK,12);
						
					}else{
						LCD_ShowFloatNum1(111-9*6,(Temp+1)*12,(float)PDO_Value/10,3,CYAN,BLACK,12);
					}
			 
          PDO_Value = ((Union_PPS_SrcCap->SRC_Cap_PPS_Struct.VoltMaxH1<<7) + (Union_PPS_SrcCap->SRC_Cap_PPS_Struct.VoltMaxL7));
					LCD_ShowString(75,(Temp+1)*12,"-",CYAN,BLACK,12,0);
					if(PDO_Value/10 >= 10)
					{
						 LCD_ShowFloatNum1(108-4*6,(Temp+1)*12,(float)PDO_Value/10,4,CYAN,BLACK,12);
					}else{
						LCD_ShowFloatNum1(108-3*6,(Temp+1)*12,(float)PDO_Value/10,3,CYAN,BLACK,12);
					}
					PDO_Value = ((Union_PPS_SrcCap->SRC_Cap_PPS_Struct.Current)*50)/10;
					LCD_ShowFloatNum1(120,(Temp+1)*12,(float)PDO_Value/100,3,CYAN,BLACK,12);
				 	LCD_ShowString(3,(Temp+1)*12,"< > PPS",CYAN,BLACK,12,0);
				  LCD_ShowIntNum(10,(Temp+1)*12,Temp+1,1,CYAN,BLACK,12);
				  LCD_ShowString(108,(Temp+1)*12,"V",CYAN,BLACK,12,0);
				  LCD_ShowString(145,(Temp+1)*12,"A",CYAN,BLACK,12,0); 
			 }
		 }

		 	LCD_ShowString(44,(Temp+2)*12-6,"Fixed",BLACK,CYAN,12,0);
		  LCD_ShowString(92,(Temp+2)*12-6,"PPS",CYAN,BLACK,12,0);
 	RecvPDOFlag = 0;
	 }
}


因A口协议属于未公开状态,本次将不进行讲解。有兴趣的小伙伴可以多了解一下,附送一张QC2.0的协议规范。
 
 

 后续会上传附件,在此处公开资料代码和PCB等,开源。多协议电源诱骗触发器Power Low(可多快充协议PD、QC等) - 电源论坛_电源技术论坛 - 21ic电子技术开发论坛https://bbs.21ic.com/icview-3232588-1-1.html

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值