fix: 调整关机低电流确认帧数与相关配置

1. 修改chrg_comm.c中关机流程的注释,将5帧改为2帧
2. 更新chrg_sink.h的SINK_WORK_STOP_WAIT注释,修正低电流确认次数
3. 调整chrg_sink.c中的低电流确认计数阈值和相关注释
4. 实现多通道COM命令轮询调度逻辑,避免低编号通道独占总线
5. 优化北向量测请求的重试策略,调整CC等待超时时间
This commit is contained in:
wrh
2026-08-19 16:41:53 +08:00
parent 52c59395a8
commit de45a902fe
5 changed files with 30 additions and 9 deletions
+1 -1
View File
@@ -2436,7 +2436,7 @@ static eMBException chrg_comm_apply_sink_effect(rt_uint8_t ch,
pReal->sink.On_work = 0;
/* 组合控制或上位机重发可能在关机尚未完成时再次提交OFF。
* 此时必须保留当前停止阶段,不能重新进入STOP并清零低电流确认次数,
* 否则实际电流即使一直为0,也永远累计不到连续5帧。 */
* 否则实际电流即使一直为0,也永远累计不到连续2帧。 */
if ((old_work_mode == SINK_WORK_STOP_WAIT) ||
(old_work_mode == SINK_WORK_STOP_RELAY) ||
(old_work_mode == SINK_WORK_STOP_RELAY_WAIT)) {
+12 -4
View File
@@ -28,12 +28,13 @@
#define NORTH_RESPONSE_TIMEOUT_MS 50U // 单次北向请求等待匹配回码的总时间
#define NORTH_REQUEST_MAX_RETRIES 2U // 首次发送失败后最多重发2次,总发送次数为3次
#define NORTH_MEASURE_MAX_ATTEMPTS 1U // 0x20量测查询失败后直接留给下一轮轮询重发
#define NORTH_RETRY_INTERVAL_MS 5U // 相同请求两次发送之间的保护间隔
#define NORTH_POLL_INTERVAL_MS 10U // 一个通道事务结束后到下一通道的轮询间隔
#define SOURCE_CC_CLOSE_VALUE 0x03U // 0x17命令参数:同时断开CC1和CC2
#define SOURCE_CC_CLOSE_WAIT_MS 300U // 本轮所有CC_CLOSE应答后的共享保护时间
#define SOURCE_PROTOCOL_WAIT_MS 100U // 每通道0xD0应答后的协议生效保护时间
#define SINK_CC_WAIT_MS 200U // Sink设置目标CC应答后的非阻塞保护时间
#define SINK_CC_WAIT_MS 50U // 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)))
@@ -867,6 +868,7 @@ static int chrg_roll_nor_auto_request(rt_uint8_t idx,
rt_uint8_t request_sub = 0; // 本次请求实际使用的sub快照
rt_uint8_t next_sub = 0; // 正确回码后准备提交的候选sub
rt_uint8_t expected_cmd = 0; // 本次请求期望收到的命令码
rt_uint8_t max_attempts; // 本次请求允许的总发送次数
eIDX_ID expected_id = ID_SINK; // 本次请求发送时的角色快照
rt_uint32_t request_version = 0; // 本次请求发送时的COM配置版本
int send_ret; // 当前命令的串口发送结果
@@ -878,13 +880,19 @@ static int chrg_roll_nor_auto_request(rt_uint8_t idx,
return -1;
}
for (attempt = 0; attempt <= NORTH_REQUEST_MAX_RETRIES; attempt++) {
/* 默认保留设置命令的3次发送;首轮取得实际命令码后,0x20会改为
* 单次发送并留给下一轮轮询重试,避免量测无回码时长期占用通道。 */
max_attempts = NORTH_REQUEST_MAX_RETRIES + 1U;
for (attempt = 0; attempt < max_attempts; attempt++) {
rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
if (attempt == 0U) {
/* 首次发送固定请求状态,后续重发必须继续使用同一份请求上下文。 */
request_sub = pSW->sub;
expected_id = pSW->id;
expected_cmd = chrg_roll_nor_expected_cmd(pSW);
if (expected_cmd == SRC_CMD_GET_VOLTAGE) {
max_attempts = NORTH_MEASURE_MAX_ATTEMPTS;
}
request_version = pNOR->config_version[idx];
/* 新事务发送前清理已结束或已超时事务遗留的邮箱回码。 */
chrg_roll_nor_drain_mailbox(pTN);
@@ -956,7 +964,7 @@ static int chrg_roll_nor_auto_request(rt_uint8_t idx,
}
}
if (attempt < NORTH_REQUEST_MAX_RETRIES) {
if ((attempt + 1U) < max_attempts) {
/* 本次发送失败或等待超时,保持request_sub并准备重发同一命令。 */
rt_thread_mdelay(NORTH_RETRY_INTERVAL_MS);
}
@@ -964,7 +972,7 @@ static int chrg_roll_nor_auto_request(rt_uint8_t idx,
LOG_W("north request failed: ch=%d id=%02x cmd=%02x sub=%d attempts=%d",
idx + 1U, expected_id, expected_cmd, request_sub,
NORTH_REQUEST_MAX_RETRIES + 1U);
max_attempts);
return -1;
}
+14 -1
View File
@@ -35,6 +35,11 @@ chrg_rollsou_com_t g_sou_com_batch = {0};
static rt_uint8_t g_sou_measure_once_pending_mask = 0U;
static rt_uint8_t g_sou_measure_once_active_mask = 0U;
/* COM批量命令按通道轮询发送。一次写命令收到匹配回码后才移动游标;
* 回码错误或超时时游标保持不变,使同一条命令优先完成重发,避免破坏
* 本通道批次内的寄存器执行顺序。 */
static rt_uint8_t g_sou_com_batch_rr_next_ch = 0U;
struct chrg_rollsou_t chrgrollsou = {
.run = RUN_AUTO,
.ch = IDX_SOU_CH1,
@@ -516,6 +521,7 @@ static int sou_com_batch_next(rt_uint8_t *ch, rt_uint16_t *reg, rt_uint16_t *val
rt_bool_t pending_wait = RT_FALSE;
rt_tick_t now;
rt_uint8_t idx;
rt_uint8_t offset;
if ((RT_NULL == pTHR->mutex) ||
(rt_mutex_take(pTHR->mutex, rt_tick_from_millisecond(SOU_MUTEX_TIMEOUT_MS)) != RT_EOK)) {
@@ -523,7 +529,11 @@ static int sou_com_batch_next(rt_uint8_t *ch, rt_uint16_t *reg, rt_uint16_t *val
}
now = rt_tick_get();
for (idx = 0; idx < TOTAL_SOU_CHS; idx++) {
/* 从上一次成功命令的下一个通道开始查找,使多通道批次按
* "CH1一条 -> CH2一条 -> ..." 交替执行,而不是低编号通道独占总线。 */
for (offset = 0; offset < TOTAL_SOU_CHS; offset++) {
idx = (rt_uint8_t)((g_sou_com_batch_rr_next_ch + offset) %
TOTAL_SOU_CHS);
sou_com_batch_ch_t *pBatch = &g_sou_com_batch.ch[idx];
if (pBatch->pending != RT_TRUE) {
continue;
@@ -577,6 +587,9 @@ static int sou_com_batch_complete(rt_uint8_t ch, rt_uint16_t reg, rt_uint16_t va
}
pBatch->cur_idx++;
/* 当前寄存器已收到匹配写回码。下一次调度从下一个通道开始;
* 当前通道的下一条命令会在其它就绪通道各执行一条后继续发送。 */
g_sou_com_batch_rr_next_ch = (rt_uint8_t)((ch + 1U) % TOTAL_SOU_CHS);
/* 暂时关闭副继电器与主继电器之间的固定延时;需要恢复时重新启用本段。 */
if ((reg == REG_REL_ON) && (value == ALL_REL_OFF) &&
(pBatch->cur_idx < pBatch->reg_cnt) &&
+2 -2
View File
@@ -22,7 +22,7 @@
#define SINK_UNLOAD_QUERY_INTERVAL_MS 20U // 卸载期间两次优先量测请求的最小间隔
#define SINK_UNLOAD_CURRENT_MAX_MA 200U // 判定负载已安全卸载的最大实际电流
#define SINK_UNLOAD_CONFIRM_COUNT 5U // 连续满足低电流条件的量测帧数
#define SINK_UNLOAD_CONFIRM_COUNT 2U // 连续满足低电流条件的量测帧数
/* 主继电器闭合跟踪:1=已提交ALL_REL_ON(主继电器应已闭合) 0=未闭合/已断开。
* 用于0V硬保护区分"首次开载/握手恢复"(主继电器未闭合,Now_voltage=0属正常)
@@ -687,7 +687,7 @@ static int chrg_sink_work_handshake_prepare(eIDX_SOU_CH idx,
return -1;
}
/* 协议或CC切换先停止电子负载,连续5次确认低电流后再操作继电器。 */
/* 协议或CC切换先停止电子负载,连续2次确认低电流后再操作继电器。 */
chrg_sink_unload_confirm_reset(idx);
pSW->sink.work_mode = SINK_WORK_HANDSHAKE_WAIT;
return 0;
+1 -1
View File
@@ -232,7 +232,7 @@ enum {
SINK_WORK_LOAD_STANDBY, // 协议已就绪但主继电器未打开,低设定电流下保持停止
SINK_WORK_LOAD_STOP, // 运行中跨到低电流:只发送WORK_STOP关闭电子负载
SINK_WORK_LOAD_START, // 主继电器未打开的低电流待机恢复:等待北向电压稳定后进入RUNING
SINK_WORK_STOP_WAIT, // 关机:等待连续5次实际电流达到安全范围
SINK_WORK_STOP_WAIT, // 关机:等待连续2次实际电流达到安全范围
SINK_WORK_STOP_RELAY, // 关机:低电流确认后提交关闭南向继电器
SINK_WORK_STOP_RELAY_WAIT // 关机:等待关闭南向继电器的回码
};