diff --git a/apps/chrg/applications/thread/chrg_comm.c b/apps/chrg/applications/thread/chrg_comm.c index c9fff7d..759c562 100644 --- a/apps/chrg/applications/thread/chrg_comm.c +++ b/apps/chrg/applications/thread/chrg_comm.c @@ -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)) { diff --git a/apps/chrg/applications/thread/chrg_roll_nor.c b/apps/chrg/applications/thread/chrg_roll_nor.c index 020c691..4e14190 100644 --- a/apps/chrg/applications/thread/chrg_roll_nor.c +++ b/apps/chrg/applications/thread/chrg_roll_nor.c @@ -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; } diff --git a/apps/chrg/applications/thread/chrg_roll_sou.c b/apps/chrg/applications/thread/chrg_roll_sou.c index 2b0d540..ad9d2a8 100644 --- a/apps/chrg/applications/thread/chrg_roll_sou.c +++ b/apps/chrg/applications/thread/chrg_roll_sou.c @@ -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) && diff --git a/apps/chrg/applications/utils/chrg_sink.c b/apps/chrg/applications/utils/chrg_sink.c index 7641b1f..97361d3 100644 --- a/apps/chrg/applications/utils/chrg_sink.c +++ b/apps/chrg/applications/utils/chrg_sink.c @@ -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; diff --git a/apps/chrg/applications/utils/chrg_sink.h b/apps/chrg/applications/utils/chrg_sink.h index 97b544e..ecce436 100644 --- a/apps/chrg/applications/utils/chrg_sink.h +++ b/apps/chrg/applications/utils/chrg_sink.h @@ -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 // 关机:等待关闭南向继电器的回码 };