feat: 新增Sink协议切换复位开关及版本更新

修改了短路测试不能四个通道同时的问题,增加了协议板版本切换宏定义,老版本用0,新版本用1

1 新增SINK_PROTOCOL_SWITCH_RESET_ENABLE宏控制协议切换是否先复位Sink
2 仅CC参数实际变化时才断开北向D+/D-/CC继电器
3 更新协议板版本寄存器为0x0147,软件版本升至V1.1.55
4 修改相关状态机及函数实现复位开关逻辑
5 更新修改日志文档记录本次变更
This commit is contained in:
wrh
2026-10-09 09:30:20 +08:00
parent d932c98dc8
commit 42e1174516
7 changed files with 112 additions and 22 deletions
+11 -8
View File
@@ -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 {
@@ -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
+75 -10
View File
@@ -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) ||
@@ -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
+2 -2
View File
@@ -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:
+2 -1
View File
@@ -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;
+9
View File
@@ -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
### 南向写寄存器打印通道号