chore: 更新修改日志到V1.1.7并完成低电流待机与并行握手优化

1. 关闭南向寄存器写命令调试日志
2. 新增SINK_LOAD_ENABLE_MIN_MA宏限制最低带载电流为100mA
3. 新增SINK_WORK_LOAD_STANDBY等4种低电流待机工作状态
4. 重构协议电压/电流变化处理逻辑,改为软卸载不切继电器
5. 实现南北向握手并行执行,降低0x20查询频率
6. 新增chrg_sink_load_should_start和chrg_sink_handshake_north_ready接口
7. 优化RUNING状态命令顺序,避免主继电器重复断开
8. 更新编译日志,修正代码尺寸数据
This commit is contained in:
wrh
2026-08-08 20:09:18 +08:00
parent b96902f9b9
commit 8b7f29d0fc
8 changed files with 676 additions and 158 deletions
+98 -10
View File
@@ -100,6 +100,9 @@ static void chrg_mb_write_src(rt_uint8_t ch, rt_uint16_t reg_offset, rt_uint16_t
static eMBException chrg_mb_write_sys(rt_uint8_t ch, rt_uint16_t reg_offset, rt_uint16_t sou_value, struct chrg_switch_t *pSW, struct chrg_north_t *pNOR, struct chrg_south_t *pSOU);
static int chrg_sink_diff_send_reg(eIDX_SOU_CH ch,
const chrg_param_diff_t *pDiff, struct chrg_switch_t *pReal);
static rt_bool_t chrg_comm_handle_sink_load_current(
const chrg_param_diff_t *pDiff, rt_uint8_t old_work_mode,
struct chrg_switch_t *pReal);
/*! \brief Function to set bits in a byte buffer.
*
@@ -2338,23 +2341,31 @@ static eMBException chrg_comm_apply_sink_effect(rt_uint8_t ch,
{
rt_bool_t full_handshake_change;
rt_bool_t protocol_voltage_only;
rt_bool_t protocol_current_change;
rt_bool_t protocol_data_changed;
rt_uint8_t curr_test;
rt_uint8_t curr_test_old;
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_work_mode = pReal->sink.work_mode;
rt_uint16_t sink_work = pShadow->sink.Now_State;
chrg_param_diff_t diff_info;
chrg_comm_get_param_diff(ID_SINK, pReal, pShadow, &diff_info);
/*
* 协议类型、CC、协议组号或协议电流变化都按完整重握手处理。
* 只有单独修改协议电压时才允许仅掉载而不切换南向继电器。
* 协议类型、CC和协议组号变化需要完整握手;协议电压和协议电流
* 变化只需要软卸载后重发协议,不关闭南向继电器。
*/
full_handshake_change = diff_info.protocol_changed || diff_info.cc_changed ||
diff_info.group_changed || diff_info.pro_current_changed;
protocol_voltage_only = diff_info.pro_voltage_changed &&
diff_info.group_changed;
protocol_data_changed = diff_info.protocol_changed ||
diff_info.group_changed || diff_info.pro_voltage_changed ||
diff_info.pro_current_changed;
protocol_current_change = diff_info.pro_current_changed &&
!full_handshake_change;
protocol_voltage_only = diff_info.pro_voltage_changed &&
!full_handshake_change && !protocol_current_change;
rt_memcpy(pReal, pShadow, sizeof(struct chrg_switch_t));
if (sink_work == 0x01) {
@@ -2380,14 +2391,38 @@ static eMBException chrg_comm_apply_sink_effect(rt_uint8_t ch,
pReal->sub = IDX_SET_SINK_PD;
pReal->sink.work_mode = SINK_WORK_INIT;
} else if (full_handshake_change) {
/* 协议类型或CC变化需要重发协议和CC;仅组号/协议电流变化只重发协议。 */
pReal->sub = (diff_info.protocol_changed || diff_info.cc_changed) ?
IDX_SET_SINK_PD : IDX_SET_SINK_PD_ONLY;
pReal->sink.work_mode = SINK_WORK_HANDSHAKE_PREPARE;
} else if (protocol_voltage_only) {
/* 仅协议电压变化时保持主副继电器状态,只停止负载并清零电流。 */
/*
* 只有CC实际变化时才发送目标CC命令并等待;协议类型或组号
* 单独变化时直接重发PD帧,不重复设置未变化的CC。
* 协议与CC同时变化时先发送协议,协议应答后再设置目标CC;
* 仅协议变化时不重复设置未变化的CC。
*/
if (diff_info.cc_changed && protocol_data_changed) {
pReal->sub = IDX_SET_SINK_PD;
} else if (diff_info.cc_changed) {
pReal->sub = IDX_SET_SINK_CCLINE;
} else {
pReal->sub = IDX_SET_SINK_PD_ONLY;
}
pReal->sink.work_mode = SINK_WORK_HANDSHAKE_PREPARE;
} else if (protocol_voltage_only || protocol_current_change) {
/*
* 协议电压、协议电流变化都只执行软卸载,不关闭南向继电器。
* 低电流待机本身已经WORK_STOP,无需重复提交卸载命令;运行中
* 则等待实际电流降到安全范围后再重发协议。
*/
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;
}
} else if (chrg_comm_handle_sink_load_current(&diff_info,
old_work_mode, pReal)) {
/* 电流跨门限的停止或恢复已转换为独立Sink状态,由统一入口下发。 */
} else if (chrg_sink_diff_send_reg((eIDX_SOU_CH)ch,
&diff_info, pReal) != 0) {
pReal->CV_mode = old_cv_mode;
@@ -2404,6 +2439,59 @@ static eMBException chrg_comm_apply_sink_effect(rt_uint8_t ch,
MB_EX_NONE : MB_EX_SLAVE_BUSY;
}
/*****************************************************************
函数名称: chrg_comm_handle_sink_load_current
函数描述: 处理普通负载电流跨越最低带载门限时的状态转换
输入参数: pDiff:本次参数差异 old_work_mode:生效前工作状态
pReal:已复制新参数的运行结构体
输出参数: 必要时更新sink.work_mode
返回说明: RT_TRUE:本次电流变化已处理,禁止再直接写电流寄存器
RT_FALSE:未跨门限,继续执行普通差异下发
其它说明: 北向协议、CC和协议电流变化在调用本函数前处理;本函数只管理
南向电子负载的WORK_STOP/CURRENT=0及无握手快速恢复
*****************************************************************/
static rt_bool_t chrg_comm_handle_sink_load_current(
const chrg_param_diff_t *pDiff, rt_uint8_t old_work_mode,
struct chrg_switch_t *pReal)
{
rt_bool_t should_start;
if ((pDiff == RT_NULL) || (pReal == RT_NULL) ||
!pDiff->current_changed ||
(pReal->CV_mode != MODE_CONSTANT_CURRENT)) {
return RT_FALSE;
}
should_start = chrg_sink_load_should_start(pReal);
if ((old_work_mode == SINK_WORK_RUNING) ||
(old_work_mode == SINK_WORK_SOFT_RUNNING)) {
if (!should_start) {
pReal->sink.work_mode = SINK_WORK_LOAD_STOP;
return RT_TRUE;
}
return RT_FALSE;
}
if (old_work_mode == SINK_WORK_LOAD_STANDBY) {
if (should_start) {
/* 独立入口可避开RUNING相同状态去重,并执行完整继电器启动。 */
pReal->sink.work_mode = SINK_WORK_LOAD_START;
}
return RT_TRUE;
}
if (old_work_mode == SINK_WORK_LOAD_SOFT_STANDBY) {
if (should_start) {
/* 继电器和协议保持不变,只恢复目标电流和WORK_START。 */
pReal->sink.work_mode = SINK_WORK_LOAD_RESUME;
}
return RT_TRUE;
}
/* 协议握手期间禁止把低于门限的小电流提前写入南向功率板。 */
return should_start ? RT_FALSE : RT_TRUE;
}
/*****************************************************************
函数名称: chrg_comm_apply_source_effect
函数描述: 处理COM参数生效后的同角色电源启停和参数差异更新
+14 -7
View File
@@ -29,7 +29,7 @@
#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_CONFIRM_COUNT 2U // Sink进入RUNING前连续稳定电压帧数
#define SINK_VOLT_STABLE_CONFIRM_COUNT 0U // Sink一帧有效稳定电压即进入RUNING
/*****************************************************************
函数名称: chrg_source_apply_protocol_voltage_rule
@@ -193,7 +193,7 @@ void chrg_source_setting(rt_uint8_t *frame_data, eIDX_SOU_CH idx,
输出参数: 更新VZ、VF、低压计数、稳定电压计数、无电流计数及sink.work_mode
返回说明: -
其它说明: 电压连续低于门槛进入LOW;掉电处理恢复副继电器后,电压重新
出现时先重设协议和CC;连续两次达到目标附近才进入RUNING
出现时先重设协议和CC;一帧有效电压达到目标附近即进入RUNING
*****************************************************************/
void chrg_sink_parse(rt_uint8_t *frame_data, eIDX_SOU_CH idx,
struct chrg_switch_t *pSW, struct chrg_north_t *pNOR)
@@ -220,7 +220,7 @@ 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] >= 2) {
if (++volt_low[idx] >= 100) {
volt_set_ok[idx] = 0;
no_curr[idx] = 0;
pSW->sink.work_mode = SINK_WORK_LOW;
@@ -245,13 +245,15 @@ void chrg_sink_parse(rt_uint8_t *frame_data, eIDX_SOU_CH idx,
no_curr[idx] = 0;
} else if ((rt_uint32_t)volt_mv + 2000 >= 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_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) {
volt_stable_count[idx]++;
}
if (volt_stable_count[idx] >= SINK_VOLT_STABLE_CONFIRM_COUNT) {
/* 连续两次北向量测均达到目标电压附近后才允许带载,避免
* 单次瞬态电压或旧回码导致负载提前进入RUNING。 */
/* 回码已经过CRC、ID、命令和配置版本校验;首帧达到目标
* 电压附近后立即进入RUNING,不再增加额外稳定等待。 */
volt_stable_count[idx] = 0;
pSW->sink.work_mode =
(pSW->sink.work_mode == SINK_WORK_SOFT_RESUME_WAIT) ?
@@ -259,8 +261,13 @@ void chrg_sink_parse(rt_uint8_t *frame_data, eIDX_SOU_CH idx,
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)) {
/* 协议保持在线但电子负载主动停止,不执行无电流重试。 */
volt_stable_count[idx] = 0;
no_curr[idx] = 0;
} else if ((pSW->Now_current > 200) ||
(pSW->sink.pro_loadc < 200)) {
(pSW->sink.loadc < 200)) {
volt_stable_count[idx] = 0;
no_curr[idx] = 0;
} else if ((rt_tick_t)(rt_tick_get() - running_start_tick[idx]) >=
+1 -1
View File
@@ -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 0x01 // 南向寄存器写命令
#define SOUTH_COMMAND_DEBUG 0x00 // 南向寄存器写命令
#define COMM_FRAME_DEBUG 0x00 // COM UART原始收发帧
#define COMM_DEBUG 0x00 // COM寄存器读写过程
#define COMM_TRIM_DEBUG 0x00 // COM校准参数解析
+109 -15
View File
@@ -33,7 +33,9 @@
#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_STABLE_WAIT_MS 50U // Sink设置目标CC应答后的非阻塞稳定时间
#define SINK_CC_WAIT_MS 200U // 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)))
const rt_base_t sw_uart[TOTAL_NOR_CHS] = {
IDX_GPO_UART_SW1,
@@ -58,6 +60,49 @@ static rt_uint8_t g_source_protocol_wait_mask = 0U;
static rt_tick_t g_source_protocol_wait_start[TOTAL_NOR_CHS] = {0};
static rt_uint8_t g_sink_cc_wait_mask = 0U;
static rt_tick_t g_sink_cc_wait_start[TOTAL_NOR_CHS] = {0};
/* 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};
static rt_tick_t g_sink_query_tick[TOTAL_NOR_CHS] = {0};
/*****************************************************************
函数名称: chrg_roll_nor_sink_query_is_slow
函数描述: 判断当前Sink状态是否仍处于协议握手量测阶段
输入参数: pSW:当前负载通道控制结构体
输出参数: -
返回说明: RT_TRUE:0x20查询按握手节奏发送 RT_FALSE:使用正常轮询周期
其它说明: 只有协议/CC设置后等待协商电压的阶段限速;RUNING和低电流
待机不受影响,避免影响正常量测刷新速度
*****************************************************************/
static rt_bool_t chrg_roll_nor_sink_query_is_slow(
const struct chrg_switch_t *pSW)
{
if (pSW == RT_NULL) {
return RT_FALSE;
}
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);
}
/*****************************************************************
函数名称: chrg_roll_nor_sink_query_wait_start
函数描述: 启动Sink握手阶段的0x20查询节流计时
输入参数: ch:北向通道编号
输出参数: 记录当前tick并开启节流
返回说明: -
其它说明: 协议或CC回码成功后调用,避免下一轮立即查询协议板
*****************************************************************/
static void chrg_roll_nor_sink_query_wait_start(rt_uint8_t ch)
{
if (ch >= TOTAL_NOR_CHS) {
return;
}
g_sink_query_throttle[ch] = RT_TRUE;
g_sink_query_first_pending[ch] = RT_TRUE;
g_sink_query_tick[ch] = rt_tick_get();
}
/*****************************************************************
函数名称: chrg_roll_nor_source_switch_reset
@@ -220,12 +265,12 @@ static void chrg_roll_nor_sink_cc_wait_start(rt_uint8_t ch)
/*****************************************************************
函数名称: chrg_roll_nor_sink_wait_process
函数描述: 管理Sink副继电器确认、安全卸载和CC设置后的稳定等待
函数描述: 管理Sink安全卸载、南北并行握手和CC设置后的稳定等待
输入参数: ch:北向通道编号 pSW:通道实时控制结构体
输出参数: 南向卸载完成后允许发送协议;CC稳定时间到达后切换为电压查询
输出参数: 南向批次完成后允许协议/CC;低电流和CC均满足后允许查询
返回说明: RT_TRUE:本轮仍需等待,不发送北向命令 RT_FALSE:可继续发送
其它说明: INIT只等待第一条FU_REL_ON完成;其余初始化命令入队后与北向
握手并行。软卸载和完整重握手仍必须完成低电流确认后才放行
其它说明: 完整重握手中,南向批次完成后协议/CC与低电流确认并行;
进入GET_SINK_VC后,必须等低电流确认完成才允许发送0x20
*****************************************************************/
static rt_bool_t chrg_roll_nor_sink_wait_process(rt_uint8_t ch,
struct chrg_switch_t *pSW)
@@ -241,35 +286,80 @@ static rt_bool_t chrg_roll_nor_sink_wait_process(rt_uint8_t ch,
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;
g_sink_query_throttle[ch] = RT_FALSE;
g_sink_query_first_pending[ch] = RT_FALSE;
g_sink_query_tick[ch] = 0U;
return RT_FALSE;
}
/* 副继电器或安全卸载尚未确认时,禁止任何北向设置和电压查询。 */
if ((pSW->sink.work_mode == SINK_WORK_INIT_AUX_WAIT) ||
(pSW->sink.work_mode == SINK_WORK_UNLOAD_WAIT) ||
(pSW->sink.work_mode == SINK_WORK_LOW_AUX_WAIT) ||
(pSW->sink.work_mode == SINK_WORK_HANDSHAKE_WAIT)) {
/* 普通软卸载和低电流恢复仍禁止北向;INIT_AUX_WAIT允许南北向并行。 */
if ((pSW->sink.work_mode == SINK_WORK_UNLOAD_WAIT) ||
(pSW->sink.work_mode == SINK_WORK_LOW_AUX_WAIT)) {
return RT_TRUE;
}
/*
* 完整握手批次最后发送FU_REL_ON。批次完成并建立量测基线后,
* 允许北向协议/CC与南向低电流确认并行;当sub进入GET_SINK_VC
* 而状态仍为HANDSHAKE_WAIT时,说明低电流确认尚未完成,禁止发送0x20。
*/
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;
}
}
if (pSW->sub != IDX_WAIT_SINK_CC) {
/* COM在等待期间提交新配置时,清理旧事务留下的CC计时记录。 */
g_sink_cc_wait_mask &= (rt_uint8_t)~bit;
g_sink_cc_wait_start[ch] = 0U;
return RT_FALSE;
if (!chrg_roll_nor_sink_query_is_slow(pSW)) {
g_sink_query_throttle[ch] = RT_FALSE;
g_sink_query_first_pending[ch] = RT_FALSE;
g_sink_query_tick[ch] = 0U;
}
} else {
if ((g_sink_cc_wait_mask & bit) == 0U) {
pSW->sub = IDX_GET_SINK_VC;
return RT_FALSE;
chrg_roll_nor_sink_query_wait_start(ch);
return RT_TRUE;
}
elapsed = (rt_tick_t)(rt_tick_get() - g_sink_cc_wait_start[ch]);
if (elapsed < rt_tick_from_millisecond(SINK_CC_STABLE_WAIT_MS)) {
if (elapsed < rt_tick_from_millisecond(SINK_CC_WAIT_MS)) {
return RT_TRUE;
}
/* 协议已先设置;CC应答并完成保护等待后进入电压查询。 */
g_sink_query_throttle[ch] = RT_TRUE;
g_sink_query_first_pending[ch] = RT_TRUE;
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;
pSW->sub = IDX_GET_SINK_VC;
return RT_TRUE;
}
/* 首条0x20等待200ms;握手未稳定时,后续查询间隔缩短为100ms。 */
if (chrg_roll_nor_sink_query_is_slow(pSW) &&
(pSW->sub == IDX_GET_SINK_VC)) {
rt_uint32_t query_interval_ms;
if (!g_sink_query_throttle[ch]) {
chrg_roll_nor_sink_query_wait_start(ch);
return RT_TRUE;
}
query_interval_ms = g_sink_query_first_pending[ch] ?
SINK_HANDSHAKE_FIRST_QUERY_DELAY_MS :
SINK_HANDSHAKE_QUERY_INTERVAL_MS;
elapsed = (rt_tick_t)(rt_tick_get() - g_sink_query_tick[ch]);
if (elapsed < rt_tick_from_millisecond(query_interval_ms)) {
return RT_TRUE;
}
g_sink_query_first_pending[ch] = RT_FALSE;
g_sink_query_tick[ch] = rt_tick_get();
}
return RT_FALSE;
}
/*****************************************************************
@@ -665,7 +755,7 @@ static int chrg_roll_nor_cmd (struct chrg_rollnor_t *pROLL)
返回说明: >0:发送长度 <0:发送失败或状态不支持
其它说明: Source按差异执行协议、CC或组合命令;涉及PD的运行中切换先发送CC_CLOSE;
停止状态启动和主动停止均不额外发送CC_CLOSE;
Sink依次执行协议设置、目标CC线选择、稳定等待和VC查询
Sink完整握手依次执行协议设置、目标CC线选择、稳定等待和VC查询
*****************************************************************/
static int chrg_roll_nor_set(rt_uint8_t ch, struct chrg_switch_t *pSW,
rt_uint8_t *next_sub)
@@ -815,6 +905,10 @@ static int chrg_roll_nor_auto_request(rt_uint8_t idx,
(request_sub == IDX_SET_SINK_CCLINE)) {
/* 北向Sink继电器保持接通,仅等待目标CC配置稳定。 */
chrg_roll_nor_sink_cc_wait_start(idx);
} else if ((expected_id == ID_SINK) &&
(request_sub == IDX_SET_SINK_PD_ONLY)) {
/* 仅重发协议时没有CC回码作为节流入口,直接启动200ms计时。 */
chrg_roll_nor_sink_query_wait_start(idx);
}
/* 业务解析可能主动切换sub,例如掉电恢复后要求重新设置协议。
* 只有sub仍属于本次请求时,才应用请求函数计算出的next_sub。 */
+266 -103
View File
@@ -30,6 +30,27 @@ static rt_bool_t g_sink_unload_batch_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};
/*****************************************************************
函数名称: chrg_sink_load_should_start
函数描述: 判断普通负载的设定值是否允许启动南向电子负载
输入参数: pSW:当前通道控制结构体
输出参数: -
返回说明: RT_TRUE:允许WORK_START RT_FALSE:应保持WORK_STOP
其它说明: 门限只作用于恒流模式的负载电流loadc;协议电流pro_loadc无论
大小都继续参与北向握手,恒压模式不受该恒流门限限制
*****************************************************************/
rt_bool_t chrg_sink_load_should_start(const struct chrg_switch_t *pSW)
{
if (pSW == RT_NULL) {
return RT_FALSE;
}
if (pSW->CV_mode != MODE_CONSTANT_CURRENT) {
return RT_TRUE;
}
return (pSW->sink.loadc >= SINK_LOAD_ENABLE_MIN_MA) ?
RT_TRUE : RT_FALSE;
}
/*****************************************************************
函数名称: chrg_sink_unload_confirm_reset
函数描述: 清除指定通道的卸载批次和低电流确认上下文
@@ -49,6 +70,24 @@ static void chrg_sink_unload_confirm_reset(eIDX_SOU_CH idx)
g_sink_unload_confirm_count[idx] = 0U;
}
/*****************************************************************
函数名称: chrg_sink_handshake_north_ready
函数描述: 判断完整握手的南向安全批次是否已经执行完成
输入参数: idx:南向功率板通道
输出参数: -
返回说明: RT_TRUE:辅助继电器命令已完成并已建立低电流量测基线
RT_FALSE:南向安全批次仍在执行
其它说明: 基线建立后返回成功,实际低电流确认仍由当前状态函数继续执行;
用于允许北向协议/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_batch_confirmed[idx];
}
/*****************************************************************
函数名称: chrg_sink_unload_query_submit
函数描述: 按最小间隔提交当前通道的一次性P1量测请求
@@ -188,66 +227,30 @@ int sink_set_pd (rt_uint8_t pd, rt_uint8_t *buf)
/*****************************************************************
函数名称: chrg_sink_work_init
函数描述: 执行负载INIT入口,第一条南向命令只打开副继电器
函数描述: 执行负载INIT入口,将副继电器和初始化命令按顺序提交南向
输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体
输出参数: 禁止北向请求并进入SINK_WORK_INIT_AUX_WAIT
返回说明: 0:副继电器命令提交成功 <0:参数或命令提交失败
其它说明: FU_REL_ON同时保证主继电器关闭;收到有效回码前不得启动北向握手
输出参数: 立即打开北向Sink继电器和enable,并进入INIT_AUX_WAIT后台确认
返回说明: 0:初始化批次提交成功 <0:参数或命令提交失败
其它说明: 南向顺序为FU_REL_ON、CURRENT=0、MODE、VON和可选测试停止;
北向协议握手不等待南向回码,南北向从批次入队后并行执行
*****************************************************************/
static int chrg_sink_work_init(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
{
struct chrg_north_t *pNOR = &chrgnorth;
rt_uint16_t reg = REG_REL_ON;
rt_uint16_t value = FU_REL_ON;
rt_uint16_t regs[5] = {REG_REL_ON, REG_CURRENT_OUT + 1,
REG_MODE, Eload_Start_V_ON, 0};
rt_uint16_t vals[5] = {FU_REL_ON, 0, 0, 0, 0};
rt_bool_t first_start;
rt_uint8_t count = 4U;
if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
return -1;
}
if (chrg_sou_com_batch_submit(idx, &reg, &value, 1U) != 0) {
return -1;
}
/* 北向软件使能在副继电器回码后恢复,避免协议命令先于电压通路。 */
pSW->sink.On_work = 1;
pNOR->enable[idx] = 0;
pSW->sink.work_mode = SINK_WORK_INIT_AUX_WAIT;
return 0;
}
/*****************************************************************
函数名称: chrg_sink_work_init_aux_wait
函数描述: 等待启动副继电器回码,并异步提交其余功率板初始化命令
输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体
输出参数: 打开北向Sink继电器、恢复北向使能并进入SINK_WORK_WAIT
返回说明: 0:继续等待或初始化命令已入队 <0:参数或命令提交失败
其它说明: 其余初始化命令只要求成功入队,不等待执行完成;北向握手和
南向初始化可并行,后续RUNING命令追加到同一队列并保持顺序
*****************************************************************/
static int chrg_sink_work_init_aux_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[4] = {REG_CURRENT_OUT + 1, REG_MODE,
Eload_Start_V_ON, 0};
rt_uint16_t vals[4] = {0};
rt_uint8_t count = 3U;
int batch_result;
if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
return -1;
}
vals[1] = pSW->CV_mode;
vals[2] = pSW->sink.volt_on;
if (chrg_sou_com_batch_is_pending(idx)) {
return 0;
}
batch_result = chrg_sou_com_batch_get_result(idx);
if (batch_result <= 0) {
/* 副继电器无有效回码时重新执行INIT,北向继续保持禁止。 */
return chrg_sink_work_init(idx, pSW);
}
/* COM进入INIT前已经设置On_work,使用原工作状态区分首次提交和后台重试。 */
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;
if (pSW->sink.test.test_mode_old == SINK_TEST_SHORT) {
regs[count] = ModbusRTU_ShortTest_CMD_MODE_FLAG;
vals[count++] = ModbusRTU_DYNA_CMD_MODE_STOP;
@@ -262,11 +265,45 @@ static int chrg_sink_work_init_aux_wait(eIDX_SOU_CH idx,
return -1;
}
/* 初始化命令已按顺序入队,此时即可给协议板接通北向Sink路径。 */
pSOU->online[idx] = 1;
pNOR->enable[idx] = 1;
pSW->sink.On_work = 1;
if (first_start) {
/* 南向批次已入队,北向按“协议->CC”顺序立即开始完整握手。 */
chrg_nor_sw_rel((eIDX_NOR_CH)idx, ID_SINK);
pNOR->enable[idx] = 1;
pSW->sub = IDX_SET_SINK_PD;
}
pSW->sink.work_mode = SINK_WORK_INIT_AUX_WAIT;
return 0;
}
/*****************************************************************
函数名称: chrg_sink_work_init_aux_wait
函数描述: 后台等待整组南向初始化命令完成,不阻塞北向协议握手
输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体
输出参数: 初始化完成后进入SINK_WORK_WAIT,失败时重提整个初始化批次
返回说明: 0:继续等待或初始化完成 <0:参数错误
其它说明: 重试时保留当前北向sub,禁止把正在执行的协议/CC事务拉回起点
*****************************************************************/
static int chrg_sink_work_init_aux_wait(eIDX_SOU_CH idx,
struct chrg_switch_t *pSW)
{
struct chrg_south_t *pSOU = &chrgsouth;
int batch_result;
if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
return -1;
}
if (chrg_sou_com_batch_is_pending(idx)) {
return 0;
}
batch_result = chrg_sou_com_batch_get_result(idx);
if (batch_result <= 0) {
/* 北向保持当前事务,南向独立重试完整初始化批次。 */
return chrg_sink_work_init(idx, pSW);
}
/* 北向可能已推进到CC或电压查询,此处只更新南向完成状态。 */
pSOU->online[idx] = 1;
pSW->sink.test.test_mode_old = 0;
pSW->sink.work_mode = SINK_WORK_WAIT;
return 0;
@@ -274,60 +311,173 @@ static int chrg_sink_work_init_aux_wait(eIDX_SOU_CH idx,
/*****************************************************************
函数名称: chrg_sink_work_volt_runing
函数描述: 执行负载RUNING状态,闭合功率继电器并启动负载
函数描述: 执行负载RUNING状态,闭合全部继电器并启动负载
输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体
输出参数: -
返回说明: 0:命令提交成功 非0:命令提交失败
其它说明: CV模式下写负载电压,其他模式下写负载电流;副继电器0x02
收到有效回码后直接发送全部继电器0x03,当前不增加固定延时
其它说明: 辅助继电器已在INIT、重握手或掉电恢复阶段打开;RUNING只发送
ALL_REL_ON、目标负载值和WORK_START,避免FU_REL_ON重复关闭主继电器
*****************************************************************/
static int chrg_sink_work_volt_runing(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
{
rt_uint16_t regs[4] = {0x01, 0x01, 0, REG_WORK};
rt_uint16_t vals[4] = {0x02, 0x03, 0, WORK_START};
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;
}
return chrg_sou_com_batch_submit(idx, regs, vals, 4);
}
/*****************************************************************
函数名称: chrg_sink_work_soft_resume
函数描述: 仅协议电压变化完成后恢复负载,不操作南向主副继电器
输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体
输出参数: 命令入队成功后将工作状态切换为SINK_WORK_SOFT_RUNNING
返回说明: 0:命令提交成功 <0:参数或命令提交失败
其它说明: 命令顺序为目标电流/电压、WORK_START,保证软卸载期间继电器
始终保持原状态,避免恢复阶段因FU_REL_ON造成主继电器短暂断开
*****************************************************************/
static int chrg_sink_work_soft_resume(eIDX_SOU_CH idx,
struct chrg_switch_t *pSW)
{
rt_uint16_t regs[2] = {0, REG_WORK};
rt_uint16_t vals[2] = {0, WORK_START};
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 (pSW->CV_mode == MODE_CONSTANT_VOLTAGE) {
regs[0] = REG_VOLTAGE_OUT + 1;
vals[0] = pSW->sink.loadv;
} else {
regs[0] = REG_CURRENT_OUT + 1;
vals[0] = pSW->sink.loadc;
if (!chrg_sink_load_should_start(pSW)) {
/*
* 北向协议已完成,低电流设定仍需要接通主继电器,使负载通路
* 处于完整连接状态;但禁止电子负载带载,随后发送WORK_STOP并
* 清零电流,避免0A或几十mA设定造成启动冲击。
*/
rt_uint16_t stop_regs[3] = {REG_REL_ON, REG_WORK,
REG_CURRENT_OUT + 1};
rt_uint16_t stop_vals[3] = {ALL_REL_ON, WORK_STOP, 0};
ret = chrg_sou_com_batch_submit(idx, stop_regs, stop_vals, 3U);
if (ret == 0) {
pSW->sink.work_mode = SINK_WORK_LOAD_STANDBY;
}
if (chrg_sou_com_batch_submit(idx, regs, vals, 2U) != 0) {
return ret;
}
if (pSW->CV_mode == MODE_CONSTANT_VOLTAGE) {
regs[1] = REG_VOLTAGE_OUT + 1;
vals[1] = pSW->sink.loadv;
} else {
regs[1] = REG_CURRENT_OUT + 1;
vals[1] = pSW->sink.loadc;
}
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;
regs[1] = REG_CURRENT_OUT + 1;
vals[1] = 0;
ret = chrg_sou_com_batch_submit(idx, regs, vals, 2U);
if (ret == 0) {
pSW->sink.work_mode = SINK_WORK_LOAD_SOFT_STANDBY;
}
return ret;
}
if (pSW->CV_mode == MODE_CONSTANT_VOLTAGE) {
regs[1] = REG_VOLTAGE_OUT + 1;
vals[1] = pSW->sink.loadv;
} else {
regs[1] = REG_CURRENT_OUT + 1;
vals[1] = pSW->sink.loadc;
}
if (chrg_sou_com_batch_submit(idx, regs, vals, 3U) != 0) {
return -1;
}
pSW->sink.work_mode = SINK_WORK_SOFT_RUNNING;
return 0;
}
/*****************************************************************
函数名称: chrg_sink_work_load_stop
函数描述: 普通负载运行中设定电流降到最低门限以下时安全停止带载
输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体
输出参数: 命令入队成功后进入SINK_WORK_LOAD_SOFT_STANDBY
返回说明: 0:命令提交成功 <0:参数或命令提交失败
其它说明: 命令顺序固定为WORK_STOP、CURRENT=0;不改变北向协议、CC和
主副继电器,保证后续恢复有效电流时无需重新协议握手
*****************************************************************/
static int chrg_sink_work_load_stop(eIDX_SOU_CH idx,
struct chrg_switch_t *pSW)
{
rt_uint16_t regs[2] = {REG_WORK, REG_CURRENT_OUT + 1};
rt_uint16_t vals[2] = {WORK_STOP, 0};
if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
return -1;
}
if (chrg_sou_com_batch_submit(idx, regs, vals, 2U) != 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:参数或命令提交失败
其它说明: 命令顺序为ALL_REL_ON、目标负载电流、WORK_START;不重新设置
协议或CC;低电流待机可能由软卸载进入且主继电器未闭合,恢复时
必须先把继电器打开再启动,防止电子负载先于主继电器带载
*****************************************************************/
static int chrg_sink_work_load_resume(eIDX_SOU_CH idx,
struct chrg_switch_t *pSW)
{
rt_uint16_t regs[3] = {REG_REL_ON, REG_CURRENT_OUT + 1, REG_WORK};
rt_uint16_t vals[3] = {ALL_REL_ON, 0, WORK_START};
if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL) ||
!chrg_sink_load_should_start(pSW)) {
return -1;
}
vals[1] = pSW->sink.loadc;
if (chrg_sou_com_batch_submit(idx, regs, vals, 3U) != 0) {
return -1;
}
pSW->sink.work_mode = SINK_WORK_SOFT_RUNNING;
return 0;
}
/*****************************************************************
函数名称: chrg_sink_work_load_start
函数描述: 从主继电器未打开的低电流待机状态执行完整负载启动
输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体
输出参数: 命令入队成功后进入SINK_WORK_RUNING
返回说明: 0:命令提交成功 <0:参数或命令提交失败
其它说明: 使用独立入口避开状态机对RUNING的重复状态去重;执行副继电器、
全部继电器、目标负载值和WORK_START的标准启动顺序
*****************************************************************/
static int chrg_sink_work_load_start(eIDX_SOU_CH idx,
struct chrg_switch_t *pSW)
{
int ret;
if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
return -1;
}
ret = chrg_sink_work_volt_runing(idx, pSW);
if ((ret == 0) && (pSW->sink.work_mode == SINK_WORK_LOAD_START)) {
pSW->sink.work_mode = SINK_WORK_RUNING;
}
return ret;
}
/*****************************************************************
函数名称: chrg_sink_nor_work_low
函数描述: 执行负载掉电处理,卸载后关闭主副继电器并重新打开副继电器
@@ -397,8 +547,8 @@ static int chrg_sink_nor_work_off(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] = {0x01, REG_WORK};
rt_uint16_t vals[2] = {0x00, WORK_STOP};
rt_uint16_t regs[2] = {REG_REL_ON, REG_WORK};
rt_uint16_t vals[2] = {ALL_REL_OFF, WORK_STOP};
if (chrg_sou_com_batch_submit(idx, regs, vals, 2) != 0) {
return -1;
@@ -442,7 +592,7 @@ static int chrg_sink_work_switch(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
/* 停止成功入队后,清除旧Source运行标志。 */
pSW->source.On_Flag = 0;
/* 首次进入Sink时从协议配置开始,协议应答后再设置目标CC线。 */
/* 首次进入Sink时先设置协议,协议应答后再设置目标CC线。 */
pSW->sub = IDX_SET_SINK_PD;
/* SWITCH只负责旧角色退出,后续启动统一交给Sink INIT状态。 */
pSW->sink.work_mode = SINK_WORK_INIT;
@@ -451,23 +601,23 @@ static int chrg_sink_work_switch(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
/*****************************************************************
函数名称: chrg_sink_work_protocol_unload
函数描述: 仅协议电压变化前的软卸载:停止负载并将设定电流归零
函数描述: 协议电压或电流变化前的软卸载:停止电子负载
输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体
输出参数: -
返回说明: 0:命令提交成功 <0:命令提交失败
其它说明: 不操作北向和南向功率继电器;两条写命令完成后进入UNLOAD_WAIT,
其它说明: 不操作北向和南向功率继电器;WORK_STOP完成后进入UNLOAD_WAIT,
连续确认两帧实际电流不大于100mA,才允许北向重配协议并使用软恢复流程
*****************************************************************/
static int chrg_sink_work_protocol_unload(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
{
rt_uint16_t regs[2] = {REG_WORK, REG_CURRENT_OUT + 1};
rt_uint16_t vals[2] = {WORK_STOP, 0};
rt_uint16_t reg = REG_WORK;
rt_uint16_t value = WORK_STOP;
if (chrg_sou_com_batch_submit(idx, regs, vals, 2) != 0) {
if (chrg_sou_com_batch_submit(idx, &reg, &value, 1U) != 0) {
return -1;
}
/* 写回码只确认命令接收;批次完成后还需连续读取两帧合格的实际电流。 */
/* WORK_STOP回码只确认命令接收;还需连续读取两帧合格的实际电流。 */
chrg_sink_unload_confirm_reset(idx);
pSW->sink.work_mode = SINK_WORK_UNLOAD_WAIT;
return 0;
@@ -510,11 +660,11 @@ static int chrg_sink_work_handshake_prepare(eIDX_SOU_CH idx,
函数名称: chrg_sink_work_current_wait
函数描述: 等待负载安全断开批次完成,并连续确认两帧实际电流不大于100mA
输入参数: idx:南向功率板通道 pSW:当前通道控制结构体
full_handshake:RT_TRUE为完整重握手 RT_FALSE为仅协议电压软卸载
full_handshake:RT_TRUE为完整重握手 RT_FALSE为协议参数软卸载
输出参数: 确认成功后将sink.work_mode切换为SINK_WORK_WAIT
返回说明: 0:继续等待或确认成功 <0:状态查询或优先量测请求失败
其它说明: 只有WORK_STOP和CURRENT=0均收到匹配回码后才建立量测基线;
完整重握手还要求ALL_REL_OFF和FU_REL_ON回码成功,但保持北向Sink继电器接通
其它说明: 软卸载只要求WORK_STOP收到匹配回码后建立量测基线;完整重握手
还要求CURRENT=0、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)
@@ -736,6 +886,19 @@ int chrg_sink_work(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
case SINK_WORK_HANDSHAKE_WAIT:
ret = chrg_sink_work_current_wait(idx, pSW, RT_TRUE);
break;
case SINK_WORK_LOAD_STANDBY:
case SINK_WORK_LOAD_SOFT_STANDBY:
ret = 0;
break;
case SINK_WORK_LOAD_STOP:
ret = chrg_sink_work_load_stop(idx, pSW);
break;
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;
}
+18 -2
View File
@@ -201,6 +201,15 @@ enum {
#define SINK_CMD_SET_AVS 0xE3 // AVS
/*
* 普通恒流负载允许执行WORK_START的最低设定电流,单位mA。
* 小于该值时北向仍完成协议握手,但南向保持WORK_STOP且设定电流为0,
* 避免功率板在零电流或几十mA的小电流设定下启动电子负载产生冲击。
*/
#define SINK_LOAD_ENABLE_MIN_MA 100U
extern rt_bool_t chrg_sink_handshake_north_ready(eIDX_SOU_CH idx);
enum {
SINK_WORK_INIT = 0, // 启动入口:第一条南向命令只打开副继电器
SINK_WORK_INIT_AUX_WAIT, // 等待启动副继电器收到有效南向回码
@@ -212,7 +221,7 @@ enum {
SINK_WORK_LOW_MONITOR, // 副继电器已恢复,等待输入电压重新出现
SINK_WORK_STOP, // 用户主动停止负载
SINK_WORK_SWITCH, // 停止旧电源后进入负载INIT
SINK_WORK_PROTOCOL_UNLOAD, // 仅协议电压变化:掉载但不切换继电器
SINK_WORK_PROTOCOL_UNLOAD, // 协议电压或电流变化:掉载但不切换继电器
SINK_WORK_UNLOAD_WAIT, // 等待软卸载完成并连续两次确认电流不大于100mA
SINK_WORK_SOFT_RESUME_WAIT, // 继电器保持闭合,等待协议电压稳定后恢复负载
SINK_WORK_SOFT_RESUME, // 只恢复目标电流/电压和WORK_START,不写继电器
@@ -221,7 +230,12 @@ enum {
SINK_WORK_ON_TEST_SHORT, // 短路测试启动状态
SINK_WORK_ON_TEST_OCP, // OCP过流保护测试启动状态
SINK_WORK_HANDSHAKE_PREPARE, // 完整重握手:停止、清流、全关继电器后打开副继电器
SINK_WORK_HANDSHAKE_WAIT, // 等待完整重握手批次及连续两次低电流确认
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, // 软待机跨回有效电流:不切继电器,直接恢复电流和WORK_START
};
// sink 参数结构
@@ -393,6 +407,8 @@ extern void chrg_nor_sink_change_test(rt_uint8_t ch, struct chrg_switch_t *pSW);
extern void chrg_nor_sink_test_stop(rt_uint8_t ch,struct chrg_switch_t *pSW,rt_uint8_t *enable);
extern void chrg_nor_sink_test_run(rt_uint8_t ch, struct chrg_switch_t *pSW);
/* 判断普通负载的当前设定是否允许启动电子负载。 */
extern rt_bool_t chrg_sink_load_should_start(const struct chrg_switch_t *pSW);
extern int chrg_sink_work(eIDX_SOU_CH idx, struct chrg_switch_t *pSW);
#endif
+1 -13
View File
@@ -1,20 +1,8 @@
*** 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_sink.c...
compiling chrg_vcom.c...
compiling chrg_rel.c...
compiling chrg_eload.c...
compiling chrg_south.c...
compiling chrg_roll_sou.c...
compiling chrg_north.c...
compiling chrg_source.c...
compiling chrg_roll_nor.c...
compiling chrg_comm.c...
linking...
Program Size: Code=145588 RO-data=15276 RW-data=9328 ZI-data=15944
Program Size: Code=146668 RO-data=15332 RW-data=9328 ZI-data=15968
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).
+162
View File
@@ -1,5 +1,167 @@
# 修改日志
## V1.1.7 - 2026-08-08
### 修改主题
并行执行Sink完整握手中的南向低电流确认与北向协议/CC设置。
### 主要修改
- 南向安全批次完成并收到辅助继电器回码、建立量测基线后,立即允许北向设置协议和CC线。
- 南向实际电流连续两次不大于 `100mA` 的确认过程与北向协议/CC设置并行执行。
- 北向进入 `GET_SINK_VC` 后,只有低电流确认完成且CC后的 `200ms` 查询保护时间到期,才发送第一条 `0x20`。
- 电压稳定后再发送 `ALL_REL_ON -> 目标电流 -> WORK_START`,防止协议协商期间提前带载。
### 涉及文件
- `apps/chrg/applications/thread/chrg_roll_nor.c`
- `apps/chrg/applications/utils/chrg_sink.c`
- `apps/chrg/applications/utils/chrg_sink.h`
### 编译验证
- Keil MDK 编译结果:`0 Error(s), 0 Warning(s)`。
## V1.1.5 - 2026-08-08
### 修改主题
协议电压和协议电流变化统一采用软卸载重发协议流程。
### 主要修改
- 协议类型、CC线和协议组号变化仍进入完整握手并切换南向继电器。
- 协议电压、协议电流单独变化或同时变化时,只发送 `WORK_STOP`,不关闭南向继电器。
- 软卸载不再额外发送 `CURRENT=0`,仅通过实际电流连续两次不大于 `100mA`确认电子负载已停止。
- 协议重新生效且电压稳定后,由RUNNING先写入实际负载电流,再发送 `WORK_START`。
### 涉及文件
- `apps/chrg/applications/thread/chrg_comm.c`
- `apps/chrg/applications/utils/chrg_sink.c`
### 编译验证
- Keil MDK 编译结果:`0 Error(s), 0 Warning(s)`。
## V1.1.4 - 2026-08-07
### 修改主题
调整负载低电流启动时的继电器和工作命令顺序。
### 主要修改
- 设定电流为 `0A` 或低于 `100mA` 时,协议握手仍正常执行。
- 电压达到目标后发送 `ALL_REL_ON`,确保主继电器打开。
- 主继电器打开后继续发送 `WORK_STOP` 和 `CURRENT=0`,保持电子负载不带载。
- 已经处于运行状态切换到低电流时,沿用原有停止流程,不重复切换继电器。
### 涉及文件
- `apps/chrg/applications/utils/chrg_sink.c`
### 编译验证
- Keil MDK 编译结果:`0 Error(s), 0 Warning(s)`。
## V1.1.3 - 2026-08-07
### 修改主题
并行执行Sink南向初始化与北向握手,并优化握手查询和RUNING继电器时序。
### 主要修改
- `INIT`将 `FU_REL_ON -> CURRENT=0 -> MODE -> VON` 作为一个有序南向批次提交。
- 南向初始化批次成功入队后立即打开北向Sink继电器、设置 `enable=1` 并开始协议握手。
- `SINK_WORK_INIT_AUX_WAIT`改为后台监控南向初始化,不再阻塞北向协议、CC和电压查询。
- 南向初始化失败重试时保留当前北向 `sub`,不重复拉回协议设置起点。
- 协议或CC有效回码后,首条 `0x20` 等待 `200ms`;电压未稳定时后续每 `100ms` 查询一次。
- 一帧通过CRC、ID、命令和配置版本校验的电压达到目标后立即进入 `RUNING`,不再等待第二帧。
- 进入稳定运行后立即解除查询节流,恢复北向正常轮询速度。
- `RUNING`删除重复的 `FU_REL_ON`,调整为 `ALL_REL_ON -> 目标负载值 -> WORK_START`。
### 涉及文件
- `apps/chrg/applications/utils/chrg_sink.c`
- `apps/chrg/applications/thread/chrg_roll_nor.c`
- `apps/chrg/applications/thread/chrg_north.c`
### 编译验证
- Keil MDK 编译结果:`0 Error(s), 0 Warning(s)`。
### 硬件验证
- 待确认南向初始化命令与北向协议/CC设置并行执行且互不重置状态。
- 待确认首条和后续 `0x20` 间隔分别约为 `200ms` 和 `100ms`。
- 待确认进入 `RUNING` 时不再发送 `FU_REL_ON`,主继电器不会被重复断开。
## V1.1.2 - 2026-08-07
### 修改主题
降低Sink协议握手阶段的北向电压电流查询频率。
### 主要修改
- 新增 `SINK_HANDSHAKE_QUERY_INTERVAL_MS`,设置为 `200ms`。
- Sink协议或CC设置收到有效回码后,不立即发送或连续快速发送 `0x20` 查询。
- CC路径的 `200ms` 从有效 `0x17` 回码时刻开始计时,包含原有 `50ms` CC稳定保护。
- 协议握手、软恢复等待和掉电恢复监控阶段的 `0x20` 查询按每 `200ms` 一次执行。
- 北向量测连续两次达到稳定条件后解除节流,`RUNING` 和低电流待机恢复正常查询频率。
- 仅重发协议的 `IDX_SET_SINK_PD_ONLY` 路径同样启动 `200ms` 查询等待。
- 设置协议和CC命令仍然按有效回码、超时和原有重试机制处理。
### 涉及文件
- `apps/chrg/applications/thread/chrg_roll_nor.c`
### 编译验证
- Keil MDK 编译结果:`0 Error(s), 0 Warning(s)`。
### 硬件验证
- 待观察协议/CC设置后 `0x20` 的发送间隔是否稳定为不小于 `200ms`。
- 待验证电压连续两次稳定后是否恢复正常量测频率。
## V1.1.1 - 2026-08-07
### 修改主题
增加普通负载最低带载电流控制,低电流时保持协议在线但关闭电子负载。
### 主要修改
- 新增 `SINK_LOAD_ENABLE_MIN_MA`,恒流负载设定低于 `100mA` 时禁止发送 `WORK_START`。
- 最低带载门限只判断南向负载电流 `loadc`,不影响北向协议电流 `pro_loadc` 和协议握手。
- 首次启动或完整重握手后为低电流时,发送 `WORK_STOP -> CURRENT=0` 并保持主继电器关闭。
- 运行中由有效电流降至低电流时,发送 `WORK_STOP -> CURRENT=0`,保持协议、CC和继电器不变。
- 运行中低电流待机恢复有效电流时,只发送目标电流和 `WORK_START`,不重新握手或切换继电器。
- 主继电器未打开的低电流待机使用独立 `SINK_WORK_LOAD_START` 恢复入口,避免被 `RUNING` 状态去重。
- 低电流待机期间仅修改协议电压时不重复卸载,并保持原有主继电器状态语义。
- 将 COM 端运行电流跨门限判断封装为 `chrg_comm_handle_sink_load_current()`,避免生效分支继续膨胀。
- 北向解析将两种低电流待机状态作为稳定状态,不因实际电流为零反复进入 `RUNING`。
### 涉及文件
- `apps/chrg/applications/utils/chrg_sink.h`
- `apps/chrg/applications/utils/chrg_sink.c`
- `apps/chrg/applications/thread/chrg_comm.c`
- `apps/chrg/applications/thread/chrg_north.c`
### 编译验证
- Keil MDK 编译结果:`0 Error(s), 0 Warning(s)`。
### 硬件验证
- 待验证 `20V/3A -> 20V/0A -> 20V/3A` 的南向命令顺序和协议保持情况。
- 待验证首次以低于 `100mA` 的电流启动时,北向握手正常且南向不执行 `WORK_START`。
## V1.1.0 - 2026-08-07
### 修改主题