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: 删除大量废弃测试代码,为所有负载状态机函数补充详细中文注释与函数说明
378 lines
13 KiB
C
378 lines
13 KiB
C
/****************************************************************************
|
||
文件名称 : 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, ®, &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;
|
||
}
|
||
|
||
|
||
|