打印
[国产单片机]

USB PD DRP 单口DRP 充电宝原理解析(开源)

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

市面上很多充电宝基于USB PD协议具备DRP功能(可以做Source/Sink)。拥有DRP功能的充电宝只需要一个Type-C口就能满足充电/放电的功能,在产品的实际生产中可降低成本的投入并且实际使用中能够符合安全规范。
DRP功能实际就是PD芯片在Source/Sink之间进行角色切换,将PD DRP功能应用到充电宝的使用中需要注意电源角色需要以Source功能为主,这样才能保证在给DRP设备(例:手机、电脑)充电的时候能够正确输出。
(注:充电宝的电源角色之所以需要以Source为主,是为了避免给DRP设备充电时反向索取电量。例如在给手机充电过程中,充电宝的电源角色没有做Source为主的处理时,会出现手机反过来给充电宝充电。)
如下图Source时间为:200ms,Sink时间为:100ms。

代码如下:
UINT8 DRP_Set_Source(void)
{
        UINT16 Count = 200;
        UINT8 Connect_Count = 0;
        CC1_CTRL = 0x84;
        CC2_CTRL = 0x84;
        printf("Set Source\r\n");
        while(Count > 1)
        {
                ADC_CHAN = 0x00;
                ADC_CTRL |= bADC_START;
                while( (ADC_CTRL & bADC_IF) == 0 )  ;                                  /* 等待转换完成 */
                ADC_CTRL |= bADC_IF;
        //printf("Source CC =%d\n",(UINT16)ADC_DAT );                    /* 输出ADC采样值 */                /* 清标志 */
    if((UINT16)ADC_DAT < Power3_0AMax)
                {
                        Connect_Count++;
                        if(Connect_Count >= 50){
                                CCSel = 1;
                                printf("CC1 Connect!\r\n");
                                UPD_CTRL &= ~(bPD_CC_SEL);
                                PowerRole = 1;
                                return 1;
                        }
                }else{
                                        ADC_CHAN =0x01;
                                        ADC_CTRL |= bADC_START;
                                        while( (ADC_CTRL & bADC_IF) == 0 )  ;                                  /* 等待转换完成 */
                                        ADC_CTRL |= bADC_IF;                                                /* 清标志 */
        //                printf("Source CC =%d\n",(UINT16)ADC_DAT );                    /* 输出ADC采样值 */                /* 清标志 */
                                        if((UINT16)ADC_DAT < Power3_0AMax)
                      {
                                                        Connect_Count++;
                                                if(Connect_Count >= 50){
                                                        CCSel = 2;
                                                        printf("CC2 Connect! \r\n");
                                                        UPD_CTRL |= bPD_CC_SEL;
                                                  PowerRole = 1;
                                                        return 1;
                                                }
                                        }        
                                }
                mDelaymS(1);
                Count --;
        }
        return 0;
}

UINT8 DRP_Set_Sink(void)
{
        UINT16 Count = 100;
        UINT8 Connect_Count = 0;
        CC1_CTRL = 0x82;
        CC2_CTRL = 0x82;
        printf("Set Sink\r\n");
//        mDelaymS(100);
        while(Count > 1)
        {
                ADC_CHAN =0x00;
                ADC_CTRL |= bADC_START;
                while( (ADC_CTRL & bADC_IF) == 0 )  ;                                  /* 等待转换完成 */
                ADC_CTRL |= bADC_IF;                                                /* 清标志 */
        //        printf("Sink CC =%d\n",(UINT16)ADC_DAT );                    /* 输出ADC采样值 */
    if((UINT16)ADC_DAT > DufaultPowerMax)
                {
                                Connect_Count++;
                                if(Connect_Count >= 50){
                                       
                                CCSel = 1;
                                UPD_CTRL &= ~(bPD_CC_SEL);
                                printf("CC1 Connect! \r\n");
                                PowerRole = 0;
                                return 1;
                                }
                }else {
                                        ADC_CHAN =0x01;
                                        ADC_CTRL |= bADC_START;
                                        while( (ADC_CTRL & bADC_IF) == 0 )  ;                                  /* 等待转换完成 */
                                        ADC_CTRL |= bADC_IF;                                                /* 清标志 */
        //                printf("Sink CC =%d\n",(UINT16)ADC_DAT );                    /* 输出ADC采样值 */
                                        if((UINT16)ADC_DAT > DufaultPowerMax)
                                        {
                                                        Connect_Count++;
                                                        if(Connect_Count >= 50){
                                                        CCSel = 2;
                                                        UPD_CTRL |= bPD_CC_SEL;
                                                        printf("CC2  Connect!\r\n");
                                                        PowerRole = 0;
                                                        return 1;
                                                }
                                 }
         }
                        mDelaymS(1);
                Count --;
        }
        return 0;
}
现在市面上存在的产品就三种:Source(供电端例如:充电器)、Sink(受电端例如:手电筒)、DRP(供电/受电端例如:手机电脑)。
本次将使用CH543 Demo板模拟充电宝的DRP功能,会分别和充电器(Source)、设备(Sink)、手机(DRP)进行PD通讯,模拟真实应用场景下的使用。
(1)充电宝在给设备Sink充电时电源角色将切换为Source,电流方向由充电宝流入受电设备。
(2)充电宝自身电量不足时需要接充电器Source充电,此时充电宝的电源角色将切换为Sink,电流方向由外部流入充电宝内部。
(3)充电宝的主要功能就是给设备Sink充电,所以在遇到和DRP(手机电脑)连接时应多次进行判断设备的电源角色为DRP,充电宝在遇到DRP时应果断将自身电源角色转变为Source向外部供电,避免反向充电吸收外部设备的电量。
以下为三种情况下的判断代码:
 PD_Init:
                Src_Connect = 0;
                Sik_Connect = 0;
    Src_Connect = DRP_Set_Source();  //Source
          Sik_Connect = DRP_Set_Sink();   //SInk  
        
        //        printf("Src_Connect = %d   Sik_Connect = %d \r\n",(UINT16)Src_Connect,(UINT16)Sik_Connect);
                if((Src_Connect == 0)&&(Sik_Connect == 0))
                {               
                        goto PD_Init;        
                }
PD_Start:        
        if(Src_Connect == 1)
        {
        //设置成Source
    DRP_Set_Source();
    IE_USBPD = 1;
                PD_PHY_TX_SourCap();
                while(State)
                {
                         State = Check_Remove_Src();
                         mDelaymS(200);
                }
                State = 1;
                printf("DEV Remove\r\n");
                goto PD_Init;
        }
        if((Src_Connect == 0)&&(Sik_Connect == 1))
                {
                        Src_Connect = DRP_Set_Source();  //Source 400ms
                        if(Src_Connect == 0)
                        {
                                //设置成Sink
                                DRP_Set_Sink();
                                
                                PD_PHY_RX_INIT();
                                IE_USBPD = 1;
                                while(State)
                                {
                                         State = Check_Remove_Sik();
                                         mDelaymS(200);
                                }
                                State = 1;
                                printf("DEV Remove\r\n");
                          goto PD_Init;
                        }        else{
                                Sik_Connect = DRP_Set_Sink();
                                if((Sik_Connect == 1)&&(Src_Connect == 1))
                                {
                                        goto PD_Start;
                                       
                                }
                        }
        }
之所以选用CH543是因为此款芯片内置上拉电流和下拉电阻,可以软件进行切换电源角色。另外ISINK引脚具有控制FB的功能,在充电宝电源角色做主机Source时可以通过ISINK进行电压调节,下图为CH543 Demo板。

1、        CH543 Demo与充电器(Source)进行通讯。
充电器(Source)未接入Type-C口时CH543 会在Source/Sink之间来回切换。当充电器(Source)接入Type-C口, CH543电源角色处于Sink阶段的时候,才会进行PD通讯补充自身的电量。
下图为CH543与充电器(Source)协议包图,前端CC电平周期翻转是充电器(Source)未接入时CH543的电源角色在进行Source/Sink切换。后端无电平翻转是充电器(Source)介入后进行的PD通讯过程。

  

2、CH543 Demo与受电端(Sink)进行通讯。
在没有设备(Sink)接入时CH543 会Source/Sink之间来回切换。当设备(Sink)和CH543连接时,CH543处于Source阶段会检测到Sink端接入,进行判断后会进行PD通讯,实现向外部设备供电的功能。



3、CH543 Demo与DRP设备进行通讯。
本次选用的DRP设备为手机,在手机没有接入时CH543 会Source/Sink之间来回切换。当手机和CH543连接时,CH543会检测到手机为DRP设备(CH543和手机都会在Source/Sink切换角色),然后CH543会强制转换电源角色为Source后进行PD通讯,给手机进行充电。(若不强制CH543切换成Source会存在手机反向给CH543充电的可能性,此时CH543电源角色将为Sink吸收手机电量)



本次只是基本探究充电宝的工作原理,并未做出相实物。通过上述三种验证下,基本清楚了充电宝在工作时的基本原理。有兴趣的可以在此基础上继续完善,DRP的代码处理可自行下载。

CH543 PD 充电.zip

483.45 KB

充电宝DRP

使用特权

评论回复
评论
Liuhl1998 2022-7-4 11:31 回复TA
1111111111111111111111111 
Liuhl1998 2022-6-22 09:36 回复TA
@huweizhouyudan :通俗点讲,例如充电器和手机之间是SOP包通讯,手机和线缆之间是SOP‘通讯用于确定线缆是否支持Emarker功能,也就是5A大电流,充电器和线缆之间是SOP’‘,至于各种复位区分软件复位,硬件复位等……PD官方手册都有详解 
huweizhouyudan 2022-6-22 09:18 回复TA
@Liuhl1998 :这东西还是挺复杂的。SOP* 是不是包含 SOP SOP' SOP''。如果是SOP*的话是不是使用哪一种应用场景都可以。 还有什么Soft Reset 、 Hard Reset 、Cable Reset 都没搞懂 
Liuhl1998 2022-6-21 19:20 回复TA
@huweizhouyudan :往期帖子有介绍,遇到问题随时联系, 
huweizhouyudan 2022-6-21 18:05 回复TA
@Liuhl1998 :我把DEMO板 上焊了个5V的LDO 输入是40V的。刚接触PD 想学习下 
Liuhl1998 2022-6-21 18:01 回复TA
@huweizhouyudan :记得单独给CH543供电,VDD12供电5V,然后跳帽拔下来,理由是:VDD12最大耐压值只有12V,断开跳帽保护安全 
Liuhl1998 2022-6-21 17:58 回复TA
@huweizhouyudan :底层具体协议的话去网上买梦源的逻辑分析仪298米,只是看充电宝PD的话可以参照我新发的帖子 
huweizhouyudan 2022-6-21 17:24 回复TA
@Liuhl1998 :协议,我下载了你的程序试了。可以成功诱骗出5-20V的电压 
Liuhl1998 2022-6-21 17:21 回复TA
@huweizhouyudan :你是想解析协议,还是单纯的看电压呢? 
huweizhouyudan 2022-6-21 16:44 回复TA
@Liuhl1998 :你好!我的DEMO板到了,你讲解SINK请求5V 9V 12V 15V 20V 用到一个逻辑分析仪可以分析PD协议的有链接吗,我也想买个 

相关帖子

沙发
Liuhl1998|  楼主 | 2022-7-4 11:30 | 只看该作者

使用特权

评论回复
板凳
Liuhl1998|  楼主 | 2022-7-11 09:44 | 只看该作者
最近准备出个系统的DRP单口充电宝,样板在打了,使用的是三串锂电池11V标称电压,充电电压12.6V,放电电压11.1V,目前充电时准备请求9v电压,采用BOOST电路实现恒流恒压的处理,外接DCDC控制输出PDO。

使用特权

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

本版积分规则

16

主题

109

帖子

31

粉丝