使用CH32X035+CH211做PD_SROUCE支持FIXED挡位、PPS挡位

一、简介

         CH32X035 是基于青稞 RISC-V 内核设计的工业级微控制器。CH32X035 内置 USB 和 PD PHY,支持 USB Host 主机和 USB Device 设备功能、PDUSB 及 Type-C 快充功能,内置可编程协议 I/O 控制器,提供了 2 组 OPA 运放、3 组 CMP 电压比较器、4 组 USART 串口、I2C、SPI、多组定时器、12 位 ADC、14 路 Touchkey 等丰富外设资源。

        CH211 是内置了高压开关和升压模块的 Type-C/PD 高压接口芯片。芯片内置了 4 通道高压开关, 用于 MCU 的 PD 信号对接高压 Type-C 接口;内置了升压电路,支持外部 N 型 MOSFET 功率管控制;内 置了两路 LDO 稳压器,支持双路高压电源输入;内部集成了 VBUS 上电和掉电监测、过压监测、过温 监测等模块;单引脚支持按键检测和唤醒;提供 2 线控制接口及中断;可用于 MCU 管理 Type-C 接口 电源和 USB PD 信号高压扩展等。


二、什么是PD_SROUCE

        在PD协议中提供电源输出的角色为SROUCE,常见的设备类型为墙充适配器、车载适配器、USB主机口(PC机、机顶盒)等。在USB数据传输中通常做为Host角色出现。

三、硬件设计

        做为PD_SOURCE是PD协议中的供电方,需要有一定的供电能力。在PD协议规范中当PD_SROUCE在检测到SINK设备接入时,VBUS需要提供vSafe5V,这个电压的范围在4.75V-5V之间。所以在默认状态下,PD_SOURCE需要有控制vSafe5V输出的能力。

        按照规范在检测到SINK设备接入前,VBUS上不能有vSafe5V,需要SOURCE检测到设备接入后打开MOS输出vSafe5V。所以需要在VBUS上放置一颗MOS控制输出,由于我们要做PD_SROUCE要做大功率的情况下需要控制大电压,所以要使用NMOS控制,CH32X035没有驱动NMOS的能力,需要在外围搭配一颗CH211驱动NMOS管,同时CH211有两路LDO稳压器,可以使用CH211的VDD33给CH32X035供电。

        在沁恒的官网上下载的CH32X035的EVT中,CH32X035+CH211的DEMO上有两颗MOS,因为该DEMO是要实现DRP,可以切换C口供电和电池供电,我们可以利用电池座给C口供电,去掉Q2只用Q1控制电池座这边可以接我们的DCVout。

        做PD_SOURCE输出的电压是需要更具协议沟通的挡位调节电压值的,所以需要供电是一个可调的DCDC,CH32X035没有DAC,我们可以通过PWM输出经过放大器来模拟一个FB引脚,通过FB引脚漏电控制DC输出。

        所以在选择DC芯片时要选择可调DC芯片,Vout的电压输出范围可以根据自己设计参数去选择。(推荐选择的Vout输出电压要大于5V电流大于3A)

        方便监控VBUS输出的电压值,可以使用一路ADC检测VBUS的电压,CH32X035的ADC检测电压值最大是3.3V所以需要做分压电路做检测。可以参考官方提供的EVT绘制原理图。

四、软件设计

        该方案中使用到了CH211做高压辅助,CH211支持IIC读写寄存器,在软件中首先要写CH211_IIC的控制代码,在官方提供的例程中,CH32X035+CH211的例程里面带有CH211的控制代码。

        因为CH32X035没有DAC,所以要使用PWM加OPA做模拟的DAC。

        CH32X035内部两个OPA的结构如下:

void OPA1_Init( void )
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};
    OPA_InitTypeDef  OPA_InitStructure = {0};

    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init( GPIOA, &GPIO_InitStructure );

    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init( GPIOB, &GPIO_InitStructure );

    OPA_InitStructure.OPA_NUM=OPA1;
    OPA_InitStructure.PSEL = CHP0;
    OPA_InitStructure.NSEL = CHN0;
    OPA_InitStructure.Mode=OUT_IO_OUT0;
    OPA_Init( &OPA_InitStructure );
    OPA_Cmd(OPA1, ENABLE );
}
void TIM1_PWMOut_Init(u16 arr, u16 psc, u16 ccp)
{
    GPIO_InitTypeDef        GPIO_InitStructure = {0};
    TIM_OCInitTypeDef       TIM_OCInitStructure = {0};
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure = {0};

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_TIM1, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    TIM_TimeBaseInitStructure.TIM_Period = arr;
    TIM_TimeBaseInitStructure.TIM_Prescaler = psc;
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStructure);

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = ccp;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OC3Init(TIM1, &TIM_OCInitStructure);

    TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Disable);
    TIM_ARRPreloadConfig(TIM1, ENABLE);
}

        本文使用的是OPA1和高级定时器TIM1生成PWM,初始化的方法如上。

        调节PWM输出的频率和占空比控制DC的Vout,在做Fixed挡位输出的时候,可以根据设置的Fixed挡位调出几个合适的值,做固定输出。在做PPS挡位时,根据ADC检测的VBUS电压值调节输出。

        CC检测部分在例程中都已经做好了,在检测到SINK接入的时候,需要控制DC输出5V电压并打开MOS。

void PD_User_Src_DevIn(void)
{

    TIM1_PWMOut_Init( 5000, 2-1, 950 ); //5V
	CH211_I2C_SetBit(HVCP_CTRL, 0, CP_LE);
    CH211_I2C_SetBit(HVCP_CTRL, CP_AUTO, 0);
    
	Delay_Ms(10);
	printf(" PD_User_Src_DevIn \r\n");
}

        我们可以根据自己的设计需求修改Source_Capabilities里面的数据,Source_Capabilities的数据结构为:

        Source_Capabilities的第一个FIXED的PDO是需要完整的信息,方便SINK识别SROUCE的能力,后面的FIXED的PDO只需要Bit0...19的数据内容,要是做支持PPS模式的PDO需要每个PDO都是完整的。且一个Source_Capabilities消息里面最多可以携带7个PDO,如果要支持更多的PDO需要使用Extended Message,把挡位拆分放在多个Source_Capabilities块里面。        

//The device acts as a source, sending the Source_Capabilities message content
u32 SrcCap[] = 	{0x3A21912C,};	//5V3A
u8 SrcCapCnt = 1;

        例程中SrcCap只有一个PDO,可以根据自己的设计需求修改,SrcCapCnt的最大值是7,这个是需要发送的PDO挡位的数量,因为每个PDO数据的长度是32bits,所以需要*4。

memcpy(&PD_TX_BUF[1],SrcCap,SrcCapCnt*4);

        SROUCE在检测到SINK设备接入的之后会连续发送三次Source_Capabilities,且在没有收到Reject时会间隔120ms再发送一次Source_Capabilities。
        发送完Source_Capabilities之后,等待收到SINK发送的Request。接收到Request之后解析Request Message里面的数据包,数据包结构如下:

        判断Request是否在Source_Capabilities的范围内,如果在范围内发送Accept,然后调节VBUS的电压到Request里面的电压值,然后发送PS_RDY。

        在收到PPS请求时,需要微调DCVout,并且需要300ms内等待SINK发第二次的PPS请求,如果没有等到SINK发PPS请求,需要断掉VBUS供电,重启PD流程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值