[国产单片机] USB Type-C拓展DisplayPort and USB2.0(基于PD通讯开源资料)

[复制链接]
 楼主| Liuhl1998 发表于 2022-3-31 20:41 | 显示全部楼层 |阅读模式
本帖最后由 Liuhl1998 于 2022-4-8 15:51 编辑

我们的电脑现在大多都只有一个Type-C端口,不能挂载多余的外设,为了解决这一问题,便产生了Type-C扩展坞。拓展坞是常用于笔记本电脑的一种外置设备,可以扩展、丰富笔记本的外接端口,使得笔记本可以连接多个外置设备(例如显示器、U盘、SD卡、TF卡、投影仪等)。
说到Type-C拓展坞就不得不提及USB PD,想必大家一听到USB PD都会下意识想到PD快充,实际上USB PD还有Alternate Mode等拓展功能,并且是Type-C拓展坞最核心的知识点。下面便基于CH543D进行了拓展设计,实现单口Type-C转Display Port口和USB 2.0口(简易版),效果演示如下:


CH543D拓展坞方案的数据协商过程是在USB PD快充的基础上增加了VDM的数据处理,同样是在CC线上进行(确定主机端和设备端)。通过VDM协商后,便能实现单口Type-C转Display Port和USB 2.0,具体的协商过程如下:
1、上图为USB PD快充的协议流程(相关解析请查阅上篇**)。当PD快充在CC线上完成后,主机将会对设备发送VDM类请求,如下图:

上图为VDM协商的具体流程,相关解析如下:
1、主机会先发送 Disc IDENT类请求(0xff008001/0xff00A001),设备进行响应回复Good CRC和ACK(0xff008041/0xff00A001)。
2、主机收到ACK响应后回复Good CRC,然后进行下一步请求Disc SVID(0xff008002/0xff00A002),设备进行响应回复Good CRC和ACK(0xff008042/0xff00A042)。
3、主机收到ACK响应后回复Good CRC,然后进行下一步请求Disc Mode(0xff018003/0xff01A003),设备进行响应回复Good CRC和ACK(0xff018043/0xff01A043)。
4、主机收到ACK响应后回复Good CRC,然后进行下一步请求Enter Mode 1(0xff018104/0xff01A104),设备进行响应回复Good CRC和ACK(0xff018144/0xff01A144)。
5、主机收到ACK响应后回复Good CRC,然后进行下一步请求DP Stat POS 1(0x ff018110/0x ff01A110),设备进行响应回复Good CRC和ACK(0xff018150/0xff01A150)。
6、主机收到ACK响应后回复Good CRC,然后进行下一步请求DP Configure POS 1(0x ff018111/0x ff01A111),设备进行响应回复Good CRC和ACK(0xff018151/0xff01A151)。


基本的协议架构参考上述,下面开始进行实践,硬件采用的是:“沁恒微电子”的CH543D芯片,CH543D 内置了 USB Power Delivery 控制器和 PD BMC PHY 收发器,支持 USB type C、BC、PD2.0、PD3.0、PPS,还支持 12V 高压电源。PD通讯时需要的BMC编解码、4B5B编解码、CRC校验也都有集成,这样的话使用CH543来实现USB PD通讯是比较简单的。


在原理图中使用了Type-C公口,并在端口出外加1.2K下拉电阻做E-mark处理(CH543内置5.1K下拉电阻和外置1.2K下拉电阻并联后为1K下拉电阻,E-mark处理可提升兼容性),若使用Type-C母口,需做正反插检测处理(差分信号需要进行切换)。
原理图中USB 2.0母口和Type-C母口直接相连,通过USB PD协议沟通确认数据的主从关系后,便可以实现一个USB 2.0通讯接口(本文为拓展坞的简易版,只采用了USB 2.0。感兴趣的小伙伴可以尝试升级为USB 3.0通讯口)。
另外,值得注意的是原理图中采用了多组差分线,可以有效的保证视频传输时的稳定和高效性。另外Display Port拉电阻的处理是重点,并做了HPD检测处理。为了达到节约成本的同时提高性能,在应用中增加了USB 2.0母口,同时省略了一个Type-C下载母口(图中Type-C下载用JP1排针进行代替),如此一来就能实现拓展坞的基本功能。


VDM消息包含:Header + VDM Header + 消息内容,在VDM消息中:Header下的Message Type都是一致的为:0x0f只能判断消息是否属于VDM,不能区分VDM的具体类型(如下图)。

  为了能区分VDM的具体数据类型,所以在工程中增加了解析VDM Header的结构体:_VDM_Hdr_Struct。结构体中的Command可以用来区分VDM具体类型,代码如下:

  1. /* VDM Header*/
  2. typedef struct  {

  3.         UINT16 ModeIndex:3;
  4.         UINT16 :2;
  5.         UINT16 SVDMVer:2;
  6.         UINT16 StructuredVDM:1;
  7.         
  8.         UINT16 Command:5;
  9.         UINT16 :1;
  10.         UINT16 CommandType:2;


  11.   UINT16 SVIDH8:8; //00 ff
  12.   UINT16 SVIDL8:8;
  13. } _VDM_Hdr_Struct;
  14. typedef union {
  15.         _VDM_Hdr_Struct  VDMHdrStruct;
  16.         UINT8 VDMHdrData[4];
  17. } _Union_VDM_Hdr;


VDM数据类型可以区分后,下面来讲解VDM通讯流程。前面有提及VDM是基于USB PD快充的(有关USB PD快充的知识点,请参考“PD快充也没那么神秘”),接下来将会围绕着VDM进行讲解。因为VDM接收/发送的消息“相对固定”,所以在工程中用数组方式进行了固定处理,代码如下:
  1. /*       VDM       */
  2. UINT8C  ACK_Disc_Ident[ ] =
  3. {
  4.         0xc9,0x1f,0x00,0x6c,
  5.         0xa8,0x5e,0x02,0x00,
  6.         0x10,0x01,0x02,0x50,
  7.         0x39,0x00,0x00,0x11        
  8. };
  9. UINT8C  ACK_Disc_SVID[ ] = {0x00,0x00,0x01,0xff};
  10. /* 四线,仅支持模式C */
  11. #if 1
  12. //VDM 模式列表
  13. UINT8C  ACK_Disc_Mode[ ] = {0x05,0x04,0x00,0x00};
  14. //VDM DP状态
  15. UINT8C  ACK_DP_Stat_Pos_1[ ] ={0x0a,0x00,0x00,0x00};
  16. #else
  17. /* 两线,支持C D模式,prefer D模式 */
  18. UINT8C  ACK_Disc_Mode[ ] = {0x05,0x0C,0x00,0x00};
  19. UINT8C  ACK_DP_Stat_Pos_1[ ] = {0x1a,0x00,0x00,0x00};
  20. #endif
  21. UINT8C DPAttention_Table[ ] =                                                //VDM DP拔插状态
  22. {
  23.         0x06,0x81,0x01,0xff,
  24.         0x8a,0x00,0x00,0x00
  25. };
  26. UINT8C DPAttention_Table_1[ ] =                                                //VDM DP拔插状态
  27. {
  28.         0x06,0x81,0x01,0xff,
  29.         0x0a,0x00,0x00,0x00
  30. };
接下来严格按照VDM的协商流程(参考VDM协商流程图),完成相关通讯。软件如下:
  1. switch(Union_Header->HeaderStruct.MsgType)
  2.                                         {
  3.                                                 case SourceCap:
  4.                                                                  PD_PHY_STAT.SendingRequest = 1;
  5.                                                                  break;
  6.                                                 case Accept:
  7.                                                                  break;
  8.                                                 case Reject:
  9.                                                                  break;
  10.                                                 case PS_RDY:
  11.                                                                  break;
  12.                                                 case GetSinkCap:
  13.                                                                  MsgID++;
  14.                                                                  PD_PHY_STAT.SendingSinkCap = 1;         
  15.                                                                  break;
  16.                                           case SourceCap_VDM:
  17.                                                           Union_VDM_Hdr = (_Union_VDM_Hdr *)&PD_RX_BUF[2];
  18.                                                     switch(Union_VDM_Hdr->VDMHdrStruct.Command)
  19.                                                                 {
  20.                                                                         case 1:
  21.                                                                                 MsgID++;
  22.                                                                                 PD_PHY_STAT.SendingACK_Disc_Ident = 1;        
  23.                                                                                 break;
  24.                                                                         case 2:
  25.                                                                                 MsgID++;
  26.                                                                           PD_PHY_STAT.SendingACK_Disc_SVID = 1;        
  27.                                                                                 break;
  28.                                                                         case 3:
  29.                                                                                 MsgID++;
  30.                                                                           PD_PHY_STAT.SendingACK_Disc_Mode = 1;
  31.                                                                                 break;
  32.                                                                         case 4:
  33.                                                                                 MsgID++;
  34.                                                                           PD_PHY_STAT.SendingACK_Enter_Mode = 1;
  35.                                                                                 break;
  36.                                                                         case 16:
  37.                                                                                 PD_PHY_STAT.SendingACK_DP_Stat_Pos_1 = 1;
  38.                                                                                 MsgID++;
  39.                                                                                 break;
  40.                                                                         case 17:
  41.                                                                                 PD_PHY_STAT.SendingACK_DP_Configure_Pos_1 = 1;
  42.                                                                           MsgID++;
  43.                                                                           break;               
  44.                                                                 }        
  45.                                                                  break;        
  46.                                                 default :
  47.                                                 break;        

至此CH543D的VDM操作就结束了,通过以上操作便可以实现单口Type-C转Display Port口和USB 2.0口,感兴趣的小伙伴可以在此基础上继续升级改造(例如USB 3.0、U盘、SD卡、TF卡、投影仪等)。附件是硬件、软件资料,小伙伴们可以按需下载。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×

评论

好久没看到这么牛X的文章咯。  发表于 2024-3-21 14:06
厉害了啊,好久没看到这么好的文章了  发表于 2022-12-4 23:18
 楼主| Liuhl1998 发表于 2022-4-6 13:23 | 显示全部楼层
本帖最后由 Liuhl1998 于 2022-4-8 09:34 编辑

相关资可以联系楼主
 楼主| Liuhl1998 发表于 2022-4-11 10:00 | 显示全部楼层
本帖最后由 Liuhl1998 于 2022-4-12 10:13 编辑

  ;
iamOJZ 发表于 2022-4-15 21:55 | 显示全部楼层
膜拜巨佬,之前就有想法用CH543做DP ALE相关的应用,不过由于知识匮乏做不出来。看到大佬的Demo想询问下大佬几个问题:1、DisplayPort拉电阻部分具体有什么要求嘛,比如要上拉还是下拉,阻值控制多少。2、若要使用C口母座,如何通过CC通信来控制MUX芯片实现正反插识别(协议层)。最后再次感谢大佬对于DP ALE方面应用的贡献!!!
 楼主| Liuhl1998 发表于 2022-4-19 10:41 | 显示全部楼层
iamOJZ 发表于 2022-4-15 21:55
膜拜巨佬,之前就有想法用CH543做DP ALE相关的应用,不过由于知识匮乏做不出来。看到大佬的Demo想询问下大 ...

拉电阻部分是参考DP手册以及网络文档而来的,图中经给出详细的电路,比较准确,可以直接使用。使用母口时:两根CC都将连接至母口上,但是通讯时只会有一根CC进行通讯,通过检测CC1/CC2哪一根进行通讯来判断正反插。电平控制模拟开关来切换差分线。没明白您指的协议层是想知道哪一方面,不好意思。
iamOJZ 发表于 2022-4-19 15:05 | 显示全部楼层
我的问题,一开始我以为是通过PD协议来获取DFP的方向来判断。后面看了一些例程才知道,PD协议只能判断当前端口的方向(也就是大佬所说根据连接到CC1/CC2来判断正反),然后MUX只要当CC2连接的时候开启翻转功能就行,我在大佬demo的基础上加了一个MUX(PI3USB305),不过样品没到还没验证。关于这个芯片还有一些问题,我看官方的keil pak并没有这个型号,然后WCHTOOL也没有这个型号(文档说更新3.3版本,但是官网上的只有3.2),话说大佬你是咋编译工程和烧录芯片的啊。

评论

@Liuhl1998 :提示该用户不存在  发表于 2023-8-30 23:50
+ V:CS957914743  发表于 2022-4-19 16:00
 楼主| Liuhl1998 发表于 2022-8-11 17:14 | 显示全部楼层
11111111
woshiwoshi 发表于 2023-8-23 22:55 | 显示全部楼层
优质的创作者您好,我正在使用沁恒的CH543开发PD协议中的alternate model模块,即typec转dp功能,我在开发过程中使用到了您的代码,但学识有限,有一些不太明白的地方,**能接收您的指教,谢谢。
个人邮箱:binary_world@163.com[/email]
微信:Hello_Btf_World
woshiwoshi 发表于 2023-8-30 23:49 | 显示全部楼层
本帖最后由 woshiwoshi 于 2023-9-6 11:45 编辑

您好,我看了你前面的几篇关于使用ch543作为pd controller开发typec转dp的程序的代码,受益匪浅,首先感谢博主的分享。在了解了你写的代码之后,我尝试进行了复现,目前能够实现电源协商模块,但是在接着开发typec转dp模块时遇到了一些问题,请问能否予以解答,谢谢。如蒙赐教,不甚感激。
谢谢
b513247209 发表于 2024-4-8 11:24 | 显示全部楼层
楼主是大佬。膜拜!!
Ivan007 发表于 2024-9-26 09:29 | 显示全部楼层
感谢楼主分享。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

16

主题

109

帖子

33

粉丝
快速回复 在线客服 返回列表 返回顶部