Files
chrg/apps/chrg/applications/utils/chrg_sink.c
T
wrh 587e03b65f refactor(chrg): 重构北向轮询与状态机代码,补充注释与函数文档
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: 删除大量废弃测试代码,为所有负载状态机函数补充详细中文注释与函数说明
2026-07-22 10:14:48 +08:00

378 lines
13 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/****************************************************************************
文件名称 : chrg_sink.c
完成日期 :
当前版本号 : V1.0
主要功能 : 北向数据sink请求数据填充及发送。
版本历史 : 创建原始版本
说明 :
******************************************************************************/
#include <rtthread.h>
#include "chrg_sink.h"
#include "chrg_north.h"
#include "chrg_north_pkg.h"
#include "chrg_utils.h"
#include "chrg_roll_sou.h"
#include "chrg_roll_nor.h"
#include "chrg_def.h"
#include "chrg_rel.h"
#include "chrg_comm.h"
/*****************************************************************
函数名称: sink_get_vc
函数描述: sink电压电流查询请求
输入参数: vol:电压 cur:电流
输出参数: -
返回说明: <0: 错误 >0:发送长度
其它说明: -
*****************************************************************/
int sink_get_vc (rt_uint16_t vol, rt_uint16_t cur)
{
rt_uint16_t len = 0;
rt_uint8_t data[12] = {0};
rt_uint8_t frame[16] = {0};
u16_to_u8v(vol, &data[0]);
u16_to_u8v(cur, &data[2]);
data[4] = 0x00;
data[5] = 0x00;
chrg_north_pkg_encode(ID_SINK, SINK_CMD_GET_VOLTAGE, data, 6, frame, &len);
return chrg_north_send(frame, len);
}
/*****************************************************************
函数名称: sink_get_pd
函数描述: sink pd 协议查询请求
输入参数: -
输出参数: -
返回说明: <0: 错误 >0:发送长度
其它说明: -
*****************************************************************/
int sink_get_pd (void)
{
rt_uint16_t len = 0;
rt_uint8_t frame[16] = {0};
chrg_north_pkg_encode(ID_SINK, SINK_CMD_GET_PD, RT_NULL, 0, frame, &len);
return chrg_north_send(frame, len);
}
/*****************************************************************
函数名称: sink_set_cc_line
函数描述: sink 设置 cc 线
输入参数: line:线
输出参数: -
返回说明: <0: 错误 >0:发送长度
其它说明: -
*****************************************************************/
int sink_set_cc_line (rt_uint8_t line)
{
rt_uint16_t len = 0;
rt_uint8_t data[8] = {0};
rt_uint8_t frame[16] = {0};
data[0] = line;
chrg_north_pkg_encode(ID_SINK, SINK_CMD_SET_CC, data, 1, frame, &len);
// for(int i = 0; i < len; i++) {
// rt_kprintf("data[%d]=%02x\r\n", i, frame[i]);
// }
return chrg_north_send(frame, len);
}
/*****************************************************************
函数名称: sink_set_cc_lvl
函数描述: sink 设置 cc 等级
输入参数: lvl:等级
输出参数: -
返回说明: <0: 错误 >0:发送长度
其它说明: -
*****************************************************************/
int sink_set_cc_lvl (rt_uint8_t lvl)
{
rt_uint16_t len = 0;
rt_uint8_t data[8] = {0};
rt_uint8_t frame[16] = {0};
data[0] = lvl;
chrg_north_pkg_encode(ID_SINK, SINK_CMD_SET_LEVEL, data, 1, frame, &len);
return chrg_north_send(frame, len);
}
/*****************************************************************
函数名称: sink_set_pd
函数描述: sink 设置 PD 协议
输入参数: pd:协议命令号 *buf:协议数据,5字节
输出参数: -
返回说明: <0: 错误 >0:发送长度
其它说明: -
*****************************************************************/
int sink_set_pd (rt_uint8_t pd, rt_uint8_t *buf)
{
rt_uint16_t len = 0;
rt_uint8_t data[8] = {0};
rt_uint8_t frame[16] = {0};
int i = 0;
for (i = 0; i < 5; i++) {
data[i] = buf[i];
}
chrg_north_pkg_encode(ID_SINK, pd, data, 5, frame, &len);
return chrg_north_send(frame, len);
}
/*****************************************************************
函数名称: 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;
struct chrg_north_t *pNOR = &chrgnorth;
rt_uint16_t regs[5] = {REG_CURRENT_OUT + 1, REG_MODE,Eload_Start_V_ON,0, 0};
rt_uint16_t vals[5] = {0, pSW->CV_mode,pSW->sink.volt_on, 0, 0};
rt_uint8_t count = 3;
if (pSW->sink.test.test_mode_old == 1) {
regs[count] = ModbusRTU_ShortTest_CMD_MODE_FLAG;
vals[count++] = ModbusRTU_DYNA_CMD_MODE_STOP;
} else if (pSW->sink.test.test_mode_old == 3) {
regs[count] = ModbusRTU_DYNA_CMD_MODE_FLAG;
vals[count++] = ModbusRTU_DYNA_CMD_MODE_STOP;
}
/* Close both power-board relays before starting sink init. */
regs[count] = REG_REL_ON;
vals[count++] = ALL_REL_OFF;
if (chrg_sou_com_batch_submit(idx, regs, vals, count) != 0) {
return -1;
}
pSW->sink.On_work = 1;
pSOU->enable[idx] = 1;
pSOU->online[idx] = 1;
pNOR->enable[idx] = 1;
chrg_nor_sw_rel((eIDX_NOR_CH)idx, ID_SINK); //打开北向继电器
pSW->sink.test.test_mode_old = 0;
pSW->sink.work_mode = SINK_WORK_WAIT;
return 0;
}
/*****************************************************************
函数名称: 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};
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_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};
rt_uint16_t vals[2] = {0x00, WORK_STOP};
return chrg_sou_com_batch_submit(idx, regs, vals, 2);
}
/*****************************************************************
函数名称: 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;
struct chrg_north_t *pNOR = &chrgnorth;
rt_uint16_t regs[2] = {0x01, REG_WORK};
rt_uint16_t vals[2] = {0x00, WORK_STOP};
if (chrg_sou_com_batch_submit(idx, regs, vals, 2) != 0) {
return -1;
}
pSW->sink.On_work = 0;
pSOU->enable[idx] = 0;
pSOU->online[idx] = 0;
pNOR->enable[idx] = 0;
chrg_nor_sw_rel((eIDX_NOR_CH)idx, 0); //关闭北向继电器
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;
rt_uint16_t value = WORK_STOP;
int ret;
ret = chrg_sou_com_batch_submit(idx, &reg, &value, 1);
if (ret != 0) {
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;
rt_uint16_t regs[8] = {REG_REL_ON, REG_REL_ON,
ModbusRTU_DYNA_L1, ModbusRTU_DYNA_T1, ModbusRTU_DYNA_L2,
ModbusRTU_DYNA_T2, ModbusRTU_DYNA_CMD_MODE_FLAG, REG_WORK};
rt_uint16_t vals[8] = {0x02, 0x03,
pTest->change_test.curr1_set, pTest->change_test.time1_set,
pTest->change_test.curr2_set, pTest->change_test.time2_set,
ModbusRTU_DYNA_CMD_MODE_RUN, WORK_START};
/*
* 动态测试可能在普通 RUNING 状态打开功率板继电器之前进入。
* 因此动态启动流程必须自行打开两路继电器,避免快速从 PD 设置
* 切换到动态测试时,负载已经启动但功率板继电器仍处于关闭状态。
*/
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};
rt_uint16_t vals[3] = {0,0,0};
if(pSW->sink.test.short_test.set_mode == 0)
{
vals[0] = pSW->sink.test.short_test.hold_time;
vals[1] = ModbusRTU_DYNA_CMD_MODE_RUN_NO_CURR;
}
else{
vals[1] = ModbusRTU_DYNA_CMD_MODE_RUN_ALWAYS_KEPP;
}
vals[2] = WORK_START;
return chrg_sou_com_batch_submit((eIDX_SOU_CH)ch, regs, vals, 3);
}
/*****************************************************************
函数名称: 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};
rt_uint8_t work_mode;
int ret = -1;
if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
return -1;
}
work_mode = pSW->sink.work_mode;
// 本次状态和上次一致,直接跳过,不重复下发寄存器
if (work_mode == last_state[idx]) {
return 0;
}
switch(work_mode){
case SINK_WORK_INIT:
ret = chrg_sink_work_init(idx,pSW);
break;
case SINK_WORK_WAIT:
ret = 0;
break;
case SINK_WORK_RUNING:
ret = chrg_sink_work_volt_runing(idx,pSW);
break;
case SINK_WORK_ON_TEST_DYNA:
ret = chrg_sink_TEST_DYNA_ON(idx,pSW);
break;
case SINK_WORK_ON_TEST_SHORT:
ret = chrg_sink_TEST_SHORT_ON(idx,pSW);
break;
case SINK_WORK_LOW:
ret = chrg_sink_nor_work_low(idx,pSW);
break;
case SINK_WORK_STOP:
ret = chrg_sink_nor_work_off(idx,pSW);
break;
case SINK_WORK_SWITCH:
ret = chrg_sink_work_switch(idx,pSW);
break;
default:
break;
}
if (ret == 0) {
last_state[idx] = work_mode;
}
return ret;
}