可正常使用版本,代价是5V比较慢
chore: 完成充电控制软件多项功能迭代与优化 1. 修改chrg.uvprojx,开启调试前更新Flash 2. 新增协议回码等待状态,注释掉协议优先于CC的测试流程 3. 启用南向寄存器写命令调试日志 4. 重构Sink工作状态机,拆分关机流程为多阶段等待 5. 新增主继电器0V持续掉电保护功能 6. 优化南向单次量测队列管理,修复多通道低电流确认异常 7. 调整电压稳定确认逻辑,为5V目标增加更长确认窗口 8. 移除软恢复相关状态与逻辑,简化状态流转
This commit is contained in:
@@ -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,8 +2434,21 @@ static eMBException chrg_comm_apply_sink_effect(rt_uint8_t ch,
|
||||
}
|
||||
} else {
|
||||
pReal->sink.On_work = 0;
|
||||
/* 组合控制或上位机重发可能在关机尚未完成时再次提交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) ?
|
||||
MB_EX_NONE : MB_EX_SLAVE_BUSY;
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,9 @@
|
||||
#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_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;
|
||||
|
||||
@@ -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校准参数解析
|
||||
|
||||
@@ -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,19 +303,17 @@ 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) {
|
||||
|
||||
/* 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) &&
|
||||
(pSW->sub != IDX_WAIT_SINK_CC_BEFORE_PD)) {
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1016,7 +1029,10 @@ void chrg_roll_nor_thread_entry (void *data)
|
||||
(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_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);
|
||||
}
|
||||
/*
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
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;
|
||||
} else {
|
||||
regs[2] = REG_CURRENT_OUT + 1;
|
||||
vals[2] = pSW->sink.loadc;
|
||||
}
|
||||
if (chrg_sou_com_batch_submit(idx, regs, vals, 3U) != 0) {
|
||||
return -1;
|
||||
}
|
||||
pSW->sink.work_mode = SINK_WORK_SOFT_RUNNING;
|
||||
/* 只有南向实测电压曾经到位后再次掉到低压,才判定为掉电。
|
||||
* 初次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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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 参数结构
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
<UseTargetDll>1</UseTargetDll>
|
||||
<UseExternalTool>0</UseExternalTool>
|
||||
<RunIndependent>0</RunIndependent>
|
||||
<UpdateFlashBeforeDebugging>0</UpdateFlashBeforeDebugging>
|
||||
<UpdateFlashBeforeDebugging>1</UpdateFlashBeforeDebugging>
|
||||
<Capability>1</Capability>
|
||||
<DriverSelection>4096</DriverSelection>
|
||||
</Flash1>
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user