打印
[电源技术资料]

开源PD快充触发器Power Low(受电端Sink,支持PD、BC等多协议)

[复制链接]
10176|46
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 Liuhl1998 于 2022-7-11 09:36 编辑

提到快充协议都会想到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)

以下为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的协议规范。



附件后续会上传,目前需要进行优化一些功能。



使用特权

评论回复

相关帖子

沙发
Liuhl1998|  楼主 | 2022-6-17 13:37 | 只看该作者
快充协议的普及某种程度上来说就是得益于智能手机的普及,对我们用户的直接影响就是提升了充电性能、降低了等待时间。对于快充协议,其实说白了就是让多个设备厂家来共同支持一个相互识别设备的通用协议,可以确保这些支持协议设备在快充上的安全性、高效性。目前的快充协议上有些杂乱,比如华为SuperCharge(SCP)、OPPO闪充VOOC,高通QuickChange、一加WARP、MTK的PE3.0等快充体系, 但由于协议的不同,一些不同品牌手机的原装快充头并不通用,只能搭配原厂充电头为自家手机进行充电,极大的限制了用户的使用。某种程度上来说这是导致USB-PD协议出现的原因,目前的USB-PD 3.0协议已经包含了高通QC 3.0与4.0,华为的SCP与FCP, MTK的PE3.0与PE2.0, OPPO的VOOC,但一加WARP仍旧未加入进来。

使用特权

评论回复
板凳
lwdz21| | 2022-6-17 16:03 | 只看该作者

使用特权

评论回复
地板
Liuhl1998|  楼主 | 2022-6-20 09:59 | 只看该作者

使用特权

评论回复
5
Liuhl1998|  楼主 | 2022-7-11 09:35 | 只看该作者
目前可以动态触发固定挡位的PDO,以及PPS的触发和退出。目前看没啥人关注,所以一直没上传源码,感兴趣的可以说下,我分享,开源

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
樱花树 + 1 赞一个!
6
devildcg| | 2022-9-21 15:30 | 只看该作者
本帖最后由 qbwww 于 2023-1-28 21:42 编辑
Liuhl1998 发表于 2022-7-11 09:35
目前可以动态触发固定挡位的PDO,以及PPS的触发和退出。目前看没啥人关注,所以一直没上传源码,感兴趣的可 ...

可 以分享开源吗,正在研究这个。万分感谢 735568187@qq.com

使用特权

评论回复
7
hbsun| | 2022-10-3 09:43 | 只看该作者
求分享开源。万分感谢 859482555@qq.com

使用特权

评论回复
8
Liuhl1998|  楼主 | 2022-10-13 09:46 | 只看该作者
hbsun 发表于 2022-10-3 09:43
求分享开源。万分感谢 859482555@qq.com

已发送

使用特权

评论回复
9
gihr09| | 2022-10-20 19:21 | 只看该作者
最近正在研究这个,求分享,万分感谢873801757@qq.com

使用特权

评论回复
10
橘橘吃橘橘| | 2022-11-3 15:37 | 只看该作者
Liuhl1998 发表于 2022-7-11 09:35
目前可以动态触发固定挡位的PDO,以及PPS的触发和退出。目前看没啥人关注,所以一直没上传源码,感兴趣的可 ...

您好,最近在研究这方面,求分享,谢谢!615832287@qq.com

使用特权

评论回复
11
Liuhl1998|  楼主 | 2022-11-4 14:50 | 只看该作者
橘橘吃橘橘 发表于 2022-11-3 15:37
您好,最近在研究这方面,求分享,谢谢!615832287@qq.com

ok

使用特权

评论回复
12
Liuhl1998|  楼主 | 2022-11-4 14:50 | 只看该作者
gihr09 发表于 2022-10-20 19:21
最近正在研究这个,求分享,万分感谢

ok         

使用特权

评论回复
13
yingjieso| | 2022-11-7 07:03 | 只看该作者
看起来很牛啊,我也求分享719959167@qq.com

使用特权

评论回复
14
cj519| | 2022-11-8 06:47 | 只看该作者
您好,正好用到,求分享,谢谢!gacj@163.com

使用特权

评论回复
15
樱花树| | 2022-11-10 19:17 | 只看该作者
Liuhl1998 发表于 2022-7-11 09:35
目前可以动态触发固定挡位的PDO,以及PPS的触发和退出。目前看没啥人关注,所以一直没上传源码,感兴趣的可 ...

求分享开源,楼主很给力 想了解一下PD底层和VDM消息 1542914807@qq.com

使用特权

评论回复
16
樱花树| | 2022-11-13 22:00 | 只看该作者
求分享开源,楼主很给力 想了解一下PD底层和VDM消息 1542914807@qq.com  万分感谢

使用特权

评论回复
17
Liuhl1998|  楼主 | 2022-11-14 10:05 | 只看该作者
樱花树 发表于 2022-11-13 22:00
求分享开源,楼主很给力 想了解一下PD底层和VDM消息   万分感谢

VDM 查看PD手册,VDM可以表示不同功能  ,比如Emark线缆,比如DP输出等

使用特权

评论回复
18
樱花树| | 2022-11-18 12:40 | 只看该作者
Liuhl1998 发表于 2022-11-14 10:05
VDM 查看PD手册,VDM可以表示不同功能  ,比如Emark线缆,比如DP输出等

楼主方便发一下源码学习一下吗

使用特权

评论回复
19
Liuhl1998|  楼主 | 2022-11-21 10:15 | 只看该作者
樱花树 发表于 2022-11-18 12:40
楼主方便发一下源码学习一下吗

邮箱留下

使用特权

评论回复
20
Liuhl1998|  楼主 | 2022-11-21 11:22 | 只看该作者
最近需要二次改版,到时候PCB,原理图,代码一并附上。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

16

主题

109

帖子

31

粉丝