From 587e03b65f58b8530348925f1eb50ec93e14ab36 Mon Sep 17 00:00:00 2001 From: wrh Date: Wed, 22 Jul 2026 10:14:48 +0800 Subject: [PATCH] =?UTF-8?q?refactor(chrg):=20=E9=87=8D=E6=9E=84=E5=8C=97?= =?UTF-8?q?=E5=90=91=E8=BD=AE=E8=AF=A2=E4=B8=8E=E7=8A=B6=E6=80=81=E6=9C=BA?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=EF=BC=8C=E8=A1=A5=E5=85=85=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=E4=B8=8E=E5=87=BD=E6=95=B0=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. apps/chrg/applications/thread/chrg_roll_nor.c: 新增chrg_roll_nor_cmd、chrg_roll_nor_set函数注释,补充线程判断逻辑注释 2. apps/chrg/applications/thread/chrg_comm.c: 完善modbus写入寄存器的注释,补充角色切换逻辑说明 3. apps/chrg/applications/utils/chrg_source.c: 为所有电源状态机函数补充详细中文注释与函数说明 4. apps/chrg/applications/thread/chrg_north.c: 删除冗余全局变量与函数,补充帧处理、解析函数注释,修正初始化注释 5. apps/chrg/applications/utils/chrg_sink.c: 删除大量废弃测试代码,为所有负载状态机函数补充详细中文注释与函数说明 --- apps/chrg/applications/thread/chrg_comm.c | 18 +- apps/chrg/applications/thread/chrg_north.c | 79 +++- apps/chrg/applications/thread/chrg_roll_nor.c | 24 +- apps/chrg/applications/utils/chrg_sink.c | 391 +++--------------- apps/chrg/applications/utils/chrg_source.c | 69 +++- 5 files changed, 238 insertions(+), 343 deletions(-) diff --git a/apps/chrg/applications/thread/chrg_comm.c b/apps/chrg/applications/thread/chrg_comm.c index a638b75..9f46ba8 100644 --- a/apps/chrg/applications/thread/chrg_comm.c +++ b/apps/chrg/applications/thread/chrg_comm.c @@ -1867,7 +1867,11 @@ static eMBException chrg_mb_write_sys(rt_uint8_t ch, rt_uint16_t reg_offset, rt_ struct chrg_thread_t *pTHR_NOR = &chrgthr[IDX_THR_ROLL_NOR]; rt_mutex_take(pTHR_NOR->mutex, RT_WAITING_FOREVER); - /* 保存复制前的真实角色,复制后据此判断是否需要先停后切。 */ + /* + * pReal保存当前正在运行的真实状态,pSW指向COM影子配置。 + * 必须在rt_memcpy之前保存old_id,否则复制后会丢失旧角色, + * 无法判断本次生效是普通参数更新还是Source/Sink角色切换。 + */ eIDX_ID old_id = pReal->id; g_shadow_dirty[ch] = 0; @@ -1878,6 +1882,7 @@ static eMBException chrg_mb_write_sys(rt_uint8_t ch, rt_uint16_t reg_offset, rt_ rt_uint16_t old_loadv = pReal->sink.loadv; rt_uint16_t old_loadc = pReal->sink.loadc; //rt_uint8_t old_sink_test = pReal->sink.test.test_mode; + /* COM参数统一生效;复制完成后的id就是本次请求的目标角色。 */ rt_memcpy(pReal, &g_shadow_sw[ch], sizeof(struct chrg_switch_t)); eIDX_ID new_id = pReal->id; @@ -1885,7 +1890,11 @@ static eMBException chrg_mb_write_sys(rt_uint8_t ch, rt_uint16_t reg_offset, rt_ { int switch_ret; - /* 复制后按新角色选择状态机,保证id与work_mode归属一致。 */ + /* + * SWITCH表示“切换进入new_id对应角色”,因此必须按new_id + * 选择状态机,保证ID_SOURCE只使用Source状态机,ID_SINK + * 只使用Sink状态机。SWITCH内部先停止旧角色,再转入INIT。 + */ if (new_id == ID_SOURCE) { pReal->source.work_mode = SOURCE_WORK_SWITCH; switch_ret = chrg_source_work_state(ch, pReal); @@ -1894,12 +1903,17 @@ static eMBException chrg_mb_write_sys(rt_uint8_t ch, rt_uint16_t reg_offset, rt_ switch_ret = chrg_sink_work((eIDX_SOU_CH)ch, pReal); } + /* 入队失败时保留影子待生效标志,让COM返回忙并允许重试。 */ if (switch_ret != 0) { g_shadow_dirty[ch] = 1; rt_mutex_release(pTHR_NOR->mutex); return MB_EX_SLAVE_BUSY; } + /* + * 角色切换路径已经完成状态安排,必须直接返回,避免继续执行 + * 下方同角色启动/停止逻辑并再次覆盖INIT状态。 + */ rt_mutex_release(pTHR_NOR->mutex); return MB_EX_NONE; } diff --git a/apps/chrg/applications/thread/chrg_north.c b/apps/chrg/applications/thread/chrg_north.c index 364a3a3..75c83a0 100644 --- a/apps/chrg/applications/thread/chrg_north.c +++ b/apps/chrg/applications/thread/chrg_north.c @@ -23,12 +23,6 @@ //#define LOG_TAG "chrg.nor" #define DBG_LEVEL DBG_LOG #include -rt_uint16_t volt; -uint16_t chrg_compare(rt_int16_t a, rt_int16_t b) -{ - if(a>b) return a - b; - else return b - a; -} /***************************************************************** 函数名称: chrg_source_standard_output @@ -53,7 +47,16 @@ void chrg_source_standard_output(eIDX_SOU_CH idx, struct chrg_switch_t *pSW) } } -//电源快充 +/***************************************************************** +函数名称: chrg_source_parse +函数描述: 解析北向电源板电压电流回码并驱动Source状态机 +输入参数: frame_data:完整北向回码 idx:当前通道 pSW:通道控制结构体 + pNOR:北向总控结构体 +输出参数: 更新协商电压、电流、source.work_mode及上次下发电压缓存 +返回说明: - +其它说明: frame_data[4~7]为实测值,[8~11]为协议协商目标值; + 目标电压变化时进入RUNING,相同时进入WAIT +*****************************************************************/ void chrg_source_parse(rt_uint8_t *frame_data, eIDX_SOU_CH idx, struct chrg_switch_t *pSW, struct chrg_north_t *pNOR) { @@ -61,7 +64,6 @@ void chrg_source_parse(rt_uint8_t *frame_data, eIDX_SOU_CH idx, rt_uint16_t Curr_mA = (frame_data[10] << 8) | frame_data[11]; rt_uint16_t volt_mv_Now = (frame_data[4] << 8) | frame_data[5]; rt_uint16_t Curr_mA_Now = (frame_data[6] << 8) | frame_data[7]; - rt_uint16_t volt_compare = chrg_compare(volt_mv, volt_mv_Now); static rt_uint16_t last_volt_mv[TOTAL_SOU_CHS] = {0}; static rt_uint8_t number = 0; int ret; @@ -84,7 +86,15 @@ void chrg_source_parse(rt_uint8_t *frame_data, eIDX_SOU_CH idx, } } -//电源设置 +/***************************************************************** +函数名称: chrg_source_setting +函数描述: 根据电源协议类型和启停标志选择标准输出或快充解析流程 +输入参数: frame_data:北向回码 idx:当前通道 pSW:通道控制结构体 + pNOR:北向总控结构体 +输出参数: 可能更新功率板设定值或北向子状态sub +返回说明: - +其它说明: 标准协议直接设置输出,快充协议使用协商结果驱动状态机 +*****************************************************************/ void chrg_source_setting(rt_uint8_t *frame_data, eIDX_SOU_CH idx, struct chrg_switch_t *pSW, struct chrg_north_t *pNOR) { @@ -103,7 +113,16 @@ void chrg_source_setting(rt_uint8_t *frame_data, eIDX_SOU_CH idx, } } -//解析负载返回数据 +/***************************************************************** +函数名称: chrg_sink_parse +函数描述: 解析北向负载板回码并根据电压、电流反馈驱动Sink状态机 +输入参数: frame_data:完整北向回码 idx:当前通道 pSW:通道控制结构体 + pNOR:北向总控结构体 +输出参数: 更新VZ、VF、低压计数、无电流计数及sink.work_mode +返回说明: - +其它说明: 电压连续低于门槛进入LOW;电压达到目标附近进入RUNING; + 运行电流连续过低时退回WAIT重新判断 +*****************************************************************/ void chrg_sink_parse(rt_uint8_t *frame_data, eIDX_SOU_CH idx, struct chrg_switch_t *pSW, struct chrg_north_t *pNOR) { @@ -163,8 +182,12 @@ void chrg_sink_parse(rt_uint8_t *frame_data, eIDX_SOU_CH idx, /***************************************************************** 函数名称: chrg_north_handle_Seting_Volt -功能描述: 处理设置电压/电流命令,解析命令数据并执行相应操作 -****************************************************/ +函数描述: 根据当前通道角色分发21字节电压电流回码 +输入参数: frame_data:完整北向回码 frame_len:回码长度 +输出参数: 调用Source或Sink解析函数更新当前通道状态 +返回说明: - +其它说明: 当前通道由chrgnorth.idx确定,角色由pSW->id确定 +*****************************************************************/ rt_uint8_t change_number = 0; static void chrg_north_handle_Seting_Volt(rt_uint8_t *frame_data, rt_uint16_t frame_len) { @@ -198,7 +221,7 @@ struct chrg_north_t chrgnorth = { .source = { // 电源侧参数初始化 .On_Flag = 0, // 启动标志初始关闭 .Set_CV_Flag = 1, // 启停控制初始置1 - .work_mode = SOURCE_WORK_WAIT, + .work_mode = SOURCE_WORK_WAIT, // 上电保持等待,禁止自动执行Source INIT }, // 关键:补充逗号分隔source和sink .sink = { .protocol = 0xFE, @@ -216,7 +239,7 @@ struct chrg_north_t chrgnorth = { .source = { .On_Flag = 0, .Set_CV_Flag = 1, - .work_mode = SOURCE_WORK_WAIT, + .work_mode = SOURCE_WORK_WAIT, // 上电保持等待,禁止自动执行Source INIT }, .sink = { .protocol = 0xFE, @@ -233,7 +256,7 @@ struct chrg_north_t chrgnorth = { .source = { .On_Flag = 0, .Set_CV_Flag = 1, - .work_mode = SOURCE_WORK_WAIT, + .work_mode = SOURCE_WORK_WAIT, // 上电保持等待,禁止自动执行Source INIT }, .sink = { .protocol = 0xFE, @@ -250,7 +273,7 @@ struct chrg_north_t chrgnorth = { .source = { .On_Flag = 0, .Set_CV_Flag = 1, - .work_mode = SOURCE_WORK_WAIT, + .work_mode = SOURCE_WORK_WAIT, // 上电保持等待,禁止自动执行Source INIT }, .sink = { .protocol = 0xFE, @@ -393,6 +416,14 @@ int a_number; #define NORTH_FRAME_TIMEOUT_MS 100 +/***************************************************************** +函数名称: chrg_north_frame_reset +函数描述: 复位北向帧接收状态并按需释放未完成帧内存 +输入参数: pFrame:帧接收上下文 release:是否释放pMB及payload +输出参数: 清零接收长度、帧头标志、超时计时和消息指针 +返回说明: - +其它说明: 完整帧已移交邮箱时release应为RT_FALSE,异常中止时为RT_TRUE +*****************************************************************/ static void chrg_north_frame_reset(struct pickup_info_t *pFrame, rt_bool_t release) { if (RT_NULL == pFrame) { @@ -413,6 +444,14 @@ static void chrg_north_frame_reset(struct pickup_info_t *pFrame, rt_bool_t relea pFrame->pMB = RT_NULL; } +/***************************************************************** +函数名称: chrg_north_frame_append +函数描述: 从北向环形缓冲区追加数据到当前未完成帧 +输入参数: rb:北向接收环形缓冲区 pFrame:帧接收上下文 +输出参数: 更新已接收长度和最后接收时间 +返回说明: 1:完整帧接收完成 0:仍需等待数据 <0:参数或状态异常 +其它说明: 单次仅复制当前帧剩余长度,避免读取下一帧数据 +*****************************************************************/ static int chrg_north_frame_append(struct rt_ringbuffer *rb, struct pickup_info_t *pFrame) { @@ -444,6 +483,14 @@ static int chrg_north_frame_append(struct rt_ringbuffer *rb, return (pFrame->length == (rt_size_t)pFrame->len_msg) ? 1 : 0; } +/***************************************************************** +函数名称: chrg_north_frame_dispatch +函数描述: 分发已经组装完成的北向数据帧 +输入参数: pFrame:包含完整pMB消息的帧接收上下文 +输出参数: 21字节回码进入电压解析,同时完整消息发送到北向轮询邮箱 +返回说明: - +其它说明: 消息所有权移交邮箱后只复位上下文,不在此处释放pMB +*****************************************************************/ static void chrg_north_frame_dispatch(struct pickup_info_t *pFrame) { struct mb_msg_t *pMB = pFrame->pMB; diff --git a/apps/chrg/applications/thread/chrg_roll_nor.c b/apps/chrg/applications/thread/chrg_roll_nor.c index 3d72e77..d2fcbcd 100644 --- a/apps/chrg/applications/thread/chrg_roll_nor.c +++ b/apps/chrg/applications/thread/chrg_roll_nor.c @@ -272,6 +272,14 @@ static int chrg_roll_nor_parse (struct chrg_rollnor_t *pROLL, rt_uint8_t *data) return 0; } +/***************************************************************** +函数名称: chrg_roll_nor_cmd +函数描述: 执行北向手动插入命令的入口检查 +输入参数: pROLL:北向轮询控制结构体 +输出参数: - +返回说明: 0:参数有效 <0:参数为空 +其它说明: 当前仅保留入口,具体手动命令由后续功能扩展 +*****************************************************************/ static int chrg_roll_nor_cmd (struct chrg_rollnor_t *pROLL) { if (RT_NULL == pROLL) { @@ -279,6 +287,15 @@ static int chrg_roll_nor_cmd (struct chrg_rollnor_t *pROLL) } return 0; } +/***************************************************************** +函数名称: chrg_roll_nor_set +函数描述: 按当前角色和sub状态发送一条北向协议命令 +输入参数: ch:北向通道编号 pSW:通道控制结构体 enable:通道使能指针 +输出参数: 某些发送步骤成功发起后推进pSW->sub +返回说明: - +其它说明: Source依次执行CC选择、协议设置、VC查询; + Sink依次执行CC线选择、协议设置、VC查询 +*****************************************************************/ void chrg_roll_nor_set(rt_uint8_t ch, struct chrg_switch_t *pSW,rt_uint8_t *enable) { if(pSW->id==ID_SOURCE){ //电源 @@ -358,7 +375,12 @@ void chrg_roll_nor_thread_entry (void *data) idx = index%TOTAL_NOR_CHS; pSW = &pNOR->sw[idx]; rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER); - /* INIT/STOP必须在enable过滤前执行,否则停机通道无法重新启动。 */ + /* + * INIT/STOP必须在enable过滤前执行:STOP会把enable清零,而COM + * 启动时只改变work_mode。若先判断enable,停机通道会直接continue, + * INIT永远没有机会把enable重新置1,也就无法恢复北向轮询。 + * Source->Sink切换后的SINK_WORK_INIT同样从这里首次执行。 + */ if ((pSW->id == ID_SOURCE) && ((pSW->source.work_mode == SOURCE_WORK_INIT) || (pSW->source.work_mode == SOURCE_WORK_STOP))) { diff --git a/apps/chrg/applications/utils/chrg_sink.c b/apps/chrg/applications/utils/chrg_sink.c index 32a839a..aecb00f 100644 --- a/apps/chrg/applications/utils/chrg_sink.c +++ b/apps/chrg/applications/utils/chrg_sink.c @@ -128,322 +128,14 @@ int sink_set_pd (rt_uint8_t pd, rt_uint8_t *buf) return chrg_north_send(frame, len); } -//// 短路测试参数解析 指令码:0x01 -//void sink_test_short_set(struct chrg_switch_t *pSW, rt_uint8_t *pData, rt_uint8_t run_flag) -//{ -// struct test_short *pTest = &pSW->sink.test.short_test; - -// // 解析报文:高字节pData[1]、低字节pData[2] → 测试保持时间 -// pTest->hold_time = (pData[1] << 8) | pData[2]; -// pTest->set_mode = pData[3]; // 模式选择:0=测试后一直保持;1=保持指定时长后恢复原有电流 -// rt_kprintf("[SINK] Short Test: time=%d, mode=%d\n", -// pTest->hold_time, pTest->set_mode); -//} - -////============================================================================= -//// OCP过流保护测试参数解析 指令码:0x02 -////============================================================================= -//void sink_test_ocp_set(struct chrg_switch_t *pSW, rt_uint8_t *pData, rt_uint8_t run_flag) -//{ -// struct test_OCP *pTest = &pSW->sink.test.OCP_test; - -// pTest->start_curr = (pData[1] << 8) | pData[2]; // 解析:OCP测试起始电流 -// pTest->end_curr = (pData[3] << 8) | pData[4]; // 解析:OCP测试终止电流 -// pTest->change_curr = (pData[5] << 8) | pData[6]; // 解析:电流步进值 -// pTest->change_keep_time = (pData[7] << 8) | pData[8]; // 解析:单步电流保持时间 -// pTest->hold_time = (pData[9] << 8) | pData[10]; // 解析:OCP触发后保持时间 -// pTest->stop_volt = (pData[11]<< 8) | pData[12]; // 解析:停止判定电压 -// pTest->set_mode = pData[13]; // 测试结束模式:0=保持设定时间后恢复;1=一直保持 -// pTest->hold_curr = pData[14]; // OCP触发后是否带载,0=带载,1=不带载 -// // pTest->change_mode = pData[11]; // 电流变化模式(预留):0=置0;1=达标立即置0;2=保持当前电流 -// // pTest->interval_time = pData[12]; // 指令保护间隔时间(预留) - -// pSW->sink.loadc = pTest->start_curr; // 负载电流初始化为OCP起始电流 -//#if SINK_TEST_DEBUG -// rt_kprintf("[SINK] OCP Test: start=%d, end=%d\n", -// pTest->start_curr, pTest->end_curr); -//#endif -//} - -////============================================================================= -//// 动态负载测试参数解析 指令码:0x03 -////============================================================================= -//void sink_test_dynamic_set(struct chrg_switch_t *pSW, rt_uint8_t *pData, rt_uint8_t run_flag) -//{ -// struct test_change *pTest = &pSW->sink.test.change_test; -//// rt_uint16_t change_curr = 0; -// pTest->curr1_set = (pData[1] << 8) | pData[2]; // 解析:第一阶段设定电流 -// pTest->time1_set = (pData[3] << 8) | pData[4]; // 解析:第一阶段保持时长 -// pTest->curr2_set = (pData[5] << 8) | pData[6]; // 解析:第二阶段设定电流 -// pTest->time2_set = (pData[7]<< 8) | pData[8]; // 解析:第二阶段保持时长 -// pTest->k_Rise = (pData[9] << 8) | pData[10]; // 电流上升斜率 -// pTest->k_Fall = (pData[11]<< 8) | pData[12]; // 电流下降斜率 -// // pTest->start_time = (pData[14]<< 8) | pData[13]; // 产品稳定时长(预留) - -// // pSW->sink.loadc = pTest->curr1_set; -//#if SINK_TEST_DEBUG -// rt_kprintf("[SINK] Dynamic Test: curr1=%d, curr2=%d\n", -// pTest->curr1_set, pTest->curr2_set); -//#endif -//} - -////============================================================================= -//// 短路测试状态机执行函数 -//// 依据 work_step 分步配置寄存器,启动短路测试 -////============================================================================= -//void chrg_nor_sink_short_test(rt_uint8_t ch, struct chrg_switch_t *pSW) -//{ -// struct test *pTest = &pSW->sink.test; -// -// switch (pTest->work_step) -// { -// case 0: -// // 第一步:切换为电子负载模式,吸合负载开关 -// chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_ELOAD, ELOAD_LOAD); -//// rt_kprintf("first\r\n"); -// chrg_nor_sw_rel((eIDX_NOR_CH)ch,ID_SINK); -// pTest->work_step = 1; -// break; -// case 1: -// // 根据模式分支配置参数 -// if(pTest->short_test.set_mode == 0x00) { //直接释放 -// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_ShortTest_CMD_MODE_FLAG , ModbusRTU_DYNA_CMD_MODE_RUN_NO_CURR); //直接为0 -// pTest->work_step = 2; -// } -// else{ //按设定的时间后释放 -// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_ShortTest_CMD_MODE_FLAG , ModbusRTU_DYNA_CMD_MODE_RUN_ALWAYS_KEPP); //保持 -// pTest->work_step = 4; -// } -// -// rt_kprintf("set_mode = %d",pTest->short_test.set_mode); -// break; -// case 2: -// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_ShortTest_Hold_Time , pTest->short_test.hold_time); -// pTest->work_step = 4; -// break; -// case 4: -// // 启动整机工作,清零状态标志 -// chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_WORK, WORK_START); -// pTest->work_step = 5; -// pSW->change_flag = 0; -// break; -// case 5: -// break; -// default: -// pTest->work_step = 0; -// break; -// } -//} - -////============================================================================= -//// OCP过流保护测试状态机执行函数 -//// 分步配置电流、时长、模式寄存器,最终启动OCP测试 -////============================================================================= -//// OCP测试执行 -//void chrg_nor_sink_OCP_test(rt_uint8_t ch, struct chrg_switch_t *pSW) -//{ -// struct test *pTest = &pSW->sink.test; - -// switch (pTest->work_step) -// { -// case 0: // 初始化:切负载模式、闭合负载开关 -// chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_ELOAD, ELOAD_LOAD); -//// rt_kprintf("first\r\n"); -// chrg_nor_sw_rel((eIDX_NOR_CH)ch,ID_SINK); -// pTest->work_step = SET_OCP_STARTCURR; -// break; -// case SET_OCP_STARTCURR: // 设置OCP起始电流 -// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_OCPTest_StartCurrent, pTest->OCP_test.start_curr); -// pTest->work_step = SET_OCP_ENDCURR; -// break; -// case SET_OCP_ENDCURR: // 设置OCP终止电流 -// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_OCPTest_StopCurrent , pTest->OCP_test.end_curr); -// pTest->work_step = SET_OCP_STEP; -// break; -// case SET_OCP_STEP: // 设置电流步进值 -// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_OCPTest_Step_CURR , pTest->OCP_test.change_curr); -// pTest->work_step = SET_OCP_STEP_HOLD_TIME; -// break; -// case SET_OCP_STEP_HOLD_TIME: // 设置单步保持时间 -// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_OCPTest_Step_Hold_Time , pTest->OCP_test.change_keep_time); -// pTest->work_step = SINK_OCP_STOP_VOLT; -// break; -// case SINK_OCP_STOP_VOLT: //设置截止电压 -// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_OCPTest_Vtrig_Stop , pTest->OCP_test.stop_volt); -// pTest->work_step = SET_OCP_CMD_MODE_RUN; -// break; -// case SET_OCP_CMD_MODE_RUN: // 标记测试运行模式 -// if(pTest->OCP_test.set_mode == 0x00) { //释放 -// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_OCPTest_CMD_MODE_FLAG , ModbusRTU_DYNA_CMD_MODE_RUN_NO_CURR); //直接为0 -// pTest->work_step = SET_OCP_HOLD_TIME; -// } -// else{ //保持 -// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_OCPTest_CMD_MODE_FLAG , ModbusRTU_DYNA_CMD_MODE_RUN_ALWAYS_KEPP); //保持 -// pTest->work_step = SET_OCP_RUNNING; -// } -// break; -// case SET_OCP_HOLD_TIME: // 设置OCP触发后保持时间 -// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_OCPTest_Hold_Time , pTest->OCP_test.hold_time); -// pTest->work_step = SET_OCP_RUNNING; -// break; -// case SET_OCP_RUNNING: // 启动OCP测试 -// chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_WORK, WORK_START); -// pSW->change_flag = 0; -// pTest->work_step = 0x10; -// break; -// case 0x10: -// break; -// default: -// break; -// } -//} -////============================================================================= -//// 动态负载测试状态机执行函数 -//// 依次配置两段电流、时长、升降斜率,启动动态负载测试 -////============================================================================= -//void chrg_nor_sink_change_test(rt_uint8_t ch, struct chrg_switch_t *pSW) -//{ -// struct test *pTest = &pSW->sink.test; - -// switch (pTest->work_step) -// { -// case 0: // 初始步骤:切换电子负载模式、闭合负载开关 -// chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_ELOAD, ELOAD_LOAD); -// chrg_nor_sw_rel((eIDX_NOR_CH)ch,ID_SINK); -// pTest->work_step = SET_DYNA_CURR1; -// break; -// case SET_DYNA_CURR1: // 设置第一路输出电流 -// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_DYNA_L1, pTest->change_test.curr1_set); -// pTest->work_step = SET_DYNA_TIME1; -// #if SINK_TEST_DEBUG -// rt_kprintf("Curr1: %d\n", pTest->change_test.curr1_set); -// #endif -// break; -// case SET_DYNA_TIME1: // 设置第一阶段保持时间 -// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_DYNA_T1 , pTest->change_test.time1_set); -// pTest->work_step = SET_DYNA_CURR2; -// #if SINK_TEST_DEBUG -// rt_kprintf("Time1: %d\n", pTest->change_test.time1_set); -// #endif -// break; -// case SET_DYNA_CURR2: // 设置第二路输出电流 -// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_DYNA_L2 , pTest->change_test.curr2_set); -// pTest->work_step = SET_DYNA_TIME2; -// #if SINK_TEST_DEBUG -// rt_kprintf("Curr2: %d\n", pTest->change_test.curr2_set); -// #endif -// break; -// case SET_DYNA_TIME2: // 设置第二阶段保持时间 -// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_DYNA_T2 , pTest->change_test.time2_set); -// pTest->work_step = SET_DYNA_RISE_SLEW_RATE; -// #if SINK_TEST_DEBUG -// rt_kprintf("Time2: %d\n", pTest->change_test.time2_set); -// #endif -// break; -// case SET_DYNA_RISE_SLEW_RATE: // 设置电流上升斜率 -// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_DYNA_Rise_Slew_Rate , pTest->change_test.k_Rise); -// pTest->work_step = SET_DYNA_FALL_SLEW_RATE; -// #if SINK_TEST_DEBUG -// rt_kprintf("Rise Slew Rate: %d\n", pTest->change_test.k_Rise); -// #endif -// break; -// case SET_DYNA_FALL_SLEW_RATE: // 设置电流下降斜率 -// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_DYNA_Fall_Slew_Rate , pTest->change_test.k_Fall); -// pTest->work_step = SET_DYNA_CND_MODE; -// #if SINK_TEST_DEBUG -// rt_kprintf("Fall Slew Rate: %d\n", pTest->change_test.k_Fall); -// #endif -// break; -// case SET_DYNA_CND_MODE: // 标记动态测试为运行状态 -// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_DYNA_CMD_MODE_FLAG , ModbusRTU_DYNA_CMD_MODE_RUN); -// pTest->work_step = SET_DYNA_RUNNING; -// pTest->work_step = SET_DYNA_CND_MODE; -// #if SINK_TEST_DEBUG -// rt_kprintf("Fall Slew Rate: %d\n", pTest->change_test.k_Fall); -// #endif -// break; -// case SET_DYNA_RUNNING: // 启动整机工作,锁定当前运行步骤、清空标志位 -// chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_WORK, WORK_START); -// pTest->work_step = SET_DYNA_RUNNING; -// pTest->work_step = 0x11; -// pSW->change_flag = 0; -// break; -// case 0x11: -// break; -// default: -// #if SINK_TEST_DEBUG -// rt_kprintf("Invalid work step: %d\n", pTest->work_step); -// #endif -// break; -// } -//} - -////============================================================================= -//// 短路测试停止处理函数 -//// 依据 stop_step 分步执行停止流程,清除测试标记并跳转状态 -////============================================================================= -//void chrg_nor_sink_short_test_stop(rt_uint8_t idx, struct chrg_switch_t *pSW,rt_uint8_t *enable) -//{ -// struct test *pTest = &pSW->sink.test; -// switch (pTest->stop_step) -// { -// case TEST_STOP_CMD_MODE: // 下发停止指令,关闭短路测试运行模式 -// chrg_set_sou_reg(idx, ModbusRTU_ShortTest_CMD_MODE_FLAG, ModbusRTU_DYNA_CMD_MODE_STOP); -// // pTest->stop_step = TEST_STOP_RUN; -// // break; -// // case TEST_STOP_RUN: // 清除测试标志,切换至负载状态管理流程 -// //chrg_set_sou_reg(idx, REG_WORK, WORK_STOP); -// //pTest->stop_step = TEST_STOP_REL; -// //chrg_nor_sw_rel((eIDX_NOR_CH)idx,0); -// //*enable = 0; -// pSW->change_flag = 0; -// pSW->sink.test.test_mode = 0; // 清空短路测试标记 -// pSW->sub = 21; // IDX_SET_SINK_WORK_STATE; 跳转至负载工作状态处理 -// break; -// default: -// break; -// } -//} - -////============================================================================= -//// OCP过流保护测试停止处理函数 -////============================================================================= -//void chrg_nor_sink_OCP_test_stop(rt_uint8_t idx, struct chrg_switch_t *pSW,rt_uint8_t *enable) -//{ -// struct test *pTest = &pSW->sink.test; -// switch (pTest->stop_step) -// { -// case TEST_STOP_CMD_MODE: // 下发停止指令,关闭OCP测试运行模式 -// chrg_set_sou_reg((eIDX_SOU_CH)idx, ModbusRTU_OCPTest_CMD_MODE_FLAG , ModbusRTU_DYNA_CMD_MODE_STOP); -// pSW->change_flag = 0; -// pSW->sink.test.test_mode = 0; // 清空OCP测试标记 -// pSW->sub = 21; // IDX_SET_SINK_WORK_STATE; -// break; -// default: -// break; -// } -//} - -////============================================================================= -//// 动态负载测试停止处理函数 -////============================================================================= -//void chrg_nor_sink_change_test_stop(rt_uint8_t idx, struct chrg_switch_t *pSW,rt_uint8_t *enable) -//{ -// struct test *pTest = &pSW->sink.test; -// switch (pTest->stop_step) -// { -// case TEST_STOP_CMD_MODE: // 下发停止指令,关闭动态测试运行模式 -// chrg_set_sou_reg((eIDX_SOU_CH)idx, ModbusRTU_DYNA_CMD_MODE_FLAG , ModbusRTU_DYNA_CMD_MODE_STOP); -// pSW->change_flag = 0; -// pSW->sink.test.test_mode = 0; // 清空动态测试标记 -// pSW->sub = 21; // IDX_SET_SINK_WORK_STATE; -// break; -// default: -// break; -// } -//} - -//sink开机初始化 +/***************************************************************** +函数名称: chrg_sink_work_init +函数描述: 执行负载INIT状态,复位测试配置并初始化功率板 +输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体 +输出参数: 设置运行、使能、在线标志并更新work_mode +返回说明: 0:初始化成功 <0:命令提交失败 +其它说明: 成功后打开负载北向继电器并进入SINK_WORK_WAIT +*****************************************************************/ static int chrg_sink_work_init(eIDX_SOU_CH idx, struct chrg_switch_t *pSW) { struct chrg_south_t *pSOU = &chrgsouth; @@ -477,7 +169,14 @@ static int chrg_sink_work_init(eIDX_SOU_CH idx, struct chrg_switch_t *pSW) return 0; } -//sink进入运行状态 +/***************************************************************** +函数名称: chrg_sink_work_volt_runing +函数描述: 执行负载RUNING状态,闭合功率继电器并启动负载 +输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体 +输出参数: - +返回说明: 0:命令提交成功 非0:命令提交失败 +其它说明: CV模式下写负载电压,其他模式下写负载电流 +*****************************************************************/ 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}; @@ -493,7 +192,14 @@ static int chrg_sink_work_volt_runing(eIDX_SOU_CH idx, struct chrg_switch_t *pSW return chrg_sou_com_batch_submit(idx, regs, vals, 4); } -//sink进入低电压状态 +/***************************************************************** +函数名称: chrg_sink_nor_work_low +函数描述: 执行负载低电压状态,断开功率继电器并停止负载 +输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体 +输出参数: - +返回说明: 0:命令提交成功 非0:命令提交失败 +其它说明: 由北向负载解析连续检测到低电压后触发 +*****************************************************************/ static int chrg_sink_nor_work_low(eIDX_SOU_CH idx, struct chrg_switch_t *pSW) { rt_uint16_t regs[2] = {0x01, REG_WORK}; @@ -502,7 +208,14 @@ static int chrg_sink_nor_work_low(eIDX_SOU_CH idx, struct chrg_switch_t *pSW) return chrg_sou_com_batch_submit(idx, regs, vals, 2); } -//com端关机流程 +/***************************************************************** +函数名称: chrg_sink_nor_work_off +函数描述: 执行负载主动关机流程 +输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体 +输出参数: 清除运行、使能和在线标志,关闭北向继电器 +返回说明: 0:关机成功 <0:停止命令提交失败 +其它说明: 先断开功率继电器并发送WORK_STOP,再关闭软件通道 +*****************************************************************/ static int chrg_sink_nor_work_off(eIDX_SOU_CH idx, struct chrg_switch_t *pSW) { struct chrg_south_t *pSOU = &chrgsouth; @@ -523,7 +236,15 @@ static int chrg_sink_nor_work_off(eIDX_SOU_CH idx, struct chrg_switch_t *pSW) return 0; } -// 切换进入负载:停止旧电源后,从负载初始化状态开始运行 +/***************************************************************** +函数名称: chrg_sink_work_switch +函数描述: 处理“电源切换到负载”的过渡状态 +输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体 +输出参数: 清除旧电源运行标志,设置负载北向入口和INIT状态 +返回说明: 0:停止命令成功加入队列 非0:命令入队失败 +其它说明: pSW->id已由COM更新为ID_SINK;先提交旧电源WORK_STOP, + 后续负载INIT使用同一通道队列,保证停止命令先执行 +*****************************************************************/ static int chrg_sink_work_switch(eIDX_SOU_CH idx, struct chrg_switch_t *pSW) { rt_uint16_t reg = REG_WORK; @@ -535,13 +256,23 @@ static int chrg_sink_work_switch(eIDX_SOU_CH idx, struct chrg_switch_t *pSW) return ret; } + /* 停止成功入队后,清除旧Source运行标志。 */ pSW->source.On_Flag = 0; + /* 首次进入Sink时必须从CC线配置开始,不能沿用Source的sub状态。 */ pSW->sub = IDX_SET_SINK_CCLINE; + /* SWITCH只负责旧角色退出,后续启动统一交给Sink INIT状态。 */ pSW->sink.work_mode = SINK_WORK_INIT; return 0; } -//动态测试启动 +/***************************************************************** +函数名称: chrg_sink_TEST_DYNA_ON +函数描述: 配置并启动动态负载测试 +输入参数: ch:南向功率通道编号 pSW:当前通道控制结构体 +输出参数: - +返回说明: 0:命令提交成功 非0:命令提交失败 +其它说明: 一次提交两组负载、保持时间、斜率、测试命令和WORK_START +*****************************************************************/ static int chrg_sink_TEST_DYNA_ON(rt_uint8_t ch, struct chrg_switch_t *pSW) { struct test *pTest = &pSW->sink.test; @@ -561,7 +292,14 @@ static int chrg_sink_TEST_DYNA_ON(rt_uint8_t ch, struct chrg_switch_t *pSW) return chrg_sou_com_batch_submit((eIDX_SOU_CH)ch, regs, vals, 8); } -//短路测试启动 +/***************************************************************** +函数名称: chrg_sink_TEST_SHORT_ON +函数描述: 配置并启动负载短路测试 +输入参数: ch:南向功率通道编号 pSW:当前通道控制结构体 +输出参数: - +返回说明: 0:命令提交成功 非0:命令提交失败 +其它说明: 根据set_mode选择定时无载或持续保持模式 +*****************************************************************/ static int chrg_sink_TEST_SHORT_ON(rt_uint8_t ch, struct chrg_switch_t *pSW) { rt_uint16_t regs[3] = {ModbusRTU_ShortTest_Hold_Time,ModbusRTU_ShortTest_CMD_MODE_FLAG, REG_WORK}; @@ -579,7 +317,14 @@ static int chrg_sink_TEST_SHORT_ON(rt_uint8_t ch, struct chrg_switch_t *pSW) } -//负载工作 +/***************************************************************** +函数名称: chrg_sink_work +函数描述: 负载工作状态机统一入口 +输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体 +输出参数: 根据sink.work_mode执行对应状态动作 +返回说明: 0:状态处理成功 <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}; diff --git a/apps/chrg/applications/utils/chrg_source.c b/apps/chrg/applications/utils/chrg_source.c index 5fb3706..c437f8c 100644 --- a/apps/chrg/applications/utils/chrg_source.c +++ b/apps/chrg/applications/utils/chrg_source.c @@ -17,6 +17,14 @@ #include "chrg_roll_sou.h" #include "chrg_rel.h" +/***************************************************************** +函数名称: chrg_source_init_submit +函数描述: 将电源模式初始化参数批量提交到南向功率板命令队列 +输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体 +输出参数: - +返回说明: 0:提交成功 <0:参数错误或队列提交失败 +其它说明: 命令顺序为源载模式、CV/CC模式、继电器、初始电压、保护电流、启动 +*****************************************************************/ int chrg_source_init_submit(rt_uint8_t idx, struct chrg_switch_t *pSW) { /* Source启动参数一次入队,最后发送WORK_START使功率板开始输出。 */ @@ -43,6 +51,14 @@ int chrg_source_init_submit(rt_uint8_t idx, struct chrg_switch_t *pSW) return chrg_sou_com_batch_submit(idx, regs, vals, 6); } +/***************************************************************** +函数名称: chrg_source_work_init +函数描述: 执行电源INIT状态,初始化功率板并打开对应北向通道 +输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体 +输出参数: 更新电源运行标志、通道使能、在线状态及work_mode +返回说明: 0:初始化命令提交成功 非0:初始化失败 +其它说明: 成功后状态切换为SOURCE_WORK_WAIT,等待北向返回协商电压 +*****************************************************************/ static int chrg_source_work_init(eIDX_SOU_CH idx, struct chrg_switch_t *pSW) { struct chrg_south_t *pSOU = &chrgsouth; @@ -64,12 +80,28 @@ static int chrg_source_work_init(eIDX_SOU_CH idx, struct chrg_switch_t *pSW) return 0; } +/***************************************************************** +函数名称: chrg_source_work_wait +函数描述: 执行电源WAIT状态 +输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体 +输出参数: - +返回说明: 0:状态处理完成 +其它说明: WAIT状态不下发命令,由北向解析函数判断目标电压是否变化 +*****************************************************************/ static int chrg_source_work_wait(eIDX_SOU_CH idx, struct chrg_switch_t *pSW) { /* WAIT状态不产生南向命令,等待下一帧北向电压数据。 */ return 0; } +/***************************************************************** +函数名称: chrg_source_work_running +函数描述: 执行电源RUNING状态,下发最新协商目标电压 +输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体 +输出参数: - +返回说明: 0:命令提交成功 非0:命令提交失败 +其它说明: 本状态只写电压寄存器,不重复发送WORK_START +*****************************************************************/ static int chrg_source_work_running(eIDX_SOU_CH idx, struct chrg_switch_t *pSW) { /* RUNING只下发协商后的目标电压,不重复发送启动命令。 */ @@ -79,6 +111,14 @@ static int chrg_source_work_running(eIDX_SOU_CH idx, struct chrg_switch_t *pSW) return chrg_sou_com_batch_submit(idx, ®, &value, 1); } +/***************************************************************** +函数名称: chrg_source_work_low +函数描述: 执行电源低电压异常状态,停止功率板输出 +输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体 +输出参数: - +返回说明: 0:停止命令提交成功 非0:命令提交失败 +其它说明: 本函数只发送WORK_STOP,不关闭通道使能和北向继电器 +*****************************************************************/ static int chrg_source_work_low(eIDX_SOU_CH idx, struct chrg_switch_t *pSW) { /* 电压异常时先停止功率板输出,保留状态供上层判断。 */ @@ -88,6 +128,14 @@ static int chrg_source_work_low(eIDX_SOU_CH idx, struct chrg_switch_t *pSW) return chrg_sou_com_batch_submit(idx, ®, &value, 1); } +/***************************************************************** +函数名称: chrg_source_work_stop +函数描述: 执行电源主动关机流程 +输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体 +输出参数: 清除运行、使能和在线标志,关闭北向继电器 +返回说明: 0:停止成功 非0:停止命令提交失败 +其它说明: 成功后状态恢复为SOURCE_WORK_WAIT,等待下一次启动命令 +*****************************************************************/ static int chrg_source_work_stop(eIDX_SOU_CH idx, struct chrg_switch_t *pSW) { struct chrg_south_t *pSOU = &chrgsouth; @@ -112,7 +160,15 @@ static int chrg_source_work_stop(eIDX_SOU_CH idx, struct chrg_switch_t *pSW) return 0; } -// 切换进入电源:关闭旧负载继电器并停止输出,然后进入电源初始化 +/***************************************************************** +函数名称: chrg_source_work_switch +函数描述: 处理“负载切换到电源”的过渡状态 +输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体 +输出参数: 清除旧负载运行标志,设置电源北向入口和INIT状态 +返回说明: 0:停止命令成功加入队列 非0:命令入队失败 +其它说明: pSW->id已由COM更新为ID_SOURCE;先关闭旧负载继电器并提交 + WORK_STOP,后续电源INIT使用同一通道队列,保证停止命令先执行 +*****************************************************************/ static int chrg_source_work_switch(eIDX_SOU_CH idx, struct chrg_switch_t *pSW) { rt_uint16_t regs[2] = {REG_REL_ON, REG_WORK}; @@ -124,12 +180,23 @@ static int chrg_source_work_switch(eIDX_SOU_CH idx, struct chrg_switch_t *pSW) return ret; } + /* 停止成功入队后,清除旧Sink运行标志。 */ pSW->sink.On_work = 0; + /* 首次进入Source时必须从CC线配置开始,不能沿用Sink的sub状态。 */ pSW->sub = IDX_SET_SOURCE_CC_SET; + /* SWITCH只负责旧角色退出,后续启动统一交给Source INIT状态。 */ pSW->source.work_mode = SOURCE_WORK_INIT; return 0; } +/***************************************************************** +函数名称: chrg_source_work_state +函数描述: 电源工作状态机统一入口 +输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体 +输出参数: 根据source.work_mode执行对应状态动作 +返回说明: 0:状态处理成功 <0:参数、状态或命令提交失败 +其它说明: 支持INIT、WAIT、RUNING、LOW、STOP和SWITCH状态 +*****************************************************************/ int chrg_source_work_state(rt_uint8_t idx, struct chrg_switch_t *pSW) { if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {