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:
@@ -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;
|
||||
/*
|
||||
* 只有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) {
|
||||
/* 仅协议电压变化时保持主副继电器状态,只停止负载并清零电流。 */
|
||||
} else if (protocol_voltage_only || protocol_current_change) {
|
||||
/*
|
||||
* 协议电压、协议电流变化都只执行软卸载,不关闭南向继电器。
|
||||
* 低电流待机本身已经WORK_STOP,无需重复提交卸载命令;运行中
|
||||
* 则等待实际电流降到安全范围后再重发协议。
|
||||
*/
|
||||
pReal->sub = IDX_SET_SINK_PD_ONLY;
|
||||
pReal->sink.work_mode = SINK_WORK_PROTOCOL_UNLOAD;
|
||||
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参数生效后的同角色电源启停和参数差异更新
|
||||
|
||||
@@ -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]) >=
|
||||
|
||||
@@ -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校准参数解析
|
||||
|
||||
@@ -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;
|
||||
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_WAIT_MS)) {
|
||||
return RT_TRUE;
|
||||
}
|
||||
|
||||
if ((g_sink_cc_wait_mask & bit) == 0U) {
|
||||
/* 协议已先设置;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_FALSE;
|
||||
}
|
||||
elapsed = (rt_tick_t)(rt_tick_get() - g_sink_cc_wait_start[ch]);
|
||||
if (elapsed < rt_tick_from_millisecond(SINK_CC_STABLE_WAIT_MS)) {
|
||||
return RT_TRUE;
|
||||
}
|
||||
|
||||
g_sink_cc_wait_mask &= (rt_uint8_t)~bit;
|
||||
g_sink_cc_wait_start[ch] = 0U;
|
||||
pSW->sub = IDX_GET_SINK_VC;
|
||||
/* 首条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。 */
|
||||
|
||||
@@ -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, ®, &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路径。 */
|
||||
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;
|
||||
pNOR->enable[idx] = 1;
|
||||
chrg_nor_sw_rel((eIDX_NOR_CH)idx, ID_SINK);
|
||||
pSW->sub = IDX_SET_SINK_PD;
|
||||
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;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
if (chrg_sou_com_batch_submit(idx, regs, vals, 2U) != 0) {
|
||||
|
||||
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, ®, &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;
|
||||
}
|
||||
|
||||
@@ -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,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).
|
||||
|
||||
Reference in New Issue
Block a user