赞
踩
现阶段快充的技术应用非常广泛,快充适配器在我们身边也随处可见,那快充是如何实现的呢?是不是有很多小伙伴存在这类的疑惑。那我们今天就一起来会会它,看一看快充是不是如我们想的那般神秘。
另外,我们身边有各种各样的受电设备需要不同的功率充电或运作,这时候往往需要对应着功率来配置一个适配器。那如果我们能随心所欲的去“控制”快充适配器输出对应的电压,不就能用一个快充适配器来满足不同功率设备的供电吗?这样一来就能解决原装适配器带来的限制,不再为原装适配器的丢失以及损坏而烦恼。
并且将快充的技术应用在产品中,可以摆脱设备充电时效率慢及时间长的难题,也可以满足无电池设备的功率问题。那下文我将针对最近比较流行的USB PD快充进行讲解,并演示如何控制适配器输出不同的电压。
下面我先会简易的讲解一下PD通讯过程,有兴趣想要深入了解USB PD协议的小伙伴可以到 www.usb.org 下载PD协议相关手册。
1、首先来了解PD通讯数据的基本结构:Preamble + SOP + Message + CRC + EOP。如下图:
(1) Preamble:64bit连续的0/1数据的前导码(0开头,1结尾,频率303kHZ左右)。
(2) SOP:同步码1/2/3组成(包含类型:SOP,SOP`,SOP``),告知是在与Cable/Sink通讯。
(3) Message:Header + Object 用于传递命令、请求、响应。
(4) CRC:CRC-32 用于对消息的校验。
(5) EOP:“01101”用于作为结束标志。
2、PD通讯数据的基本结构我们了解了,那么PD通讯物理层是如何收发消息的呢?废话就不多说了,接下来我将会从接受/发送两部分进行讲解。
先来说下如何发送消息,首先将数据Data和校验码CRC进行4b5b编码后通过BMC发送到CC线上,这就完成PD消息的发送,是不是很简单,也没那么神秘吧!如下图:
至于接收消息刚好和发送消息反过来,当检测到CC上有消息到来时,物理层会通过BMC进行接收,然后检查SOP类型,最后进行4b5b解码,将会得到数据Data和CRC校验码。如下图:
3、讲到这里应该有小伙伴开始对4b5b编解码、BMC编解码很疑惑吧?其实 4b5b是PD通讯规定的数据手段,这样能有效的避免数据在传输时造成传输错误。BMC编解码则是在数据4b5b转换的基础上进行电平的翻转(0不变,1翻转)。那么数据是如何进行4b5b转换呢?USB PD手册中给出了解答,如下图:
通过上述简易的分析,可以了解USB PD收发消息的基本概念,能得出PD通讯是需要基于一些硬性条件,比如:需要4b5b编解码、BMC发送、消息校验等。至于博主为什么会在众多单片机产品中选择CH543而不是其它单片机呢?是因为 CH543内置了USB PD收发器PHY和USB Power Delivery控制器,另外PD通讯时是可以自动BMC编解码、4B5B编解码、CRC校验。这样一来不仅能大量的节约代码空间,还能减轻工程带来的难度(嘿嘿,因为不用进行4B5B转码,不用CRC校验,也不用编写前导包。这些都好折磨人,现在可就轻松了不少)。
并且CH543是利用USB PD中断来处理PD消息,这一功能是很多单片机不具备的,一般的单片机是通过在while(1)循环中采用查询的方式进行收发消息,这样不仅大量的占用主函数代码空间,同时还会造成代码阅读上不必要的困扰,这样对比一下CH543还是蛮香的。
接下来进入主题了,来看下硬件方面的设计吧,在硬件方面使用了CH543主控MCU的两个引脚(P10:CC1和P11:CC2),就可以轻松实现PD Sink端(是不是觉得不可思议),工程使用的demo板是从www.wch.cn那里申请,有兴趣的小伙伴可以去看看。硬件原理图如下:
现在就来看下效果:
硬件方面讲完了,下面来看一下软件方面的处理,我这次编写的是PD Sink受电端,有兴趣的小伙伴可以根据PD快充通讯具体流程(如下图),反推出写出Source供电端(可以做个简易版的适配器)。另外还可以查阅PD 相关资料进行拓展编写VDM、PPS消息等。本文代码将会在文章最后打包奉上(包含:Source、Sink、VDM)。
我本次编写的是受电端Sink,由上图可以知道PD快充的基本操作流程,那么我只需要在合适的场景下及时回复Good CRC和Request,就能完成USB PD通讯。在消息处理上,我是根据CH543 USB PD中断的特点来进行相应消息处理,软件如下:
- void PD_PHY_ISR(void) interrupt INT_NO_USBPD using 1
- {
- if ( PIF_RX_RST ) {/*接收到复位信息中断*/
- printf("RST ");
- PD_PHY_HRST_ISR(); //收到HRST
- PD_PHY_RX_INIT();
- }
- if ( PIF_RX_ACT ){/*数据包接受完成中断*/
- TR0 = 0; ET0 = 0;
- 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){
- PD_PHY_STAT.WaitingGoodCRC = 0;
- if(PD_PHY_STAT.SendingRequest == 1){ PD_PHY_STAT.SendingRequest = 0;}
- Send_Count = 0;
- PD_PROT_ISR();
- }
- }else {
- switch(Union_Header->HeaderStruct.MsgType)
- {
- case SourceCap:
- NDORcv=Union_Header->HeaderStruct.NDO;
- memcpy(PD_Source,PD_RX_BUF,30);
- PD_PHY_STAT.SendingRequest = 1;
- break;
- case Request:
- break;
- case Accept:
- MsgID ++;
- break;
- case Reject:
- break;
- case PS_RDY:
- break;
- case GetSrcCap:
- MsgID++;
- PD_PHY_STAT.SendingSourceCap = 1;
- break;
- case GetSinkCap:
- MsgID++;
- PD_PHY_STAT.SendingSinkCap = 1;
- break;
- case SourceCap_VDM:
- break;
- default :
- break;
- }
- mDelayuS(25);
- 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;
- mTimer_x_SetData(10000); //5ms
- PD_PHY_RX_INIT();
- }
- }
- }
因为作为Sink端请求电压是最为重要的,那么该如何来请求电压呢?里面将会涉及到怎样的知识点?下图就详细讲解了PD Request数据各个位的作用。有兴趣的小伙伴可以查阅USB PD协议对应着理解。
根据上图提示,进行软件编写Request,因为Request包含一个请求项Data Object,所以NDO固定为1(表示Header之后有几个字节的数据)。
Message ID是根据消息次序来决定(一般Sink发送Request为起始0,后续Sink发送时ID自动加一,回复Good CRC除外),Message ID最大为7,若超过则从0重新计数。
PorPwrRole表示电源角色,Source为1,Sink为0。
Rev2表示PD的版本信息,0x01表示PD2.0,0x10表示PD3.0。
PortDataRole表示数据角色,根据需求来填写主从,1表示主,0表示从。
MessageType表示此项内容是什么类型数据,0x02表示Request,0x01表示GoodCRC。
Objpos 表示请求SourceCap档位中的第几项,1:第一项、2:第二项、、、、
Capability Mismatch表示能力不匹配,0:匹配,1:不匹配。
USB Communications 表示USB通讯能力,按需求配置。
No USB Suspend 表示没有USB挂起,0:有USB挂起,0:没有USB挂起。
Unchunked Extended Message 未分块的扩展信息。
Operation Current in 10mA units表示请求电压的电流大小。
Max Operation Current in 10mA units表示最大承受电流。
下面是用CH543编写Request的代码:
- void PD_PHY_TX_Request(void)
- {
- UINT16 Volt_Value;
- UINT8 temp=0xff; //pdo 档位
- UINT8 i;
- UINT16 Temp;
- UINT16 Data_H8;
- UINT16 Cur_Temp = 0;
-
- for (i=0;i!=NDORcv;i++)
- {
- Union_SrcCap = (_Union_SrcCap *)&PD_Source[2+(4*i)];
- Data_H8 = (Union_SrcCap->SrcCapStruct.DataH8);
- if((Data_H8 >> 6 ) == 3)
- {
- PPS_Flag = 1;
- printf("\r %d is PPS\n",(UINT16)(i+1));
- }else{
- Temp = (PD_Source[3+(i<<2)] >> 2)+((PD_Source[4+(i<<2)] & 0x0F)<<6);
- Temp*=50;
- if (Temp <= Volt_Value )
- {
- if(Temp > Cur_Temp)
- {
- Cur_Temp = Temp;
- temp = i+1;
- }
- }
- }
- }
- if(Temp_PDO != temp )
- {
- printf("No requested voltage! \r\n");
- printf("Request adjacent voltage! \r\n");
- }
- if(temp != 0xff)
- {
- UPD_T_SOP = UPD_SOP0;
- UPD_T_LEN = 6;
- PD_TX_BUF[5] =( (temp<<4) | 0x02);
- PD_TX_BUF[4] = ((PD_Source[3+((temp - 1)<<2)]&0x03)<<2) |(PD_Source[2+((temp - 1)<<2)]>>6) | (PD_Source[4+((temp - 1)<<2)] &0xF0);
- PD_TX_BUF[3] =(PD_Source[3+((temp - 1)<<2)]&0x03) | (PD_Source[2+((temp - 1)<<2)]<<2);
- PD_TX_BUF[2] = PD_Source[2+((temp - 1)<<2)];
- PD_TX_BUF[1] = (0x10 | (MsgID << 1));
- PD_TX_BUF[0] =0x02 | (0xC0 & PD_Source[0]);
- PD_PHY_TX_INIT();
- }else{
- printf("No Matched Volt.\r\n");
- }
- }
相信很多小伙伴都有发现PD进行充电时,充电电压并不是一直保持不变的,而是可以动态切换请求电压,那是如何进行动态切换的呢?动态请求电压会出现什么样的现象?针对这一个疑惑,我就利用IO中断来对请求的档位进行加减,实现这样现象。软件代码如下:
- if(Gears_Plus == 1)
- {
- if(P1_5 == 1)
- {
- PD_Request_Gears += 1;
- Gears_Plus = 0;
- }
- if(PD_Request_Gears>5)
- {
- PD_Request_Gears = 1;
- }
- }
- if(Gears_Sub == 1)
- {
- if(P1_4 == 1)
- {
- PD_Request_Gears -= 1;
- Gears_Sub = 0;
- }
- if(PD_Request_Gears<1)
- {
- PD_Request_Gears = 5;
- }
- }
通过验证动态请求电压是可行的(如下图),这样的话各位小伙伴可以利用快充适配器来得到一个动态电压(5V、9V、12V、15V、20V),提供给不同的用电设备使用,也可以将USB PD快充的技术应用到自己的产品中,不就能摆脱了传统充电时间长和功率小的问题了嘛!
至此PD Sink端的应用就要告一段落了,附件是硬件、软件资料,小伙伴们可以按需下载。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。