diff --git a/apps/chrg/applications/thread/chrg_comm.c b/apps/chrg/applications/thread/chrg_comm.c
index c1e7eaa..c9fff7d 100644
--- a/apps/chrg/applications/thread/chrg_comm.c
+++ b/apps/chrg/applications/thread/chrg_comm.c
@@ -2348,6 +2348,7 @@ static eMBException chrg_comm_apply_sink_effect(rt_uint8_t ch,
rt_uint8_t old_cv_mode = pReal->CV_mode;
rt_uint16_t old_loadv = pReal->sink.loadv;
rt_uint16_t old_loadc = pReal->sink.loadc;
+ rt_uint8_t old_on_work = pReal->sink.On_work;
rt_uint8_t old_work_mode = pReal->sink.work_mode;
rt_uint16_t sink_work = pShadow->sink.Now_State;
chrg_param_diff_t diff_info;
@@ -2383,11 +2384,13 @@ static eMBException chrg_comm_apply_sink_effect(rt_uint8_t ch,
}
pReal->sink.test.test_mode_old = curr_test;
} else {
+ /* Protocol-before-CC test flow is disabled in this version. */
pReal->sub = IDX_SET_SINK_CC_BEFORE_PD;
pReal->sink.work_mode = SINK_WORK_INIT;
}
} else if (pReal->sink.On_work == 0) {
pReal->sink.On_work = 1;
+ /* Protocol-before-CC test flow is disabled in this version. */
pReal->sub = IDX_SET_SINK_CC_BEFORE_PD;
pReal->sink.work_mode = SINK_WORK_INIT;
} else if (full_handshake_change) {
@@ -2398,6 +2401,7 @@ static eMBException chrg_comm_apply_sink_effect(rt_uint8_t ch,
* 仅协议变化时不重复设置未变化的CC。
*/
if (diff_info.cc_changed && protocol_data_changed) {
+ /* Protocol-before-CC test flow is disabled in this version. */
pReal->sub = IDX_SET_SINK_CC_BEFORE_PD;
} else if (diff_info.cc_changed) {
pReal->sub = IDX_SET_SINK_CCLINE;
@@ -2414,8 +2418,6 @@ static eMBException chrg_comm_apply_sink_effect(rt_uint8_t ch,
pReal->sub = IDX_SET_SINK_PD_ONLY;
if (old_work_mode == SINK_WORK_LOAD_STANDBY) {
pReal->sink.work_mode = SINK_WORK_WAIT;
- } else if (old_work_mode == SINK_WORK_LOAD_SOFT_STANDBY) {
- pReal->sink.work_mode = SINK_WORK_SOFT_RESUME_WAIT;
} else {
/* 运行状态修改协议参数时保持继电器,只停止电子负载。 */
pReal->sink.work_mode = SINK_WORK_PROTOCOL_UNLOAD;
@@ -2432,7 +2434,20 @@ static eMBException chrg_comm_apply_sink_effect(rt_uint8_t ch,
}
} else {
pReal->sink.On_work = 0;
- pReal->sink.work_mode = SINK_WORK_STOP;
+ /* 组合控制或上位机重发可能在关机尚未完成时再次提交OFF。
+ * 此时必须保留当前停止阶段,不能重新进入STOP并清零低电流确认次数,
+ * 否则实际电流即使一直为0,也永远累计不到连续5帧。 */
+ if ((old_work_mode == SINK_WORK_STOP_WAIT) ||
+ (old_work_mode == SINK_WORK_STOP_RELAY) ||
+ (old_work_mode == SINK_WORK_STOP_RELAY_WAIT)) {
+ pReal->sink.work_mode = old_work_mode;
+ } else if ((old_on_work == 0U) &&
+ (old_work_mode == SINK_WORK_WAIT)) {
+ /* 已完成停止时重复OFF保持WAIT,不重复操作继电器。 */
+ pReal->sink.work_mode = SINK_WORK_WAIT;
+ } else {
+ pReal->sink.work_mode = SINK_WORK_STOP;
+ }
}
return (chrg_sink_work((eIDX_SOU_CH)ch, pReal) == 0) ?
@@ -2463,8 +2478,7 @@ static rt_bool_t chrg_comm_handle_sink_load_current(
}
should_start = chrg_sink_load_should_start(pReal);
- if ((old_work_mode == SINK_WORK_RUNING) ||
- (old_work_mode == SINK_WORK_SOFT_RUNNING)) {
+ if (old_work_mode == SINK_WORK_RUNING) {
if (!should_start) {
pReal->sink.work_mode = SINK_WORK_LOAD_STOP;
return RT_TRUE;
@@ -2484,18 +2498,6 @@ static rt_bool_t chrg_comm_handle_sink_load_current(
return RT_TRUE;
}
- if (old_work_mode == SINK_WORK_LOAD_SOFT_STANDBY) {
- if (should_start) {
- /*
- * 软待机恢复同样必须先读取北向实际电压。
- * 电压稳定后由解析流程进入SOFT_RESUME,再下发目标电流和WORK_START。
- */
- pReal->sub = IDX_GET_SINK_VC;
- pReal->sink.work_mode = SINK_WORK_SOFT_RESUME_WAIT;
- }
- return RT_TRUE;
- }
-
/* 协议握手期间禁止把低于门限的小电流提前写入南向功率板。 */
return should_start ? RT_FALSE : RT_TRUE;
}
diff --git a/apps/chrg/applications/thread/chrg_north.c b/apps/chrg/applications/thread/chrg_north.c
index 3ecbaeb..fffcacf 100644
--- a/apps/chrg/applications/thread/chrg_north.c
+++ b/apps/chrg/applications/thread/chrg_north.c
@@ -29,8 +29,10 @@
#define SOURCE_QC_MIN_VOLT_MV 5000U // QC2.0/QC3.0允许使用的最低目标电压
#define SOURCE_QC_SWITCH_ERROR 0x04U // Source协议或CC切换失败错误位
#define SINK_CURRENT_START_GRACE_MS 200U // Sink启动后暂不判断无电流的保护时间
-#define SINK_VOLT_STABLE_ERROR_MV 2000U // Sink实际电压与协议目标电压的最大允许误差
-#define SINK_VOLT_STABLE_CONFIRM_COUNT 3U // Sink连续有效稳定电压帧数达到此值后进入RUNING
+#define SINK_VOLT_STABLE_ERROR_MV 2000U // Sink实际电压与协议目标电压的最大允许误差
+#define SINK_VOLT_5V_TARGET_MV 5000U // VSafe5V目标电压,需延长稳定确认时间
+#define SINK_VOLT_CONFIRM_NORMAL_COUNT 5U // 非5V目标连续有效电压确认帧数
+#define SINK_VOLT_CONFIRM_5V_COUNT 15U // 5V目标连续有效电压确认帧数,避免把握手阶段VSafe5V误判为协议稳定
/*****************************************************************
函数名称: chrg_source_apply_protocol_voltage_rule
@@ -82,6 +84,22 @@ static rt_bool_t chrg_sink_voltage_is_stable(rt_uint16_t actual_volt_mv,
RT_TRUE : RT_FALSE;
}
+/*****************************************************************
+函数名称: chrg_sink_voltage_confirm_count
+函数描述: 根据Sink协议目标电压选择进入RUNING前所需的连续稳定帧数
+输入参数: target_volt_mv:当前协议申请的目标电压,单位mV
+输出参数: -
+返回说明: 5V目标返回延长确认帧数,其它目标返回普通确认帧数
+其它说明: 快充协议切换时总线会先经过VSafe5V;当目标本身也是5V时,
+ 单凭电压值无法区分过渡阶段和协议稳定阶段,因此增加确认时间,
+ 防止电子负载提前启动后导致协议板复位
+*****************************************************************/
+static rt_uint8_t chrg_sink_voltage_confirm_count(rt_uint16_t target_volt_mv)
+{
+ return (target_volt_mv == SINK_VOLT_5V_TARGET_MV) ?
+ SINK_VOLT_CONFIRM_5V_COUNT : SINK_VOLT_CONFIRM_NORMAL_COUNT;
+}
+
/*****************************************************************
函数名称: chrg_source_voltage_control
函数描述: 根据目标电压与实际电压统一控制Source电压下发和重试
@@ -225,6 +243,7 @@ void chrg_sink_parse(rt_uint8_t *frame_data, eIDX_SOU_CH idx,
struct chrg_switch_t *pSW, struct chrg_north_t *pNOR)
{
rt_uint16_t volt_mv = ((frame_data[4] << 8) | frame_data[5]) * 10;
+ rt_uint8_t stable_confirm_count;
static rt_uint8_t volt_low[TOTAL_SOU_CHS] = {0};
static rt_uint8_t no_curr[TOTAL_SOU_CHS] = {0};
static rt_uint8_t volt_set_ok[TOTAL_SOU_CHS] = {0};
@@ -234,6 +253,8 @@ void chrg_sink_parse(rt_uint8_t *frame_data, eIDX_SOU_CH idx,
if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
return;
}
+ stable_confirm_count = chrg_sink_voltage_confirm_count(
+ pSW->sink.pro_loadv);
pSW->VZ = ((frame_data[14] << 8) | frame_data[15]);
pSW->VF = ((frame_data[16] << 8) | frame_data[17]);
@@ -246,10 +267,10 @@ void chrg_sink_parse(rt_uint8_t *frame_data, eIDX_SOU_CH idx,
if (volt_mv <= WORK_MIN_VOLT) { // 电压过低,禁止进入工作状态机
volt_stable_count[idx] = 0;
if (volt_set_ok[idx] == 1) {
- if (++volt_low[idx] >= 20) {
+ if (++volt_low[idx] >= 50) {
volt_set_ok[idx] = 0;
no_curr[idx] = 0;
- pSW->sink.work_mode = SINK_WORK_LOW;
+ //pSW->sink.work_mode = SINK_WORK_LOW;
}
}
}
@@ -273,25 +294,19 @@ void chrg_sink_parse(rt_uint8_t *frame_data, eIDX_SOU_CH idx,
else if (chrg_sink_voltage_is_stable(volt_mv,
pSW->sink.pro_loadv)) {
if ((pSW->sink.work_mode != SINK_WORK_RUNING) &&
- (pSW->sink.work_mode != SINK_WORK_SOFT_RUNNING) &&
- (pSW->sink.work_mode != SINK_WORK_LOAD_STANDBY) &&
- (pSW->sink.work_mode != SINK_WORK_LOAD_SOFT_STANDBY)) {
- if (volt_stable_count[idx] < SINK_VOLT_STABLE_CONFIRM_COUNT) {
+ (pSW->sink.work_mode != SINK_WORK_LOAD_STANDBY)) {
+ if (volt_stable_count[idx] < stable_confirm_count) {
volt_stable_count[idx]++;
}
- if (volt_stable_count[idx] >= SINK_VOLT_STABLE_CONFIRM_COUNT) {
- /* 回码已经过CRC、ID、命令和配置版本校验;首帧达到目标
- * 电压附近后立即进入RUNING,不再增加额外稳定等待。 */
+ if (volt_stable_count[idx] >= stable_confirm_count) {
+ /* 回码已经过CRC、ID、命令和配置版本校验,并连续达到当前
+ * 目标对应的确认帧数;5V采用更长窗口过滤VSafe5V过渡阶段。 */
volt_stable_count[idx] = 0;
- pSW->sink.work_mode =
- ((pSW->sink.work_mode == SINK_WORK_SOFT_RESUME_WAIT) ||
- (pSW->sink.work_mode == SINK_WORK_LOAD_RESUME)) ?
- SINK_WORK_SOFT_RESUME : SINK_WORK_RUNING;
+ pSW->sink.work_mode = SINK_WORK_RUNING;
running_start_tick[idx] = rt_tick_get();
no_curr[idx] = 0;
}
- } else if ((pSW->sink.work_mode == SINK_WORK_LOAD_STANDBY) ||
- (pSW->sink.work_mode == SINK_WORK_LOAD_SOFT_STANDBY)) {
+ } else if (pSW->sink.work_mode == SINK_WORK_LOAD_STANDBY) {
/* 协议保持在线但电子负载主动停止,不执行无电流重试。 */
volt_stable_count[idx] = 0;
no_curr[idx] = 0;
diff --git a/apps/chrg/applications/thread/chrg_north.h b/apps/chrg/applications/thread/chrg_north.h
index fb6fc7e..b3c9a78 100644
--- a/apps/chrg/applications/thread/chrg_north.h
+++ b/apps/chrg/applications/thread/chrg_north.h
@@ -26,7 +26,7 @@
#define NORTH_SOURCE_DEBUG 0x00 // Source协议解析及组帧
#define NORTH_SINK_DEBUG 0x00 // Sink协议解析及组帧
#define SOUTH_FRAME_DEBUG 0x00 // 南向UART原始收发帧
-#define SOUTH_COMMAND_DEBUG 0x00 // 南向寄存器写命令
+#define SOUTH_COMMAND_DEBUG 0x01 // 南向寄存器写命令
#define COMM_FRAME_DEBUG 0x00 // COM UART原始收发帧
#define COMM_DEBUG 0x00 // COM寄存器读写过程
#define COMM_TRIM_DEBUG 0x00 // COM校准参数解析
diff --git a/apps/chrg/applications/thread/chrg_roll_nor.c b/apps/chrg/applications/thread/chrg_roll_nor.c
index a70d980..020c691 100644
--- a/apps/chrg/applications/thread/chrg_roll_nor.c
+++ b/apps/chrg/applications/thread/chrg_roll_nor.c
@@ -82,7 +82,6 @@ static rt_bool_t chrg_roll_nor_sink_query_is_slow(
}
return (pSW->sink.work_mode == SINK_WORK_WAIT) ||
(pSW->sink.work_mode == SINK_WORK_INIT_AUX_WAIT) ||
- (pSW->sink.work_mode == SINK_WORK_SOFT_RESUME_WAIT) ||
(pSW->sink.work_mode == SINK_WORK_LOW_MONITOR);
}
@@ -283,6 +282,13 @@ static rt_bool_t chrg_roll_nor_sink_wait_process(rt_uint8_t ch,
}
bit = SOURCE_CHANNEL_BIT(ch);
+ /* 关机必须先完成南向低电流确认和继电器批次,期间禁止北向发送。 */
+ if ((pSW->sink.work_mode == SINK_WORK_STOP_WAIT) ||
+ (pSW->sink.work_mode == SINK_WORK_STOP_RELAY) ||
+ (pSW->sink.work_mode == SINK_WORK_STOP_RELAY_WAIT)) {
+ return RT_TRUE;
+ }
+
if ((pSW->id != ID_SINK) || !pSW->sink.On_work) {
g_sink_cc_wait_mask &= (rt_uint8_t)~bit;
g_sink_cc_wait_start[ch] = 0U;
@@ -297,18 +303,16 @@ static rt_bool_t chrg_roll_nor_sink_wait_process(rt_uint8_t ch,
return RT_TRUE;
}
- /*
- * 完整握手批次最后发送FU_REL_ON。批次完成并建立量测基线后,
- * 允许北向协议/CC与南向低电流确认并行;当sub进入GET_SINK_VC
- * 而状态仍为HANDSHAKE_WAIT时,说明低电流确认尚未完成,禁止发送0x20。
- */
+ /* 协议或CC切换必须先完成低电流确认;该过程保持南向继电器状态不变。 */
if (pSW->sink.work_mode == SINK_WORK_HANDSHAKE_WAIT) {
- if (!chrg_sink_handshake_north_ready((eIDX_SOU_CH)ch)) {
- return RT_TRUE;
- }
- if (pSW->sub == IDX_GET_SINK_VC) {
- return RT_TRUE;
- }
+ return RT_TRUE;
+ }
+
+ /* D0回码确认后先经过一个非发送状态,禁止把协议回码当成量测回码。 */
+ if (pSW->sub == IDX_WAIT_SINK_PD_ACK) {
+ pSW->sub = IDX_GET_SINK_VC;
+ chrg_roll_nor_sink_query_wait_start(ch);
+ return RT_TRUE;
}
if ((pSW->sub != IDX_WAIT_SINK_CC) &&
@@ -605,6 +609,9 @@ static rt_uint8_t chrg_roll_nor_expected_cmd(const struct chrg_switch_t *pSW)
return SINK_CMD_GET_PD;
case IDX_SET_SINK_PD:
case IDX_SET_SINK_PD_ONLY:
+#if 0
+ case IDX_SET_SINK_PD_BEFORE_CC:
+#endif
return pSW->sink.protocol;
case IDX_SET_SINK_CCLINE:
case IDX_SET_SINK_CC_BEFORE_PD:
@@ -822,12 +829,18 @@ static int chrg_roll_nor_set(rt_uint8_t ch, struct chrg_switch_t *pSW,
case IDX_SET_SINK_CCLVL: //CC电平
return sink_set_cc_lvl(pSW->sink.cc_lvl);
case IDX_SET_SINK_PD:
- /* CC已经在协议前完成设置,协议回码后直接查询电压。 */
- *next_sub = IDX_GET_SINK_VC;
+ /* 只有协议回码确认后,下一轮才允许进入电压查询。 */
+ *next_sub = IDX_WAIT_SINK_PD_ACK;
return chrg_roll_nor_sink_pro_set(pSW);
case IDX_SET_SINK_PD_ONLY:
- *next_sub = IDX_GET_SINK_VC;
+ *next_sub = IDX_WAIT_SINK_PD_ACK;
return chrg_roll_nor_sink_pro_set(pSW);
+#if 0
+ case IDX_SET_SINK_PD_BEFORE_CC:
+ /* 协议回码确认后再设置CC,不提前查询电压。 */
+ *next_sub = IDX_SET_SINK_CCLINE;
+ return chrg_roll_nor_sink_pro_set(pSW);
+#endif
default:
return -1;
}
@@ -1014,9 +1027,12 @@ void chrg_roll_nor_thread_entry (void *data)
(pSW->sink.work_mode == SINK_WORK_INIT_AUX_WAIT) ||
(pSW->sink.work_mode == SINK_WORK_UNLOAD_WAIT) ||
(pSW->sink.work_mode == SINK_WORK_LOW) ||
- (pSW->sink.work_mode == SINK_WORK_LOW_AUX_WAIT) ||
- (pSW->sink.work_mode == SINK_WORK_HANDSHAKE_PREPARE) ||
- (pSW->sink.work_mode == SINK_WORK_HANDSHAKE_WAIT))) {
+ (pSW->sink.work_mode == SINK_WORK_LOW_AUX_WAIT) ||
+ (pSW->sink.work_mode == SINK_WORK_HANDSHAKE_PREPARE) ||
+ (pSW->sink.work_mode == SINK_WORK_HANDSHAKE_WAIT) ||
+ (pSW->sink.work_mode == SINK_WORK_STOP_WAIT) ||
+ (pSW->sink.work_mode == SINK_WORK_STOP_RELAY) ||
+ (pSW->sink.work_mode == SINK_WORK_STOP_RELAY_WAIT))) {
state_work_ret = chrg_sink_work((eIDX_SOU_CH)idx, pSW);
}
/*
diff --git a/apps/chrg/applications/thread/chrg_roll_nor.h b/apps/chrg/applications/thread/chrg_roll_nor.h
index 9bdfa66..e11def5 100644
--- a/apps/chrg/applications/thread/chrg_roll_nor.h
+++ b/apps/chrg/applications/thread/chrg_roll_nor.h
@@ -52,6 +52,10 @@ enum {
IDX_WAIT_SINK_CC, // CC设置应答后的非阻塞稳定等待
IDX_SET_SINK_CC_BEFORE_PD, // 先设置CC,稳定后再设置协议
IDX_WAIT_SINK_CC_BEFORE_PD, // 等待CC稳定后进入协议设置
+ IDX_WAIT_SINK_PD_ACK, // 协议回码确认后的非发送过渡状态
+#if 0
+ IDX_SET_SINK_PD_BEFORE_CC, // 先设置协议,协议回码后再设置CC
+#endif
};
struct chrg_rollnor_t {
diff --git a/apps/chrg/applications/thread/chrg_roll_sou.c b/apps/chrg/applications/thread/chrg_roll_sou.c
index 5b4a706..2b0d540 100644
--- a/apps/chrg/applications/thread/chrg_roll_sou.c
+++ b/apps/chrg/applications/thread/chrg_roll_sou.c
@@ -29,7 +29,11 @@
#define SOU_CHANNEL_BIT(ch) ((rt_uint8_t)(1U << (ch)))
chrg_rollsou_com_t g_sou_com_batch = {0};
-static rt_uint8_t g_sou_measure_once_mask = 0U;
+/* 一次性P1量测分别记录待发送请求和正在等待回码的请求。
+ * 当前帧尚未结束时再次申请的下一帧保存在pending中,不能被当前帧
+ * 的完成处理清除,否则多通道运行时低电流确认会间歇性停止推进。 */
+static rt_uint8_t g_sou_measure_once_pending_mask = 0U;
+static rt_uint8_t g_sou_measure_once_active_mask = 0U;
struct chrg_rollsou_t chrgrollsou = {
.run = RUN_AUTO,
@@ -223,7 +227,7 @@ int chrg_sou_measure_once_submit(eIDX_SOU_CH ch)
rt_tick_from_millisecond(SOU_MUTEX_TIMEOUT_MS)) != RT_EOK)) {
return -1;
}
- g_sou_measure_once_mask |= SOU_CHANNEL_BIT(ch);
+ g_sou_measure_once_pending_mask |= SOU_CHANNEL_BIT(ch);
rt_mutex_release(pTHR->mutex);
return 0;
}
@@ -247,7 +251,13 @@ static int sou_measure_once_next(rt_uint8_t *ch)
return -1;
}
for (idx = 0; idx < TOTAL_SOU_CHS; idx++) {
- if ((g_sou_measure_once_mask & SOU_CHANNEL_BIT(idx)) != 0U) {
+ rt_uint8_t bit = SOU_CHANNEL_BIT(idx);
+
+ if ((g_sou_measure_once_pending_mask & bit) != 0U) {
+ /* 发送前从pending转移到active。查询等待期间的新申请会重新
+ * 置pending位,并在当前查询结束后继续执行。 */
+ g_sou_measure_once_pending_mask &= (rt_uint8_t)~bit;
+ g_sou_measure_once_active_mask |= bit;
*ch = idx;
rt_mutex_release(pTHR->mutex);
return 1;
@@ -274,7 +284,8 @@ static void sou_measure_once_finish(rt_uint8_t ch)
rt_tick_from_millisecond(SOU_MUTEX_TIMEOUT_MS)) != RT_EOK)) {
return;
}
- g_sou_measure_once_mask &= (rt_uint8_t)~SOU_CHANNEL_BIT(ch);
+ /* 只结束当前正在等待的查询;等待期间登记的下一帧pending请求必须保留。 */
+ g_sou_measure_once_active_mask &= (rt_uint8_t)~SOU_CHANNEL_BIT(ch);
rt_mutex_release(pTHR->mutex);
}
@@ -607,7 +618,8 @@ int chrg_sou_com_batch_cancel(eIDX_SOU_CH ch)
pBatch->reg_cnt = 0;
pBatch->next_send_tick = 0U;
/* 已取消事务对应的优先P1量测同样失效,后续状态会重新申请新量测。 */
- g_sou_measure_once_mask &= (rt_uint8_t)~SOU_CHANNEL_BIT(ch);
+ g_sou_measure_once_pending_mask &= (rt_uint8_t)~SOU_CHANNEL_BIT(ch);
+ g_sou_measure_once_active_mask &= (rt_uint8_t)~SOU_CHANNEL_BIT(ch);
rt_mutex_release(pTHR->mutex);
return 0;
}
diff --git a/apps/chrg/applications/utils/chrg_sink.c b/apps/chrg/applications/utils/chrg_sink.c
index fa6d1f2..7641b1f 100644
--- a/apps/chrg/applications/utils/chrg_sink.c
+++ b/apps/chrg/applications/utils/chrg_sink.c
@@ -22,16 +22,29 @@
#define SINK_UNLOAD_QUERY_INTERVAL_MS 20U // 卸载期间两次优先量测请求的最小间隔
#define SINK_UNLOAD_CURRENT_MAX_MA 200U // 判定负载已安全卸载的最大实际电流
-#define SINK_UNLOAD_CONFIRM_COUNT 2U // 连续满足低电流条件的量测帧数
-#define SINK_CLOSE_CURRENT_MA 1000U // 安全关闭阶段写入功率板的电流设定值
+#define SINK_UNLOAD_CONFIRM_COUNT 5U // 连续满足低电流条件的量测帧数
+
+/* 主继电器闭合跟踪:1=已提交ALL_REL_ON(主继电器应已闭合) 0=未闭合/已断开。
+ * 用于0V硬保护区分"首次开载/握手恢复"(主继电器未闭合,Now_voltage=0属正常)
+ * 与"运行或待机中主继电器已闭合但输入电压为0"(协议板断电窗口,禁止开载)。 */
+static rt_uint8_t g_sink_rel_main_closed[TOTAL_SOU_CHS] = {0};
+
+/* 主继电器电压到位确认:1=提交闭合后实测电压已到达工作下限,继电器确认闭合。
+ * 持续0V监控只对已到位通道生效,避免继电器动作期间(电压尚未建立)误触发掉电保护。 */
+static rt_uint8_t g_sink_rel_main_ready[TOTAL_SOU_CHS] = {0};
/* 卸载确认只接受停止批次成功后产生的新P1量测。 */
static rt_uint32_t g_sink_unload_sample_seq[TOTAL_SOU_CHS] = {0};
static rt_bool_t g_sink_unload_batch_confirmed[TOTAL_SOU_CHS] = {RT_FALSE};
-static rt_bool_t g_sink_unload_current_confirmed[TOTAL_SOU_CHS] = {RT_FALSE};
static rt_tick_t g_sink_unload_query_tick[TOTAL_SOU_CHS] = {0};
static rt_uint8_t g_sink_unload_confirm_count[TOTAL_SOU_CHS] = {0};
+enum {
+ SINK_UNLOAD_NEXT_RUNNING = 0,
+ SINK_UNLOAD_NEXT_HANDSHAKE,
+ SINK_UNLOAD_NEXT_STOP_RELAY
+};
+
/*****************************************************************
函数名称: chrg_sink_load_should_start
函数描述: 判断普通负载的设定值是否允许启动南向电子负载
@@ -68,7 +81,6 @@ static void chrg_sink_unload_confirm_reset(eIDX_SOU_CH idx)
}
g_sink_unload_sample_seq[idx] = 0U;
g_sink_unload_batch_confirmed[idx] = RT_FALSE;
- g_sink_unload_current_confirmed[idx] = RT_FALSE;
g_sink_unload_query_tick[idx] = 0U;
g_sink_unload_confirm_count[idx] = 0U;
}
@@ -83,14 +95,6 @@ static void chrg_sink_unload_confirm_reset(eIDX_SOU_CH idx)
其它说明: 基线建立后返回成功,实际低电流确认仍由当前状态函数继续执行;
用于允许北向协议/CC与南向低电流确认并行推进
*****************************************************************/
-rt_bool_t chrg_sink_handshake_north_ready(eIDX_SOU_CH idx)
-{
- if (idx >= TOTAL_SOU_CHS) {
- return RT_FALSE;
- }
- return g_sink_unload_current_confirmed[idx];
-}
-
/*****************************************************************
函数名称: chrg_sink_unload_query_submit
函数描述: 按最小间隔提交当前通道的一次性P1量测请求
@@ -253,7 +257,7 @@ static int chrg_sink_work_init(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
first_start = (pSW->sink.work_mode != SINK_WORK_INIT_AUX_WAIT) ?
RT_TRUE : RT_FALSE;
vals[2] = pSW->CV_mode;
- vals[3] = pSW->sink.volt_on;
+ vals[3] = pSW->sink.volt_on <= 500 ? 500 : pSW->sink.volt_on;
if (pSW->sink.test.test_mode_old == SINK_TEST_SHORT) {
regs[count] = ModbusRTU_ShortTest_CMD_MODE_FLAG;
vals[count++] = ModbusRTU_DYNA_CMD_MODE_STOP;
@@ -273,6 +277,7 @@ static int chrg_sink_work_init(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
/* 南向批次已入队,北向按“CC->协议”顺序立即开始完整握手。 */
chrg_nor_sw_rel((eIDX_NOR_CH)idx, ID_SINK);
pNOR->enable[idx] = 1;
+ /* Protocol-before-CC test flow is disabled in this version. */
pSW->sub = IDX_SET_SINK_CC_BEFORE_PD;
}
pSW->sink.work_mode = SINK_WORK_INIT_AUX_WAIT;
@@ -312,6 +317,40 @@ static int chrg_sink_work_init_aux_wait(eIDX_SOU_CH idx,
return 0;
}
+/*****************************************************************
+函数名称: chrg_sink_volt_low_protect
+函数描述: 主继电器闭合后持续监控南向实测输入电压,掉电立即转掉电保护
+输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体
+输出参数: 电压到位时确认ready;掉电时强制进入SINK_WORK_LOW并执行掉电批次
+返回说明: 0:正常或保护批次已提交 <0:参数错误或保护批次提交失败
+其它说明: 由北向轮询线程每轮调用,不依赖北向0x20回码。协议板断电时北向
+ 回码会中断(volt_low计数不再累积),而南向P1量测由功率板独立
+ 供电持续刷新,是本保护唯一可靠的电量来源。只有"提交闭合且实测
+ 电压已到位"的通道才启用掉电判定,继电器动作期间不误触发
+*****************************************************************/
+int chrg_sink_volt_low_protect(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
+{
+ if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
+ return -1;
+ }
+ if (g_sink_rel_main_closed[idx] == 0) {
+ return 0;
+ }
+ if (pSW->Now_voltage >= WORK_MIN_VOLT) {
+ /* 实测电压到达工作下限,确认主继电器已闭合。 */
+ g_sink_rel_main_ready[idx] = 1;
+ return 0;
+ }
+ if (g_sink_rel_main_ready[idx] != 0) {
+ /* 曾经到位后再次掉电:协议板处于断电窗口,禁止负载带载,
+ * 强制进入掉电安全处理等待协议板重新上电。 */
+ pSW->sink.work_mode = SINK_WORK_LOW;
+ return chrg_sink_work(idx, pSW);
+ }
+ /* 已提交闭合但电压尚未建立(继电器动作中),继续等待不保护。 */
+ return 0;
+}
+
/*****************************************************************
函数名称: chrg_sink_work_volt_runing
函数描述: 执行负载RUNING状态,闭合全部继电器并启动负载
@@ -342,70 +381,40 @@ static int chrg_sink_work_volt_runing(eIDX_SOU_CH idx, struct chrg_switch_t *pSW
ret = chrg_sou_com_batch_submit(idx, stop_regs, stop_vals, 2U);
if (ret == 0) {
pSW->sink.work_mode = SINK_WORK_LOAD_STANDBY;
+ g_sink_rel_main_closed[idx] = 1;
}
return ret;
}
- if (pSW->CV_mode == MODE_CONSTANT_VOLTAGE) {
- regs[2] = REG_VOLTAGE_OUT + 1;
- vals[2] = pSW->sink.loadv;
- } else {
- regs[2] = REG_CURRENT_OUT + 1;
- vals[2] = pSW->sink.loadc;
+ /* 只有南向实测电压曾经到位后再次掉到低压,才判定为掉电。
+ * 初次RUNING时继电器批次刚入队,Now_voltage可能仍是上一帧的0,
+ * 此时不能取消尚未发送到WORK_START的启动批次。 */
+ if ((g_sink_rel_main_ready[idx] != 0) &&
+ (pSW->Now_voltage < WORK_MIN_VOLT)) {
+ pSW->sink.work_mode = SINK_WORK_LOW;
+ return 0;
}
- return chrg_sou_com_batch_submit(idx, regs, vals, 3U);
-}
-/*****************************************************************
-函数名称: chrg_sink_work_soft_resume
-函数描述: 协议电压或协议电流变化完成后恢复负载
-输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体
-输出参数: 命令入队成功后将工作状态切换为SINK_WORK_SOFT_RUNNING
-返回说明: 0:命令提交成功 <0:参数或命令提交失败
-其它说明: 命令顺序为ALL_REL_ON、目标电流/电压、WORK_START;快速切换时
- 主继电器可能在完整握手阶段被关闭,恢复必须先确保继电器闭合
- 再启动电子负载,避免WORK_START先于主继电器带载;南向固件
- 继电器独立控制,ALL_REL_ON只开不关,不会误关已闭合的副继电器
-*****************************************************************/
-static int chrg_sink_work_soft_resume(eIDX_SOU_CH idx,
- struct chrg_switch_t *pSW)
-{
- rt_uint16_t regs[3] = {REG_REL_ON, 0, REG_WORK};
- rt_uint16_t vals[3] = {ALL_REL_ON, 0, WORK_START};
- int ret;
-
- if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
- return -1;
- }
- if (!chrg_sink_load_should_start(pSW)) {
- /* 软卸载未切继电器,低电流下保持原继电器和协议,只关闭电子负载。 */
- regs[0] = REG_WORK;
- vals[0] = WORK_STOP;
- ret = chrg_sou_com_batch_submit(idx, regs, vals, 1U);
- if (ret == 0) {
- pSW->sink.work_mode = SINK_WORK_LOAD_SOFT_STANDBY;
- }
- return ret;
- }
if (pSW->CV_mode == MODE_CONSTANT_VOLTAGE) {
- regs[2] = REG_VOLTAGE_OUT + 1;
- vals[2] = pSW->sink.loadv;
+ regs[1] = REG_VOLTAGE_OUT + 1;
+ vals[1] = pSW->sink.loadv;
} else {
- regs[2] = REG_CURRENT_OUT + 1;
- vals[2] = pSW->sink.loadc;
+ regs[1] = REG_CURRENT_OUT + 1;
+ vals[1] = pSW->sink.loadc;
}
- if (chrg_sou_com_batch_submit(idx, regs, vals, 3U) != 0) {
- return -1;
+ /* RUNING批次必须完整发送:ALL_REL_ON、目标负载值、WORK_START。 */
+ ret = chrg_sou_com_batch_submit(idx, regs, vals, 3U);
+ if (ret == 0) {
+ g_sink_rel_main_closed[idx] = 1;
}
- pSW->sink.work_mode = SINK_WORK_SOFT_RUNNING;
- return 0;
+ return ret;
}
/*****************************************************************
函数名称: chrg_sink_work_load_stop
函数描述: 普通负载运行中设定电流降到最低门限以下时安全停止带载
输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体
-输出参数: 命令入队成功后进入SINK_WORK_LOAD_SOFT_STANDBY
+输出参数: 命令入队成功后进入SINK_WORK_LOAD_STANDBY
返回说明: 0:命令提交成功 <0:参数或命令提交失败
其它说明: 命令只发送WORK_STOP;不改变北向协议、CC、电流设定和
主副继电器,保证后续恢复有效电流时无需重新协议握手
@@ -422,26 +431,7 @@ static int chrg_sink_work_load_stop(eIDX_SOU_CH idx,
if (chrg_sou_com_batch_submit(idx, ®, &val, 1U) != 0) {
return -1;
}
- pSW->sink.work_mode = SINK_WORK_LOAD_SOFT_STANDBY;
- return 0;
-}
-
-/*****************************************************************
-函数名称: chrg_sink_work_load_resume
-函数描述: 从保持继电器的低电流待机状态恢复普通电子负载
-输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体
-输出参数: 命令入队成功后进入SINK_WORK_SOFT_RUNNING
-返回说明: 0:命令提交成功 <0:参数或命令提交失败
-其它说明: 本状态只作为待恢复标记,不直接下发WORK_START;必须由北向解析确认
- 实际电压稳定后转入SINK_WORK_SOFT_RESUME,再恢复目标电流和WORK_START
-*****************************************************************/
-static int chrg_sink_work_load_resume(eIDX_SOU_CH idx,
- struct chrg_switch_t *pSW)
-{
- if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL) ||
- !chrg_sink_load_should_start(pSW)) {
- return -1;
- }
+ pSW->sink.work_mode = SINK_WORK_LOAD_STANDBY;
return 0;
}
@@ -477,12 +467,8 @@ static int chrg_sink_work_load_start(eIDX_SOU_CH idx,
*****************************************************************/
static int chrg_sink_nor_work_low(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
{
- rt_uint16_t regs[4] = {
- REG_WORK, REG_CURRENT_OUT + 1, REG_REL_ON, REG_REL_ON
- };
- rt_uint16_t vals[4] = {
- WORK_STOP, SINK_CLOSE_CURRENT_MA, ALL_REL_OFF, FU_REL_ON
- };
+ rt_uint16_t reg = REG_WORK;
+ rt_uint16_t value = WORK_STOP;
if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
return -1;
@@ -491,9 +477,14 @@ static int chrg_sink_nor_work_low(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
if (chrg_sou_com_batch_cancel(idx) != 0) {
return -1;
}
- if (chrg_sou_com_batch_submit(idx, regs, vals, 4U) != 0) {
+ /* Low voltage stops the electronic load only. Do not alter South relays:
+ * an intentional protocol transition must not cause a relay-induced drop. */
+ if (chrg_sou_com_batch_submit(idx, ®, &value, 1U) != 0) {
return -1;
}
+ /* 主继电器已随掉电批次断开,闭合跟踪与电压到位确认一并清除。 */
+ g_sink_rel_main_closed[idx] = 0;
+ g_sink_rel_main_ready[idx] = 0;
pSW->sink.work_mode = SINK_WORK_LOW_AUX_WAIT;
return 0;
}
@@ -535,22 +526,74 @@ static int chrg_sink_work_low_aux_wait(eIDX_SOU_CH idx,
返回说明: 0:关机成功 <0:停止命令提交失败
其它说明: 先断开功率继电器并发送WORK_STOP,再关闭软件通道
*****************************************************************/
-static int chrg_sink_nor_work_off(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
-{
+static int chrg_sink_work_stop_prepare(eIDX_SOU_CH idx,
+ struct chrg_switch_t *pSW)
+{
+ rt_uint16_t reg = REG_WORK;
+ rt_uint16_t value = WORK_STOP;
+
+ if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
+ return -1;
+ }
+ if (chrg_sou_com_batch_cancel(idx) != 0) {
+ return -1;
+ }
+ if (chrg_sou_com_batch_submit(idx, ®, &value, 1U) != 0) {
+ return -1;
+ }
+
+ /* 主动关机先停止电子负载。WORK_STOP收到匹配回码后,必须通过
+ * 停止命令之后的新P1量测连续确认低电流,才允许断开功率继电器。 */
+ chrg_sink_unload_confirm_reset(idx);
+ pSW->sink.work_mode = SINK_WORK_STOP_WAIT;
+ return 0;
+}
+
+static int chrg_sink_work_stop_relay(eIDX_SOU_CH idx,
+ struct chrg_switch_t *pSW)
+{
+ rt_uint16_t reg = REG_REL_ON;
+ rt_uint16_t value = ALL_REL_OFF;
+
+ if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
+ return -1;
+ }
+ if (chrg_sou_com_batch_submit(idx, ®, &value, 1U) != 0) {
+ return -1;
+ }
+
+ /* 继电器关闭命令已提交,等待南向回码后再清理软件通道。 */
+ pSW->sink.work_mode = SINK_WORK_STOP_RELAY_WAIT;
+ return 0;
+}
+
+static int chrg_sink_work_stop_relay_wait(eIDX_SOU_CH idx,
+ struct chrg_switch_t *pSW)
+{
struct chrg_south_t *pSOU = &chrgsouth;
struct chrg_north_t *pNOR = &chrgnorth;
- rt_uint16_t regs[2] = {REG_REL_ON, REG_WORK};
- rt_uint16_t vals[2] = {ALL_REL_OFF, WORK_STOP};
+ int result;
- if (chrg_sou_com_batch_submit(idx, regs, vals, 2) != 0) {
+ if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
return -1;
}
+ if (chrg_sou_com_batch_is_pending(idx)) {
+ return 0;
+ }
+ result = chrg_sou_com_batch_get_result(idx);
+ if (result <= 0) {
+ return chrg_sink_work_stop_relay(idx, pSW);
+ }
pSW->sink.On_work = 0;
pSOU->online[idx] = 0;
pNOR->enable[idx] = 0;
+ g_sink_rel_main_closed[idx] = 0;
+ g_sink_rel_main_ready[idx] = 0;
- chrg_nor_sw_rel((eIDX_NOR_CH)idx, 0); //关闭北向继电器
+ chrg_nor_sw_rel((eIDX_NOR_CH)idx, 0);
+ /* 主动停止已经完成,退出异步等待状态,禁止下一轮重复执行。 */
+ pSW->sink.work_mode = SINK_WORK_WAIT;
return 0;
}
@@ -585,6 +628,7 @@ static int chrg_sink_work_switch(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
/* 停止成功入队后,清除旧Source运行标志。 */
pSW->source.On_Flag = 0;
/* 首次进入Sink时先设置目标CC线,CC稳定后再设置协议。 */
+ /* Protocol-before-CC test flow is disabled in this version. */
pSW->sub = IDX_SET_SINK_CC_BEFORE_PD;
/* SWITCH只负责旧角色退出,后续启动统一交给Sink INIT状态。 */
pSW->sink.work_mode = SINK_WORK_INIT;
@@ -629,12 +673,8 @@ static int chrg_sink_work_protocol_unload(eIDX_SOU_CH idx, struct chrg_switch_t
static int chrg_sink_work_handshake_prepare(eIDX_SOU_CH idx,
struct chrg_switch_t *pSW)
{
- rt_uint16_t regs[4] = {
- REG_WORK, REG_CURRENT_OUT + 1, REG_REL_ON, REG_REL_ON
- };
- rt_uint16_t vals[4] = {
- WORK_STOP, SINK_CLOSE_CURRENT_MA, ALL_REL_OFF, FU_REL_ON
- };
+ rt_uint16_t reg = REG_WORK;
+ rt_uint16_t value = WORK_STOP;
if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
return -1;
@@ -643,11 +683,11 @@ static int chrg_sink_work_handshake_prepare(eIDX_SOU_CH idx,
if (chrg_sou_com_batch_cancel(idx) != 0) {
return -1;
}
- if (chrg_sou_com_batch_submit(idx, regs, vals, 4) != 0) {
+ if (chrg_sou_com_batch_submit(idx, ®, &value, 1U) != 0) {
return -1;
}
- /* 四条写回码完成后,还必须连续确认两帧实际电流不大于200mA。 */
+ /* 协议或CC切换先停止电子负载,连续5次确认低电流后再操作继电器。 */
chrg_sink_unload_confirm_reset(idx);
pSW->sink.work_mode = SINK_WORK_HANDSHAKE_WAIT;
return 0;
@@ -664,7 +704,7 @@ static int chrg_sink_work_handshake_prepare(eIDX_SOU_CH idx,
还要求CURRENT=1000mA、ALL_REL_OFF和FU_REL_ON回码成功,但保持北向Sink继电器接通
*****************************************************************/
static int chrg_sink_work_current_wait(eIDX_SOU_CH idx,
- struct chrg_switch_t *pSW, rt_bool_t full_handshake)
+ struct chrg_switch_t *pSW, rt_uint8_t next_action)
{
rt_uint32_t sample_seq;
int batch_result;
@@ -678,14 +718,24 @@ static int chrg_sink_work_current_wait(eIDX_SOU_CH idx,
batch_result = chrg_sou_com_batch_get_result(idx);
if (batch_result < 0) {
- /* 写命令失败时重新执行完整卸载批次,禁止使用量测值提前放行。 */
- return full_handshake ? chrg_sink_work_handshake_prepare(idx, pSW) :
- chrg_sink_work_protocol_unload(idx, pSW);
+ /* 写命令失败时重新执行停止命令,禁止使用量测值提前放行。 */
+ if (next_action == SINK_UNLOAD_NEXT_HANDSHAKE) {
+ return chrg_sink_work_handshake_prepare(idx, pSW);
+ }
+ if (next_action == SINK_UNLOAD_NEXT_STOP_RELAY) {
+ return chrg_sink_work_stop_prepare(idx, pSW);
+ }
+ return chrg_sink_work_protocol_unload(idx, pSW);
}
if (batch_result == 0) {
- /* 无有效批次结果时保持阻塞,并重新提交完整卸载动作。 */
- return full_handshake ? chrg_sink_work_handshake_prepare(idx, pSW) :
- chrg_sink_work_protocol_unload(idx, pSW);
+ /* 无有效批次结果时保持阻塞,并重新提交停止动作。 */
+ if (next_action == SINK_UNLOAD_NEXT_HANDSHAKE) {
+ return chrg_sink_work_handshake_prepare(idx, pSW);
+ }
+ if (next_action == SINK_UNLOAD_NEXT_STOP_RELAY) {
+ return chrg_sink_work_stop_prepare(idx, pSW);
+ }
+ return chrg_sink_work_protocol_unload(idx, pSW);
}
if (!g_sink_unload_batch_confirmed[idx]) {
@@ -702,10 +752,17 @@ static int chrg_sink_work_current_wait(eIDX_SOU_CH idx,
g_sink_unload_confirm_count[idx]++;
if (g_sink_unload_confirm_count[idx] >= SINK_UNLOAD_CONFIRM_COUNT) {
g_sink_unload_batch_confirmed[idx] = RT_FALSE;
- g_sink_unload_current_confirmed[idx] = RT_TRUE;
g_sink_unload_confirm_count[idx] = 0U;
- pSW->sink.work_mode = full_handshake ?
- SINK_WORK_WAIT : SINK_WORK_SOFT_RESUME_WAIT;
+ if (next_action == SINK_UNLOAD_NEXT_HANDSHAKE) {
+ /* 协议或CC切换保持南向继电器状态,低电流确认后直接开始北向配置。 */
+ pSW->sink.work_mode = SINK_WORK_WAIT;
+ } else if (next_action == SINK_UNLOAD_NEXT_STOP_RELAY) {
+ pSW->sink.work_mode = SINK_WORK_STOP_RELAY;
+ } else {
+ /* Keep relays closed and resume through the common
+ * voltage-confirmed RUNING path. */
+ pSW->sink.work_mode = SINK_WORK_WAIT;
+ }
return 0;
}
} else {
@@ -808,6 +865,7 @@ static int chrg_sink_TEST_OCP_ON(rt_uint8_t ch, struct chrg_switch_t *pSW)
返回说明: 0:状态处理成功 <0:参数、状态或命令提交失败
其它说明: 每通道记录上次成功状态,相同状态不重复下发寄存器
*****************************************************************/
+int workmode = 0;
int chrg_sink_work(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
{
static uint8_t last_state[TOTAL_SOU_CHS] ={100,100,100,100};
@@ -818,9 +876,12 @@ int chrg_sink_work(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
return -1;
}
work_mode = pSW->sink.work_mode;
+ workmode = work_mode;
/* 异步等待状态需要持续检查批次或新量测,其余相同状态保持去重。 */
if ((work_mode == last_state[idx]) &&
(work_mode != SINK_WORK_INIT_AUX_WAIT) &&
+ (work_mode != SINK_WORK_STOP_WAIT) &&
+ (work_mode != SINK_WORK_STOP_RELAY_WAIT) &&
(work_mode != SINK_WORK_UNLOAD_WAIT) &&
(work_mode != SINK_WORK_LOW_AUX_WAIT) &&
(work_mode != SINK_WORK_HANDSHAKE_WAIT)) {
@@ -858,7 +919,17 @@ int chrg_sink_work(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
ret = 0;
break;
case SINK_WORK_STOP:
- ret = chrg_sink_nor_work_off(idx,pSW);
+ ret = chrg_sink_work_stop_prepare(idx, pSW);
+ break;
+ case SINK_WORK_STOP_WAIT:
+ ret = chrg_sink_work_current_wait(idx, pSW,
+ SINK_UNLOAD_NEXT_STOP_RELAY);
+ break;
+ case SINK_WORK_STOP_RELAY:
+ ret = chrg_sink_work_stop_relay(idx, pSW);
+ break;
+ case SINK_WORK_STOP_RELAY_WAIT:
+ ret = chrg_sink_work_stop_relay_wait(idx, pSW);
break;
case SINK_WORK_SWITCH:
ret = chrg_sink_work_switch(idx,pSW);
@@ -867,25 +938,17 @@ int chrg_sink_work(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
ret = chrg_sink_work_protocol_unload(idx, pSW);
break;
case SINK_WORK_UNLOAD_WAIT:
- ret = chrg_sink_work_current_wait(idx, pSW, RT_FALSE);
- break;
- case SINK_WORK_SOFT_RESUME_WAIT:
- ret = 0;
- break;
- case SINK_WORK_SOFT_RESUME:
- ret = chrg_sink_work_soft_resume(idx, pSW);
- break;
- case SINK_WORK_SOFT_RUNNING:
- ret = 0;
+ ret = chrg_sink_work_current_wait(idx, pSW,
+ SINK_UNLOAD_NEXT_RUNNING);
break;
case SINK_WORK_HANDSHAKE_PREPARE:
ret = chrg_sink_work_handshake_prepare(idx, pSW);
break;
case SINK_WORK_HANDSHAKE_WAIT:
- ret = chrg_sink_work_current_wait(idx, pSW, RT_TRUE);
+ ret = chrg_sink_work_current_wait(idx, pSW,
+ SINK_UNLOAD_NEXT_HANDSHAKE);
break;
case SINK_WORK_LOAD_STANDBY:
- case SINK_WORK_LOAD_SOFT_STANDBY:
ret = 0;
break;
case SINK_WORK_LOAD_STOP:
@@ -894,9 +957,6 @@ int chrg_sink_work(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
case SINK_WORK_LOAD_START:
ret = chrg_sink_work_load_start(idx, pSW);
break;
- case SINK_WORK_LOAD_RESUME:
- ret = chrg_sink_work_load_resume(idx, pSW);
- break;
default:
break;
}
diff --git a/apps/chrg/applications/utils/chrg_sink.h b/apps/chrg/applications/utils/chrg_sink.h
index cec49ec..97b544e 100644
--- a/apps/chrg/applications/utils/chrg_sink.h
+++ b/apps/chrg/applications/utils/chrg_sink.h
@@ -208,7 +208,8 @@ enum {
*/
#define SINK_LOAD_ENABLE_MIN_MA 100U
-extern rt_bool_t chrg_sink_handshake_north_ready(eIDX_SOU_CH idx);
+/* 主继电器闭合后的0V持续监控:由北向轮询线程每轮调用,掉电立即转掉电保护。 */
+extern int chrg_sink_volt_low_protect(eIDX_SOU_CH idx, struct chrg_switch_t *pSW);
enum {
SINK_WORK_INIT = 0, // 启动入口:第一条南向命令只打开副继电器
@@ -219,23 +220,21 @@ enum {
SINK_WORK_LOW, // 运行电压过低,执行掉电安全处理
SINK_WORK_LOW_AUX_WAIT, // 等待掉电处理及副继电器恢复批次完成
SINK_WORK_LOW_MONITOR, // 副继电器已恢复,等待输入电压重新出现
- SINK_WORK_STOP, // 用户主动停止负载
+ SINK_WORK_STOP, // 用户主动停止:先停止负载并确认低电流
SINK_WORK_SWITCH, // 停止旧电源后进入负载INIT
SINK_WORK_PROTOCOL_UNLOAD, // 协议电压或电流变化:掉载但不切换继电器
SINK_WORK_UNLOAD_WAIT, // 等待软卸载完成并连续两次确认电流不大于200mA
- SINK_WORK_SOFT_RESUME_WAIT, // 继电器保持闭合,等待协议电压稳定后恢复负载
- SINK_WORK_SOFT_RESUME, // 只恢复目标电流/电压和WORK_START,不写继电器
- SINK_WORK_SOFT_RUNNING, // 软恢复后的稳定运行状态,禁止重复切换继电器
SINK_WORK_ON_TEST_DYNA, // 动态负载测试启动状态
SINK_WORK_ON_TEST_SHORT, // 短路测试启动状态
SINK_WORK_ON_TEST_OCP, // OCP过流保护测试启动状态
SINK_WORK_HANDSHAKE_PREPARE, // 完整重握手:停止、清流、全关继电器后打开副继电器
SINK_WORK_HANDSHAKE_WAIT, // 南向低电流确认与北向协议/CC并行
SINK_WORK_LOAD_STANDBY, // 协议已就绪但主继电器未打开,低设定电流下保持停止
- SINK_WORK_LOAD_SOFT_STANDBY, // 协议和继电器保持不变,运行中降至低电流后的停止状态
SINK_WORK_LOAD_STOP, // 运行中跨到低电流:只发送WORK_STOP关闭电子负载
SINK_WORK_LOAD_START, // 主继电器未打开的低电流待机恢复:等待北向电压稳定后进入RUNING
- SINK_WORK_LOAD_RESUME, // 软待机跨回有效电流:等待北向电压稳定后进入SOFT_RESUME
+ SINK_WORK_STOP_WAIT, // 关机:等待连续5次实际电流达到安全范围
+ SINK_WORK_STOP_RELAY, // 关机:低电流确认后提交关闭南向继电器
+ SINK_WORK_STOP_RELAY_WAIT // 关机:等待关闭南向继电器的回码
};
// sink 参数结构
diff --git a/apps/chrg/chrg.uvprojx b/apps/chrg/chrg.uvprojx
index 1b82e8a..6090132 100644
--- a/apps/chrg/chrg.uvprojx
+++ b/apps/chrg/chrg.uvprojx
@@ -132,7 +132,7 @@
1
0
0
- 0
+ 1
1
4096
diff --git a/apps/chrg/codex_low_voltage_relay_verify.log b/apps/chrg/codex_low_voltage_relay_verify.log
new file mode 100644
index 0000000..7d4c47d
--- /dev/null
+++ b/apps/chrg/codex_low_voltage_relay_verify.log
@@ -0,0 +1,9 @@
+*** Using Compiler 'V6.16', folder: 'D:\keil mdk 2\ARM\ARMCLANG\Bin'
+Build target 'chrg'
+compiling chrg_sink.c...
+linking...
+Program Size: Code=147156 RO-data=15312 RW-data=9328 ZI-data=15984
+FromELF: creating hex file...
+After Build - User command #1: fromelf --bin .\build\keil\Obj\chrg.axf -o build/chrg.bin
+".\build\keil\Obj\chrg.axf" - 0 Error(s), 0 Warning(s).
+Build Time Elapsed: 00:00:02
diff --git a/apps/chrg/codex_protocol_ack_verify.log b/apps/chrg/codex_protocol_ack_verify.log
new file mode 100644
index 0000000..0b3c0f9
--- /dev/null
+++ b/apps/chrg/codex_protocol_ack_verify.log
@@ -0,0 +1,18 @@
+*** Using Compiler 'V6.16', folder: 'D:\keil mdk 2\ARM\ARMCLANG\Bin'
+Build target 'chrg'
+compiling chrg_north_pkg.c...
+compiling chrg_lcd.c...
+compiling chrg_thread.c...
+compiling chrg_south.c...
+compiling chrg_sink.c...
+compiling chrg_north.c...
+compiling chrg_source.c...
+compiling chrg_roll_nor.c...
+compiling chrg_roll_sou.c...
+compiling chrg_comm.c...
+linking...
+Program Size: Code=146988 RO-data=15312 RW-data=9328 ZI-data=15984
+FromELF: creating hex file...
+After Build - User command #1: fromelf --bin .\build\keil\Obj\chrg.axf -o build/chrg.bin
+".\build\keil\Obj\chrg.axf" - 0 Error(s), 0 Warning(s).
+Build Time Elapsed: 00:00:03
diff --git a/apps/chrg/codex_soft_resume_remove.log b/apps/chrg/codex_soft_resume_remove.log
new file mode 100644
index 0000000..5f103a7
--- /dev/null
+++ b/apps/chrg/codex_soft_resume_remove.log
@@ -0,0 +1,21 @@
+*** Using Compiler 'V6.16', folder: 'D:\keil mdk 2\ARM\ARMCLANG\Bin'
+Build target 'chrg'
+compiling chrg_rel.c...
+compiling chrg_vcom.c...
+compiling chrg_north_pkg.c...
+compiling chrg_lcd.c...
+compiling chrg_thread.c...
+compiling chrg_south.c...
+compiling chrg_eload.c...
+compiling chrg_sink.c...
+compiling chrg_north.c...
+compiling chrg_source.c...
+compiling chrg_roll_nor.c...
+compiling chrg_roll_sou.c...
+compiling chrg_comm.c...
+linking...
+Program Size: Code=146964 RO-data=15312 RW-data=9328 ZI-data=15984
+FromELF: creating hex file...
+After Build - User command #1: fromelf --bin .\build\keil\Obj\chrg.axf -o build/chrg.bin
+".\build\keil\Obj\chrg.axf" - 0 Error(s), 0 Warning(s).
+Build Time Elapsed: 00:00:02
diff --git a/apps/chrg/codex_stop_current_confirm_verify.log b/apps/chrg/codex_stop_current_confirm_verify.log
new file mode 100644
index 0000000..df56d49
--- /dev/null
+++ b/apps/chrg/codex_stop_current_confirm_verify.log
@@ -0,0 +1,21 @@
+*** Using Compiler 'V6.16', folder: 'D:\keil mdk 2\ARM\ARMCLANG\Bin'
+Build target 'chrg'
+compiling chrg_vcom.c...
+compiling chrg_thread.c...
+compiling chrg_north_pkg.c...
+compiling chrg_lcd.c...
+compiling chrg_rel.c...
+compiling chrg_eload.c...
+compiling chrg_sink.c...
+compiling chrg_south.c...
+compiling chrg_source.c...
+compiling chrg_north.c...
+compiling chrg_roll_nor.c...
+compiling chrg_roll_sou.c...
+compiling chrg_comm.c...
+linking...
+Program Size: Code=147032 RO-data=15312 RW-data=9328 ZI-data=15984
+FromELF: creating hex file...
+After Build - User command #1: fromelf --bin .\build\keil\Obj\chrg.axf -o build/chrg.bin
+".\build\keil\Obj\chrg.axf" - 0 Error(s), 0 Warning(s).
+Build Time Elapsed: 00:00:03
diff --git a/apps/chrg/codex_stop_direct_verify.log b/apps/chrg/codex_stop_direct_verify.log
new file mode 100644
index 0000000..53e6e21
--- /dev/null
+++ b/apps/chrg/codex_stop_direct_verify.log
@@ -0,0 +1,21 @@
+*** Using Compiler 'V6.16', folder: 'D:\keil mdk 2\ARM\ARMCLANG\Bin'
+Build target 'chrg'
+compiling chrg_rel.c...
+compiling chrg_north_pkg.c...
+compiling chrg_thread.c...
+compiling chrg_vcom.c...
+compiling chrg_lcd.c...
+compiling chrg_eload.c...
+compiling chrg_sink.c...
+compiling chrg_source.c...
+compiling chrg_south.c...
+compiling chrg_north.c...
+compiling chrg_roll_nor.c...
+compiling chrg_roll_sou.c...
+compiling chrg_comm.c...
+linking...
+Program Size: Code=146976 RO-data=15312 RW-data=9328 ZI-data=15984
+FromELF: creating hex file...
+After Build - User command #1: fromelf --bin .\build\keil\Obj\chrg.axf -o build/chrg.bin
+".\build\keil\Obj\chrg.axf" - 0 Error(s), 0 Warning(s).
+Build Time Elapsed: 00:00:03
diff --git a/apps/chrg/codex_stop_repeat_guard_verify.log b/apps/chrg/codex_stop_repeat_guard_verify.log
new file mode 100644
index 0000000..ccbd541
--- /dev/null
+++ b/apps/chrg/codex_stop_repeat_guard_verify.log
@@ -0,0 +1,9 @@
+*** Using Compiler 'V6.16', folder: 'D:\keil mdk 2\ARM\ARMCLANG\Bin'
+Build target 'chrg'
+compiling chrg_comm.c...
+linking...
+Program Size: Code=147096 RO-data=15312 RW-data=9328 ZI-data=15984
+FromELF: creating hex file...
+After Build - User command #1: fromelf --bin .\build\keil\Obj\chrg.axf -o build/chrg.bin
+".\build\keil\Obj\chrg.axf" - 0 Error(s), 0 Warning(s).
+Build Time Elapsed: 00:00:02
diff --git a/apps/chrg/codex_verify.log b/apps/chrg/codex_verify.log
index d874887..72d757a 100644
--- a/apps/chrg/codex_verify.log
+++ b/apps/chrg/codex_verify.log
@@ -1,11 +1,9 @@
*** Using Compiler 'V6.16', folder: 'D:\keil mdk 2\ARM\ARMCLANG\Bin'
Build target 'chrg'
-compiling chrg_eload.c...
compiling chrg_sink.c...
-compiling chrg_roll_sou.c...
linking...
-Program Size: Code=146936 RO-data=15312 RW-data=9328 ZI-data=15992
+Program Size: Code=147104 RO-data=15312 RW-data=9328 ZI-data=16000
FromELF: creating hex file...
After Build - User command #1: fromelf --bin .\build\keil\Obj\chrg.axf -o build/chrg.bin
".\build\keil\Obj\chrg.axf" - 0 Error(s), 0 Warning(s).
-Build Time Elapsed: 00:00:04
+Build Time Elapsed: 00:00:01