From 42e1174516bd8418ba8927ad03226407f4e21722 Mon Sep 17 00:00:00 2001 From: wrh Date: Fri, 9 Oct 2026 09:30:20 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9ESink=E5=8D=8F?= =?UTF-8?q?=E8=AE=AE=E5=88=87=E6=8D=A2=E5=A4=8D=E4=BD=8D=E5=BC=80=E5=85=B3?= =?UTF-8?q?=E5=8F=8A=E7=89=88=E6=9C=AC=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改了短路测试不能四个通道同时的问题,增加了协议板版本切换宏定义,老版本用0,新版本用1 1 新增SINK_PROTOCOL_SWITCH_RESET_ENABLE宏控制协议切换是否先复位Sink 2 仅CC参数实际变化时才断开北向D+/D-/CC继电器 3 更新协议板版本寄存器为0x0147,软件版本升至V1.1.55 4 修改相关状态机及函数实现复位开关逻辑 5 更新修改日志文档记录本次变更 --- apps/chrg/applications/thread/chrg_comm.c | 19 +++-- apps/chrg/applications/thread/chrg_north.h | 7 ++ apps/chrg/applications/thread/chrg_roll_nor.c | 85 ++++++++++++++++--- apps/chrg/applications/thread/chrg_roll_nor.h | 7 +- apps/chrg/applications/utils/chrg_def.h | 4 +- apps/chrg/applications/utils/chrg_sink.c | 3 +- docs/修改日志.md | 9 ++ 7 files changed, 112 insertions(+), 22 deletions(-) diff --git a/apps/chrg/applications/thread/chrg_comm.c b/apps/chrg/applications/thread/chrg_comm.c index 2466bd1..c229dcf 100644 --- a/apps/chrg/applications/thread/chrg_comm.c +++ b/apps/chrg/applications/thread/chrg_comm.c @@ -27,7 +27,7 @@ #include "stm32f4xx_hal.h" #define HOLD_REG_FIRMWARE_VERSION 0x0300U /* 协议板固件版本,只读 */ -#define CHRG_FIRMWARE_VERSION 0x0146U /* 当前协议板版本:V1.1.54 */ +#define CHRG_FIRMWARE_VERSION 0x0147U /* 当前协议板版本:V1.1.55 */ rt_uint8_t ucDiscInBuf[(TOTAL_DISC_REGS+BITS_UCHAR-1)/BITS_UCHAR]; @@ -1905,6 +1905,7 @@ static eMBException chrg_comm_apply_sink_effect(rt_uint8_t ch, rt_bool_t protocol_voltage_only; rt_bool_t protocol_current_change; rt_bool_t protocol_data_changed; + rt_bool_t protocol_reset; rt_bool_t von_changed; rt_uint8_t curr_test; rt_uint8_t curr_test_old; @@ -1959,6 +1960,8 @@ static eMBException chrg_comm_apply_sink_effect(rt_uint8_t ch, !full_handshake_change; protocol_voltage_only = diff_info.pro_voltage_changed && !full_handshake_change && !protocol_current_change; + protocol_reset = diff_info.protocol_changed && + (SINK_PROTOCOL_SWITCH_RESET_ENABLE != 0U); von_changed = (pReal->sink.volt_on != pShadow->sink.volt_on); /* 完整握手或协议软卸载会先清理本通道批次,V_ON由对应状态机在 * WORK_STOP之后重新加入;普通参数变化仍在这里立即下发。 */ @@ -2022,12 +2025,11 @@ static eMBException chrg_comm_apply_sink_effect(rt_uint8_t ch, pReal->sink.work_mode = SINK_WORK_INIT; } else if (full_handshake_change) { /* - * 协议类型变化会复位Sink协议板,复位会清除协议板内部CC选择; - * 即使上位机CC参数未变化,也必须重新设置CC并等待稳定后再设协议。 + * 宏开启时,协议类型变化会复位Sink协议板并清除其内部CC选择, + * 因此仍须重新设置CC;宏关闭时协议类型变化直接设置目标协议。 */ - if (diff_info.protocol_changed || + if (protocol_reset || (diff_info.cc_changed && protocol_data_changed)) { - /* Protocol-before-CC test flow is disabled in this version. */ target_sub = diff_info.cv_changed ? IDX_SET_SINK_CC_BEFORE_PD_WITH_MODE : IDX_SET_SINK_CC_BEFORE_PD; @@ -2037,9 +2039,10 @@ static eMBException chrg_comm_apply_sink_effect(rt_uint8_t ch, target_sub = diff_info.cv_changed ? IDX_SET_SINK_PD_WITH_MODE : IDX_SET_SINK_PD; } - /* 仅协议类型变化需先复位Sink协议板;组号、CC、 - * 协议电压/电流和模式变化都不触发Reset。 */ - if (diff_info.protocol_changed) { + /* 只有CC参数实际变化才会在低电流确认后断开北向继电器。 */ + chrg_roll_nor_sink_cc_switch_prepare(ch, diff_info.cc_changed); + /* 宏开启时,仅协议类型变化先复位Sink;否则直接执行目标设置。 */ + if (protocol_reset) { chrg_roll_nor_sink_reset_prepare(ch, target_sub); pReal->sub = IDX_SET_SINK_RESET; } else { diff --git a/apps/chrg/applications/thread/chrg_north.h b/apps/chrg/applications/thread/chrg_north.h index fb2b234..619eabf 100644 --- a/apps/chrg/applications/thread/chrg_north.h +++ b/apps/chrg/applications/thread/chrg_north.h @@ -26,6 +26,13 @@ #error "Invalid SINK_VON_VOLTAGE_SOURCE" #endif +/* 协议类型切换是否先复位Sink协议板:1=复位,0=直接设置协议。 */ +#define SINK_PROTOCOL_SWITCH_RESET_ENABLE 0U +#if (SINK_PROTOCOL_SWITCH_RESET_ENABLE != 0U) && \ + (SINK_PROTOCOL_SWITCH_RESET_ENABLE != 1U) +#error "Invalid SINK_PROTOCOL_SWITCH_RESET_ENABLE" +#endif + /* 南向COM批次中单通道连续收到有效回码后的最大发送条数。 */ #define SOU_COM_BURST_MAX 6U diff --git a/apps/chrg/applications/thread/chrg_roll_nor.c b/apps/chrg/applications/thread/chrg_roll_nor.c index af4771e..9fbcd43 100644 --- a/apps/chrg/applications/thread/chrg_roll_nor.c +++ b/apps/chrg/applications/thread/chrg_roll_nor.c @@ -32,7 +32,7 @@ #define NORTH_POLL_INTERVAL_MS 10U // 一个通道事务结束后到下一通道的轮询间隔 #define SOURCE_PROTOCOL_WAIT_MS 100U // 每通道0xD0应答后的协议生效保护时间 #define SINK_CC_WAIT_MS 50U // Sink设置目标CC应答后的非阻塞保护时间 -#define SINK_RESET_RELAY_WAIT_MS 100U // Sink复位回码后北向继电器断开时间 +#define SINK_RESET_RELAY_WAIT_MS 100U // Sink复位回码后,实际切换CC时北向继电器断开时间 #define SINK_HANDSHAKE_FIRST_QUERY_DELAY_MS 50U // 协议/CC回码后首条0x20的等待时间 #define SINK_HANDSHAKE_QUERY_INTERVAL_MS 50U // 握手未完成时后续0x20查询间隔 #define SOURCE_CHANNEL_BIT(ch) ((rt_uint8_t)(1U << (ch))) @@ -58,6 +58,9 @@ static rt_tick_t g_sink_cc_wait_start[TOTAL_NOR_CHS] = {0}; static rt_uint8_t g_sink_reset_wait_mask = 0U; static rt_tick_t g_sink_reset_wait_start[TOTAL_NOR_CHS] = {0}; static rt_uint8_t g_sink_reset_next_sub[TOTAL_NOR_CHS] = {0}; +/* 仅CC参数实际变化的通道才会断开D+/D-/CC,并在CC稳定后恢复。 */ +static rt_uint8_t g_sink_cc_relay_close_mask = 0U; +static rt_uint8_t g_sink_cc_relay_restore_mask = 0U; /* Sink协议/CC握手期间的0x20查询节流记录,按通道独立计时。 */ static rt_bool_t g_sink_query_throttle[TOTAL_NOR_CHS] = {RT_FALSE}; static rt_bool_t g_sink_query_first_pending[TOTAL_NOR_CHS] = {RT_FALSE}; @@ -137,6 +140,61 @@ void chrg_roll_nor_sink_reset_cancel(rt_uint8_t ch) g_sink_reset_wait_mask &= (rt_uint8_t)~SOURCE_CHANNEL_BIT(ch); g_sink_reset_wait_start[ch] = 0U; g_sink_reset_next_sub[ch] = 0U; + g_sink_cc_relay_close_mask &= (rt_uint8_t)~SOURCE_CHANNEL_BIT(ch); + g_sink_cc_relay_restore_mask &= (rt_uint8_t)~SOURCE_CHANNEL_BIT(ch); +} + +void chrg_roll_nor_sink_cc_switch_prepare(rt_uint8_t ch, + rt_bool_t cc_changed) +{ + rt_uint8_t bit; + + if (ch >= TOTAL_NOR_CHS) { + return; + } + bit = SOURCE_CHANNEL_BIT(ch); + g_sink_cc_relay_close_mask &= (rt_uint8_t)~bit; + g_sink_cc_relay_restore_mask &= (rt_uint8_t)~bit; + if (cc_changed) { + g_sink_cc_relay_close_mask |= bit; + } +} + +void chrg_roll_nor_sink_cc_relay_close(rt_uint8_t ch) +{ + rt_uint8_t bit; + + if (ch >= TOTAL_NOR_CHS) { + return; + } + bit = SOURCE_CHANNEL_BIT(ch); + if ((g_sink_cc_relay_close_mask & bit) == 0U) { + return; + } + chrg_nor_sw_rel((eIDX_NOR_CH)ch, 0); + g_sink_cc_relay_close_mask &= (rt_uint8_t)~bit; + g_sink_cc_relay_restore_mask |= bit; + #if SOUTH_COMMAND_DEBUG + rt_kprintf("-------D+D- CLOSE BEFORE CC: CH%d------\n", ch + 1U); + #endif +} + +static void chrg_roll_nor_sink_cc_relay_restore(rt_uint8_t ch) +{ + rt_uint8_t bit; + + if (ch >= TOTAL_NOR_CHS) { + return; + } + bit = SOURCE_CHANNEL_BIT(ch); + if ((g_sink_cc_relay_restore_mask & bit) == 0U) { + return; + } + chrg_nor_sw_rel((eIDX_NOR_CH)ch, ID_SINK); + g_sink_cc_relay_restore_mask &= (rt_uint8_t)~bit; + #if SOUTH_COMMAND_DEBUG + rt_kprintf("-------D+D- OPEN AFTER CC: CH%d------\n", ch + 1U); + #endif } /***************************************************************** @@ -269,10 +327,7 @@ static rt_bool_t chrg_roll_nor_sink_wait_process(rt_uint8_t ch, } g_sink_reset_wait_mask &= (rt_uint8_t)~bit; g_sink_reset_wait_start[ch] = 0U; - chrg_nor_sw_rel((eIDX_NOR_CH)ch, ID_SINK); - #if SOUTH_COMMAND_DEBUG - rt_kprintf("-------D+D- OPEN AFTER RESET: CH%d------\n", ch + 1U); - #endif + /* CC实际变化时继电器保持断开,等待CC回码稳定后再恢复。 */ pSW->sub = g_sink_reset_next_sub[ch]; g_sink_reset_next_sub[ch] = 0U; return RT_TRUE; @@ -332,6 +387,7 @@ static rt_bool_t chrg_roll_nor_sink_wait_process(rt_uint8_t ch, } } else { if ((g_sink_cc_wait_mask & bit) == 0U) { + chrg_roll_nor_sink_cc_relay_restore(ch); if ((pSW->sub == IDX_WAIT_SINK_CC_BEFORE_PD) || (pSW->sub == IDX_WAIT_SINK_CC_BEFORE_PD_WITH_MODE)) { pSW->sub = (pSW->sub == IDX_WAIT_SINK_CC_BEFORE_PD_WITH_MODE) ? @@ -349,12 +405,13 @@ static rt_bool_t chrg_roll_nor_sink_wait_process(rt_uint8_t ch, if ((pSW->sub == IDX_WAIT_SINK_CC_BEFORE_PD) || (pSW->sub == IDX_WAIT_SINK_CC_BEFORE_PD_WITH_MODE)) { - /* CC先设置完成后进入协议设置,不立即查询电压。 */ + /* CC稳定后恢复北向继电器,再进入协议设置。 */ g_sink_query_throttle[ch] = RT_FALSE; g_sink_query_first_pending[ch] = RT_FALSE; g_sink_query_tick[ch] = 0U; g_sink_cc_wait_mask &= (rt_uint8_t)~bit; g_sink_cc_wait_start[ch] = 0U; + chrg_roll_nor_sink_cc_relay_restore(ch); pSW->sub = (pSW->sub == IDX_WAIT_SINK_CC_BEFORE_PD_WITH_MODE) ? IDX_SET_SINK_PD_WITH_MODE : IDX_SET_SINK_PD; return RT_TRUE; @@ -366,6 +423,7 @@ static rt_bool_t chrg_roll_nor_sink_wait_process(rt_uint8_t ch, g_sink_query_tick[ch] = g_sink_cc_wait_start[ch]; g_sink_cc_wait_mask &= (rt_uint8_t)~bit; g_sink_cc_wait_start[ch] = 0U; + chrg_roll_nor_sink_cc_relay_restore(ch); pSW->sub = IDX_GET_SINK_VC; return RT_TRUE; } @@ -961,10 +1019,17 @@ static int chrg_roll_nor_auto_request(rt_uint8_t idx, (rt_uint8_t)pSW->source.protocol); } else if ((expected_id == ID_SINK) && (request_sub == IDX_SET_SINK_RESET)) { - /* Reset回码确认后断开D+/D-和CC,每通道独立计时100ms。 */ - chrg_nor_sw_rel((eIDX_NOR_CH)idx, 0); - g_sink_reset_wait_mask |= SOURCE_CHANNEL_BIT(idx); - g_sink_reset_wait_start[idx] = rt_tick_get(); + /* 仅CC参数实际变化时,复位回码后保持继电器断开100ms。 + * CC未变化时只重设被复位清除的CC选择,不动作继电器。 */ + if ((g_sink_cc_relay_restore_mask & + SOURCE_CHANNEL_BIT(idx)) != 0U) { + g_sink_reset_wait_mask |= SOURCE_CHANNEL_BIT(idx); + g_sink_reset_wait_start[idx] = rt_tick_get(); + } else { + pSW->sub = g_sink_reset_next_sub[idx]; + g_sink_reset_next_sub[idx] = 0U; + advance_sub = RT_FALSE; + } } else if ((expected_id == ID_SINK) && ((request_sub == IDX_SET_SINK_CCLINE) || (request_sub == IDX_SET_SINK_CC_BEFORE_PD) || diff --git a/apps/chrg/applications/thread/chrg_roll_nor.h b/apps/chrg/applications/thread/chrg_roll_nor.h index 13957a6..75ad32e 100644 --- a/apps/chrg/applications/thread/chrg_roll_nor.h +++ b/apps/chrg/applications/thread/chrg_roll_nor.h @@ -32,7 +32,7 @@ enum { /* Sink北向事务状态。 */ IDX_SET_SINK_RESET, // 协议类型切换时复位Sink协议板 - IDX_WAIT_SINK_RESET_RELAY, // 复位回码后断开北向继电器100ms + IDX_WAIT_SINK_RESET_RELAY, // 复位回码后仅在实际切换CC时保持北向继电器断开100ms IDX_WAIT_SINK_CC, // CC设置应答后的非阻塞稳定等待 IDX_SET_SINK_CC_BEFORE_PD, // 先设置CC,稳定后再设置协议 IDX_WAIT_SINK_CC_BEFORE_PD, // 等待CC稳定后进入协议设置 @@ -106,6 +106,11 @@ extern void chrg_roll_nor_sink_reset_prepare(rt_uint8_t ch, rt_uint8_t next_sub); /* 停止或角色切换时取消未完成的Sink复位等待。 */ extern void chrg_roll_nor_sink_reset_cancel(rt_uint8_t ch); +/* 登记本次完整握手是否实际切换CC;仅实际切换时才断开北向继电器。 */ +extern void chrg_roll_nor_sink_cc_switch_prepare(rt_uint8_t ch, + rt_bool_t cc_changed); +/* 低电流确认完成后,按登记结果断开D+/D-/CC继电器。 */ +extern void chrg_roll_nor_sink_cc_relay_close(rt_uint8_t ch); #define sink_time 3 #endif diff --git a/apps/chrg/applications/utils/chrg_def.h b/apps/chrg/applications/utils/chrg_def.h index 9b6513c..f47ea70 100644 --- a/apps/chrg/applications/utils/chrg_def.h +++ b/apps/chrg/applications/utils/chrg_def.h @@ -14,8 +14,8 @@ /* CHRG application version. Keep this value synchronized with the changelog. */ #define CHRG_VERSION_MAJOR 1U #define CHRG_VERSION_MINOR 1U -#define CHRG_VERSION_PATCH 54U -#define CHRG_VERSION_STRING "V1.1.54" +#define CHRG_VERSION_PATCH 55U +#define CHRG_VERSION_STRING "V1.1.55" /* * Channel polling mode: diff --git a/apps/chrg/applications/utils/chrg_sink.c b/apps/chrg/applications/utils/chrg_sink.c index ac378ca..a9c6c17 100644 --- a/apps/chrg/applications/utils/chrg_sink.c +++ b/apps/chrg/applications/utils/chrg_sink.c @@ -1018,7 +1018,8 @@ static int chrg_sink_work_current_wait(eIDX_SOU_CH idx, g_sink_unload_batch_confirmed[idx] = RT_FALSE; g_sink_unload_confirm_count[idx] = 0U; if (next_action == SINK_UNLOAD_NEXT_HANDSHAKE) { - /* 协议或CC切换保持南向继电器状态,低电流确认后直接开始北向配置。 */ + /* 仅实际切换CC时断开北向D+/D-/CC;协议类型单独变化不动作继电器。 */ + chrg_roll_nor_sink_cc_relay_close((rt_uint8_t)idx); pSW->sink.work_mode = SINK_WORK_WAIT; } else if (next_action == SINK_UNLOAD_NEXT_STOP_RELAY) { pSW->sink.work_mode = SINK_WORK_STOP_RELAY; diff --git a/docs/修改日志.md b/docs/修改日志.md index 04b218d..08c6e10 100644 --- a/docs/修改日志.md +++ b/docs/修改日志.md @@ -1,5 +1,14 @@ # 修改日志 +## V1.1.55 - 2026-10-09 + +### Sink协议切换复位开关 + +- 新增 `SINK_PROTOCOL_SWITCH_RESET_ENABLE`:设为 `1` 时协议类型变化先复位Sink;设为 `0` 时直接设置协议。 +- 仅上位机CC参数实际变化时才断开北向D+/D-/CC继电器;协议类型单独变化不会断开继电器。 +- 协议复位清除内部CC选择后,仍会重新设置CC再发送协议。 +- 协议板版本寄存器 `0x0300` 更新为 `0x0147`。 + ## V1.1.54 - 2026-10-05 ### 南向写寄存器打印通道号