diff --git a/PD_CPS8860_A1_CPS_Common_Demo/ac_project/code/inc/config.h b/PD_CPS8860_A1_CPS_Common_Demo/ac_project/code/inc/config.h index f2d98ee..f2d5762 100644 --- a/PD_CPS8860_A1_CPS_Common_Demo/ac_project/code/inc/config.h +++ b/PD_CPS8860_A1_CPS_Common_Demo/ac_project/code/inc/config.h @@ -30,7 +30,8 @@ #define TYPEC_PORT_MAX 2 #define USER_DERAT_ENABLE 1 -#define USER_NTC_ENABLE 1 +#define USER_NTC_ENABLE 0 +#define SWITCH_LINE_OFF_PROTECTION 0 extern uint16_t system_1ms_cnt; extern uint16_t system_1s_cnt; diff --git a/PD_CPS8860_A1_CPS_Common_Demo/ac_project/code/inc/customized.h b/PD_CPS8860_A1_CPS_Common_Demo/ac_project/code/inc/customized.h index fbed75b..1f44cc5 100644 --- a/PD_CPS8860_A1_CPS_Common_Demo/ac_project/code/inc/customized.h +++ b/PD_CPS8860_A1_CPS_Common_Demo/ac_project/code/inc/customized.h @@ -111,6 +111,12 @@ typedef struct bool usba_is_low_power; // A口有负载, 且负载十分钟内都处在低功率状态 bool c1_priority_inser; // C1口优先C2口接进来 = 1 代表是 + + bool need_switch_mos; + bool new_request_receive_done; // 新request接收完成 + + volatile uint16_t protection_off_2s; + bool protection_off_flag[2]; } user_app_s; extern user_app_s user_app; @@ -334,6 +340,7 @@ void app_double_dynamic_power_check(void); void usba_detection(void); void insertion_equipment_judgment(void); void port_inser_priority_judgment(void); +void gate3_control(bool enable); #if USER_NTC_ENABLE // void ntc_judgment(void); diff --git a/PD_CPS8860_A1_CPS_Common_Demo/ac_project/code/src/comp_dac.c b/PD_CPS8860_A1_CPS_Common_Demo/ac_project/code/src/comp_dac.c index 36635fa..973ca65 100644 --- a/PD_CPS8860_A1_CPS_Common_Demo/ac_project/code/src/comp_dac.c +++ b/PD_CPS8860_A1_CPS_Common_Demo/ac_project/code/src/comp_dac.c @@ -34,8 +34,7 @@ void comp_dac_close_vbus(uint8_t port) // 单C2时, 用的是gate3给C2口供电 if(g_app_protocol_param[0].pd_param.typec_status.typec_status == UnattachedSRC) { - REG_ANALOG_GATE3->bf.driver_en = 0; - REG_ANALOG_GATE3->bf.cp_en = 0; + gate3_control(false); } REG_ANALOG_GATE2->bf.driver_en = 0; @@ -43,8 +42,7 @@ void comp_dac_close_vbus(uint8_t port) break; case TYPEC_PORT_MAX: - REG_ANALOG_GATE3->bf.driver_en = 0; - REG_ANALOG_GATE3->bf.cp_en = 0; + gate3_control(false); break; } } @@ -60,19 +58,8 @@ void comp_dac_open_vbus(uint8_t port) switch(port) { case TYPEC_PORT0: - // 开gate1前确认gate3是关闭的 - REG_ANALOG_GATE3->bf.driver_en = 0; - REG_ANALOG_GATE3->bf.cp_en = 0; REG_ANALOG_GATE1->bf.driver_en = 1; REG_ANALOG_GATE1->bf.cp_en = 1; - - // 先插C2口, 会打开gate3, 再插C1的时候, 不会再次去执行打开gate2 - if(g_app_protocol_param[1].pd_param.typec_status.typec_status == AttachedSRC) - { - REG_ANALOG_GATE2->bf.driver_en = 1; - REG_ANALOG_GATE2->bf.cp_en = 1; - } - break; case TYPEC_PORT1: @@ -80,15 +67,26 @@ void comp_dac_open_vbus(uint8_t port) // 单C2时,需要使用C1那一路的ACDC。 打开gate3 关闭gate2 if(g_app_protocol_param[0].pd_param.typec_status.typec_status == UnattachedSRC) { - REG_ANALOG_GATE3->bf.driver_en = 1; - REG_ANALOG_GATE3->bf.cp_en = 1; - REG_ANALOG_GATE2->bf.driver_en = 0; - REG_ANALOG_GATE2->bf.cp_en = 0; + // 1: 需要考虑C1口是不是从20V刚拔出,电还没掉到5V附近。 + if(comp_adc_get_vin12(TYPEC_PORT0) > VOLTAGE_5P5V) + { + comp_set_vol_cur(TYPEC_PORT1, + VOLTAGE_DEFAULT, + CURRENT_DEFAULT); + user_app.need_switch_mos = true; + } + else + { + gate3_control(true); + REG_ANALOG_GATE2->bf.driver_en = 0; + REG_ANALOG_GATE2->bf.cp_en = 0; + } } - else // C1口有接进来时, 需要关闭gate3。 打开gate2 关闭gate3 + else // C1口有接进来时, 需要关闭gate3。 { - REG_ANALOG_GATE3->bf.driver_en = 0; - REG_ANALOG_GATE3->bf.cp_en = 0; + // 如果是 C2 变 C1 + C2情况 并不会走这里 + // 如果是 C1 变 C1 + C2情况 这样走没啥问题 + gate3_control(false); REG_ANALOG_GATE2->bf.driver_en = 1; REG_ANALOG_GATE2->bf.cp_en = 1; } @@ -96,8 +94,7 @@ void comp_dac_open_vbus(uint8_t port) break; case TYPEC_PORT_MAX: - REG_ANALOG_GATE3->bf.driver_en = 1; - REG_ANALOG_GATE3->bf.cp_en = 1; + gate3_control(true); break; } } @@ -381,7 +378,7 @@ static void comp_dac_cc_2dcdc_fb(uint8_t port, uint16_t val, uint16_t offset) int16_t temp[TYPEC_PORT_MAX] = {0, 0}; int16_t fb_cc_offset[TYPEC_PORT_MAX] = {FB1_CCOFFFSET, FB2_CCOFFFSET}; - log_info("fb_set_cc port:%d cc_val:%d\n", port, val); + // log_info("fb_set_cc port:%d cc_val:%d\n", port, val); #if DAC_TRIM_ENABLE @@ -459,7 +456,7 @@ static void comp_dac_cc_acdc(uint8_t port, uint16_t val, uint16_t offset) uint32_t value[TYPEC_PORT_MAX] = {0}; int16_t temp[TYPEC_PORT_MAX] = {0}; - log_info("opto_set_cc port:%d cc_val:%d\n", port, val); + // log_info("opto_set_cc port:%d cc_val:%d\n", port, val); // 仅测试, C2口用第一路acdc, 走gate3时设置3.7A实际只能出3.3A test_current = val; @@ -540,6 +537,7 @@ void comp_dac_cc_target_set(uint8_t port, uint16_t val, uint16_t offset) else if(!type_c1_state && type_c2_state) // 单C2 { comp_dac_cc_acdc(TYPEC_PORT0, val, offset); + comp_dac_cc_2dcdc_fb(TYPEC_PORT1, val, offset); // 另外一路的电流也设到一样的 } else // 双口 { diff --git a/PD_CPS8860_A1_CPS_Common_Demo/ac_project/code/src/comp_protection.c b/PD_CPS8860_A1_CPS_Common_Demo/ac_project/code/src/comp_protection.c index ea267c1..26b4f85 100644 --- a/PD_CPS8860_A1_CPS_Common_Demo/ac_project/code/src/comp_protection.c +++ b/PD_CPS8860_A1_CPS_Common_Demo/ac_project/code/src/comp_protection.c @@ -618,6 +618,23 @@ void comp_protection_run(uint8_t port) case PRO_MONITOR: if(!timer_cnt[port]) { + // 哪个口有接入,哪个口才开启保护 + // if( g_app_protocol_param[port].pd_param.typec_status.typec_status != AttachedSRC ) + // { + // g_protection_param.protection_param[0].protection_enable = PORT_OTP_ENABLE; + // g_protection_param.protection_param[1].protection_enable = PORT_OTP_ENABLE; + // } + // else + // { + // g_protection_param.protection_param[0].protection_enable |= VIN_UVP_ENABLE | DPDN_WET_ENABLE | PORT_OTP_ENABLE; + // g_protection_param.protection_param[1].protection_enable |= VIN_UVP_ENABLE | DPDN_WET_ENABLE | VIN_OVP_ENABLE | VIN_OCP_ENABLE | PORT_OTP_ENABLE; + // } + + if(g_app_protocol_param[port].pd_param.typec_status.typec_status != AttachedSRC) + { + return; + } + comp_protection_monitor(port, &g_protection_param.protection_param[port]); } diff --git a/PD_CPS8860_A1_CPS_Common_Demo/ac_project/code/src/customized.c b/PD_CPS8860_A1_CPS_Common_Demo/ac_project/code/src/customized.c index fd396ca..cbc38bd 100644 --- a/PD_CPS8860_A1_CPS_Common_Demo/ac_project/code/src/customized.c +++ b/PD_CPS8860_A1_CPS_Common_Demo/ac_project/code/src/customized.c @@ -434,6 +434,13 @@ void pd_src_cap_init(uint8_t port, pd_param_s*pd_param, uint8_t pwr_cnt) // } #endif +void gate3_control(bool enable) +{ + log_info("gate3:%d\n", enable); + REG_ANALOG_GATE3->bf.driver_en = enable; + REG_ANALOG_GATE3->bf.cp_en = enable; +} + bool usba_online_state = false; void usba_detection(void) { @@ -642,6 +649,48 @@ void insertion_equipment_judgment(void) } +void mos_switch_control(void) +{ + if(!user_app.need_switch_mos) + return; + + switch(user_app.adapter_state) + { + case C2_INSER: + case C2_A_INSER: + + // 等第一路电压调整到 第二路一样的电压 + if(abs(g_powerout_info[TYPEC_PORT1].set_vol - comp_adc_get_vin12(TYPEC_PORT0)) <= VOLTAGE_0P5V) + { + user_app.need_switch_mos = false; + log_info("%s %d\n", __func__, __LINE__); + gate3_control(true); + drv_delay_ms(4); + REG_ANALOG_GATE2->bf.driver_en = 0; + REG_ANALOG_GATE2->bf.cp_en = 0; + } + + break; + + case C1_C2_INSER: + case C1_C2_A_INSER: + + // 等第一路的负载主动降低拉载功率,当功率小于40W时再去切mos + if(comp_adc_get_vin12(TYPEC_PORT0) * comp_adc_get_cur12(TYPEC_PORT0) <= 40000000) + { + user_app.need_switch_mos = false; + + REG_ANALOG_GATE2->bf.driver_en = 1; + REG_ANALOG_GATE2->bf.cp_en = 1; + drv_delay_ms(4); + gate3_control(false); + } + + break; + } + +} + /* * @brief adapter_state_check * @param NULL @@ -689,6 +738,22 @@ void adapter_state_check(void) user_app.adapter_state = C1_C2_A_INSER; } + mos_switch_control(); + +#if SWITCH_LINE_OFF_PROTECTION + + if((user_app.protection_off_2s == 0) + && (g_powerout_info[TYPEC_PORT0].power_state == PWR_RDY) + && (g_powerout_info[TYPEC_PORT1].power_state == PWR_RDY) + && user_app.protection_off_flag) + { + user_app.protection_off_flag = false; + comp_powerout_protect_en(TYPEC_PORT0, true); + comp_powerout_protect_en(TYPEC_PORT1, true); + } + +#endif + // 端口状态改变 或者 NTC有改变 或者一分钟倒计时结束 // #if USER_NTC_ENABLE @@ -703,6 +768,14 @@ void adapter_state_check(void) return; } +#if SWITCH_LINE_OFF_PROTECTION + // 每次切换gate2和gate3的时候, 关闭2秒保护, 2秒后且在ready状态再打开 + comp_powerout_protect_en(TYPEC_PORT0, false); + comp_powerout_protect_en(TYPEC_PORT1, false); + user_app.protection_off_2s = DELAY_2S; + user_app.protection_off_flag = true; +#endif + if(user_app.update_adapter_state) { user_app.update_adapter_state = false; @@ -716,8 +789,12 @@ void adapter_state_check(void) g_powerout_info[TYPEC_PORT0].support_protocol.byte = PROTOCOL_ALL_ENABLE; g_powerout_info[TYPEC_PORT1].support_protocol.byte = PROTOCOL_ALL_ENABLE; + // 拔出时, 复位协议, 关闭gate3 app_protocol_reset(TYPEC_PORT0); app_protocol_reset(TYPEC_PORT1); + gate3_control(false); + user_app.need_switch_mos = false; + user_app.new_request_receive_done = false; break; case C1_INSER: @@ -725,12 +802,26 @@ void adapter_state_check(void) need_send_cap_flag[TYPEC_PORT0] = PD_PWR_70W; g_powerout_info[TYPEC_PORT0].support_protocol.byte = PROTOCOL_ALL_ENABLE; g_powerout_info[TYPEC_PORT1].support_protocol.byte = PROTOCOL_ALL_ENABLE; + + // 关gate3, 让C2口回到5V3A + gate3_control(false); + comp_set_vol_cur(TYPEC_PORT1, + VOLTAGE_DEFAULT, + CURRENT_DEFAULT); break; case C2_INSER: need_send_cap_flag[TYPEC_PORT1] = PD_PWR_70W; g_powerout_info[TYPEC_PORT0].support_protocol.byte = PROTOCOL_ALL_ENABLE; g_powerout_info[TYPEC_PORT1].support_protocol.byte = PROTOCOL_ALL_ENABLE; + + // 让第一路的电压电流和第二路的一样之后, 才把gate3打开, gate2关闭 + comp_set_vol_cur(TYPEC_PORT0, + g_powerout_info[TYPEC_PORT1].set_vol, + g_powerout_info[TYPEC_PORT1].set_current); + + // 等待电压电流设置完毕后才去控制切mos, 要做成不阻塞状态 + user_app.need_switch_mos = true; break; case C1_C2_INSER: @@ -814,6 +905,48 @@ void adapter_state_check(void) comp_powerout_cur_set(TYPEC_PORT1, &g_powerout_info[TYPEC_PORT1], CURRENT_1P2A); } + if(user_app.last_adapter_state == C1_INSER) + { + // 1. 确保第二路口开启前 第二路口电压是<5.5V的 ---->在开mos前做了 + // 2. 确保gate3是关闭的 + gate3_control(false); + } + else if(user_app.last_adapter_state == C2_INSER) + { + /* + 单C2时候走 PD 20V,这时候 C1口接负载进来。 + 因为用的是第一路的负载: + C1口需要 主动降到5V。然后去开MOS. + C2口需要:主动发送新的src cap,得等负载申请了之后才能去切 gate3 和 gate2。 + 不等负载申请主动降的话会导致断充。 + + 有冲突。在open vbus前加个不阻塞的延迟,让C2口的新src cap能发出去, + 等新 src cap后且受到新equest时才去切 gate3和 qate2, + 或者以功率为判断标准,当C2口拉载功率从70W降到 40W之后直接切。 + */ + if(g_powerout_info[TYPEC_PORT1].protocol_type == PROTOCOL_PD) + { + // 发送新src_cap 等C2的负载主动申请完之后,再去切mos + user_app.new_request_receive_done = true; + user_app.need_switch_mos = true; + } + else // 其他协议都是小功率, 直接切mos + { + REG_ANALOG_GATE2->bf.driver_en = 1; + REG_ANALOG_GATE2->bf.cp_en = 1; + drv_delay_ms(4); + gate3_control(false); + } + } + else if(user_app.last_adapter_state == C1_C2_A_INSER) + { + // 1. 确保gate3是关闭的 + REG_ANALOG_GATE2->bf.driver_en = 1; + REG_ANALOG_GATE2->bf.cp_en = 1; + drv_delay_ms(4); + gate3_control(false); + } + break; case C1_A_INSER: @@ -824,6 +957,11 @@ void adapter_state_check(void) need_send_cap_flag[TYPEC_PORT0] = PD_PWR_65W; } + // 关gate3, 让C2口回到5V3A + gate3_control(false); + comp_set_vol_cur(TYPEC_PORT1, + VOLTAGE_DEFAULT, + CURRENT_DEFAULT); break; case C2_A_INSER: @@ -834,6 +972,13 @@ void adapter_state_check(void) need_send_cap_flag[TYPEC_PORT1] = PD_PWR_65W; } + // 让第一路的电压电流和第二路的一样之后, 才把gate3打开, gate2关闭 + comp_set_vol_cur(TYPEC_PORT0, + g_powerout_info[TYPEC_PORT1].set_vol, + g_powerout_info[TYPEC_PORT1].set_current); + + // 等待电压电流设置完毕后才去控制切mos, 要做成不阻塞状态 + user_app.need_switch_mos = true; break; case C1_C2_A_INSER: @@ -852,6 +997,50 @@ void adapter_state_check(void) comp_powerout_default_set(TYPEC_PORT1, &g_powerout_info[TYPEC_PORT1]); } + if((user_app.last_adapter_state == C1_INSER) + || (user_app.last_adapter_state == C1_A_INSER)) + { + // 1. 确保第二路口开启前 第二路口电压是<5.5V的 ---->在开mos前做了 + // 2. 确保gate3是关闭的 + gate3_control(false); + } + else if((user_app.last_adapter_state == C2_INSER) + || (user_app.last_adapter_state == C2_A_INSER)) + { + /* + 单C2时候走 PD 20V,这时候 C1口接负载进来。 + 因为用的是第一路的负载: + C1口需要 主动降到5V。然后去开MOS. + C2口需要:主动发送新的src cap,得等负载申请了之后才能去切 gate3 和 gate2。 + 不等负载申请主动降的话会导致断充。 + + 有冲突。在open vbus前加个不阻塞的延迟,让C2口的新src cap能发出去, + 等新 src cap后且受到新equest时才去切 gate3和 qate2, + 或者以功率为判断标准,当C2口拉载功率从70W降到 40W之后直接切。 + */ + if(g_powerout_info[TYPEC_PORT1].protocol_type == PROTOCOL_PD) + { + // 发送新src_cap 等C2的负载主动申请完之后,再去切mos + user_app.new_request_receive_done = true; + user_app.need_switch_mos = true; + } + else // 其他协议都是小功率, 直接切mos + { + // 先关再开, 防止功率并联反灌 + REG_ANALOG_GATE2->bf.driver_en = 1; + REG_ANALOG_GATE2->bf.cp_en = 1; + drv_delay_ms(4); + gate3_control(false); + } + } + else if(user_app.last_adapter_state == C1_C2_INSER) + { + REG_ANALOG_GATE2->bf.driver_en = 1; + REG_ANALOG_GATE2->bf.cp_en = 1; + drv_delay_ms(4); + gate3_control(false); + } + break; default: @@ -902,10 +1091,10 @@ void adapter_state_check(void) } } - log_info("adapter_state:%d port0:%d port1:%d\n", - user_app.adapter_state, - need_send_cap_flag[TYPEC_PORT0], - need_send_cap_flag[TYPEC_PORT1]); + // log_info("adapter_state:%d port0:%d port1:%d\n", + // user_app.adapter_state, + // need_send_cap_flag[TYPEC_PORT0], + // need_send_cap_flag[TYPEC_PORT1]); user_app.last_adapter_state = user_app.adapter_state; #if USER_NTC_ENABLE diff --git a/PD_CPS8860_A1_CPS_Common_Demo/ac_project/project/Objects/CPS8860_anker_9196.axf b/PD_CPS8860_A1_CPS_Common_Demo/ac_project/project/Objects/CPS8860_anker_9196.axf index feb09e0..3646316 100644 Binary files a/PD_CPS8860_A1_CPS_Common_Demo/ac_project/project/Objects/CPS8860_anker_9196.axf and b/PD_CPS8860_A1_CPS_Common_Demo/ac_project/project/Objects/CPS8860_anker_9196.axf differ diff --git a/PD_CPS8860_A1_CPS_Common_Demo/ac_project/project/Objects/CPS8860_anker_9196.build_log.htm b/PD_CPS8860_A1_CPS_Common_Demo/ac_project/project/Objects/CPS8860_anker_9196.build_log.htm index 7938cc1..4151e49 100644 --- a/PD_CPS8860_A1_CPS_Common_Demo/ac_project/project/Objects/CPS8860_anker_9196.build_log.htm +++ b/PD_CPS8860_A1_CPS_Common_Demo/ac_project/project/Objects/CPS8860_anker_9196.build_log.htm @@ -27,17 +27,20 @@ Project File Date: 04/21/2025