refactor: 重构电源通道控制逻辑,引入状态机管理

1. 删除apps/chrg/applications/thread/chrg_lcd.h中的chrg_sou_work函数声明
2. 移除chrg_source.h中冗余的状态标志定义,新增电源工作状态机枚举
3. 重构chrg_lcd.c,删除旧的启动/停止流程代码和冗余标志位操作
4. 重写chrg_roll_nor.c的协议设置和通道控制逻辑,替换为状态机处理
5. 重写chrg_source.c,新增统一的电源工作状态机实现,替换旧的协议设置函数
6. 重构chrg_north.c的电源解析逻辑,移除旧的停止流程和冗余标志位
7. 简化chrg_comm.c的Modbus协议处理逻辑,改为通过状态机控制电源通道
This commit is contained in:
wrh
2026-07-21 20:56:36 +08:00
parent a6621a304a
commit 660aaa5a7a
7 changed files with 160 additions and 595 deletions
+6 -376
View File
@@ -1022,378 +1022,6 @@ eMBException funcWriteMultipleCoils (rt_uint8_t *reqFrame, rt_uint16_t reqLen,
return eStatus;
}
static void parse_load_no_group(rt_uint8_t protoCmd, rt_uint8_t *pData, rt_uint16_t reqLen, struct chrg_switch_t *pSW)
{
rt_uint16_t volt_mv = 0; // 协议请求电压(mV)
rt_uint16_t curr_ma = 0; // 负载电流(mA)
// 数据区索引:0=状态+通道,1=CC线,2,选择恒压恒流模式3-4=电压,5-6=电流,6-7=保留
volt_mv = u8v_to_u16(&pData[3]); // 电压(mV,大端)
curr_ma = u8v_to_u16(&pData[5]); // 电流(mA,大端)
// 按协议命令码赋值
switch (protoCmd)
{
case 0x11: // QC2.0
pSW->sink.protocol = LOAD_PRO_QC20;
break;
case 0x12: // QC3.0
pSW->sink.protocol = LOAD_PRO_QC30;
break;
case 0x13: // FCP
pSW->sink.protocol = LOAD_PRO_FCP;
break;
case 0x14: // AFC
pSW->sink.protocol = LOAD_PRO_AFC;
break;
case 0x15: // SCP
pSW->sink.protocol = LOAD_PRO_SCP;
break;
case 0x16: // VIVO
pSW->sink.protocol = LOAD_PRO_VIVO;
break;
case 0x17: // TFC
pSW->sink.protocol = LOAD_PRO_TFC_RFC;
break;
default:
rt_kprintf("无组号负载协议不支持:0x%02X\n", protoCmd);
return;
}
// 赋值通用参数
pSW->sink.loadv = volt_mv;
pSW->sink.loadc = curr_ma;
pSW->sink.Pro_Group = 0; // 无组号
rt_kprintf("pro=%d,volt_mv=%d,curr=%d",pSW->sink.protocol,volt_mv,curr_ma);
}
static void parse_load_with_group(rt_uint8_t protoCmd, rt_uint8_t *pData, rt_uint16_t reqLen, struct chrg_switch_t *pSW)
{
rt_uint8_t group_num = 0; // 组号
rt_uint16_t volt_mv = 0; // 协议请求电压(mV)
rt_uint16_t curr_ma = 0; // 负载电流(mA)
// 数据区索引:0=状态+通道,1=CC线,2=恒压恒流模式,3=组号
group_num = pData[3];
pSW->sink.Pro_Group = group_num;
// 按协议命令码分支
switch (protoCmd)
{
case CMD_LOAD_PD0_MAN: // PD0(手动)
pSW->sink.protocol = LOAD_PRO_PDO_MANUAL;
// PD0特殊:组号后为3个保留2字节,无电压电流
volt_mv = 0;
curr_ma = 0;
break;
case CMD_LOAD_PD0_AUTO: // PDO自动
pSW->sink.protocol = LOAD_PRO_PDO_AUTO;
volt_mv = u8v_to_u16(&pData[4]); // 4-5=电压
curr_ma = u8v_to_u16(&pData[6]); // 6-7=电流
break;
case CMD_LOAD_PPS_MAN: // PPS(手动)
pSW->sink.protocol = LOAD_PRO_PPS_MANUAL;
volt_mv = u8v_to_u16(&pData[4]);
curr_ma = u8v_to_u16(&pData[6]);
break;
case CMD_LOAD_PPS_AUTO: // PPS(自动)
pSW->sink.protocol = LOAD_PRO_PPS_AUTO;
volt_mv = u8v_to_u16(&pData[4]);
curr_ma = u8v_to_u16(&pData[6]);
break;
case CMD_LOAD_PD31: // PD3.1
pSW->sink.protocol = LOAD_PRO_PD31AVS;
volt_mv = u8v_to_u16(&pData[4]);
curr_ma = u8v_to_u16(&pData[6]);
break;
case CMD_LOAD_UFCS: // UFCS
pSW->sink.protocol = LOAD_PRO_UFCS;
volt_mv = u8v_to_u16(&pData[4]);
curr_ma = u8v_to_u16(&pData[6]);
break;
case CMD_LOAD_VOOC: // VOOC
pSW->sink.protocol = LOAD_PRO_VOOC;
volt_mv = 0;
curr_ma = 0;
break;
case CMD_LOAD_AVS: // AVS
pSW->sink.protocol = LOAD_PRO_AVS;
volt_mv = u8v_to_u16(&pData[4]);
curr_ma = u8v_to_u16(&pData[6]);
break;
default:
rt_kprintf("有组号负载协议不支持:0x%02X\n", protoCmd);
return;
}
rt_kprintf("volt_mv=%d,curr_ma=%d\n",volt_mv,curr_ma);
// 赋值通用参数
pSW->sink.loadv = volt_mv;
pSW->sink.loadc = curr_ma;
}
// //sink开机函数
// rt_uint8_t chrg_com_sink_on(rt_uint8_t ch, struct chrg_switch_t *pSW, rt_uint8_t *enable){
// *enable = 1;
// pSW->id = ID_SINK;
// pSW->sub = IDX_SET_SINK_CURR;
// pSW->change_flag = 0x01;
// pSW->sink.work_on_step = 0;
// return 0;
// }
//source开机函数
rt_uint8_t chrg_com_source_on(rt_uint8_t ch, rt_uint8_t protoCmd, struct chrg_switch_t *pSW, rt_uint8_t *enable){
*enable = 1;
pSW->id = ID_SOURCE;
pSW->source.LCD_Set_Pro_Flag=3;
pSW->sub = IDX_SET_SOURCE_ID;
pSW->change_flag = 0x01;
pSW->continue_flag = 1;
return 0;
}
/*****************************************************************
函数名称: funcWriteProtoCal
函数描述: 写入协议
输入参数: reqFrame: 请求数据 reqLen: 请求长度 resFrame:响应数据 resLen:响应长度
输出参数: -
返回说明: -
其它说明: -
*****************************************************************/
eMBException funcWriteProtoCal (rt_uint8_t *reqFrame, rt_uint16_t reqLen,
rt_uint8_t *resFrame, rt_uint16_t *resLen)
{
/************ 局部变量定义 ************/
struct chrg_north_t *pNOR = &chrgnorth;
struct chrg_south_t *pSOU = &chrgsouth;
struct chrg_switch_t *pSW = RT_NULL;
rt_uint8_t slaveAddr = 0; // 从机地址(0x01~0xFF)
rt_uint8_t protoCmd = 0; // 协议命令码(0x11~0x1F/0x22~0x2C/0x2F)
rt_uint16_t regAddress = 0; // 寄存器起始地址
rt_uint8_t *pData = RT_NULL; // 协议数据区起始指针(状态+通道字段开始)
rt_uint8_t statusChByte = 0;// 状态+通道字节(reqFrame[5])
eIDX_SOU_CH ch = IDX_SOU_CH1;// 通道号(1~4)
rt_uint8_t chNum = 0; // 通道号数值(1~4)
rt_uint8_t devStatus = 0; // 设备状态(0=不变,1=开机,2=关机)
rt_uint8_t ccSel = 0; // CC线选择(0=CC1+CC2,1=CC1,2=CC2,3=断开)
// *g_proto_pData = RT_NULL;
g_proto_reqLen = 0;
// Modbus异常码
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
rt_uint16_t reg_offset = 0;
rt_uint16_t sout_reg = 0;
rt_uint16_t sou_value = 0;
/************ 校验 ************/
// 最小帧长度:地址(1)+命令码(1)+寄存器(2)+数据区(至少1)+校验(2) = 7字节
if (reqLen < 7) {
rt_kprintf("The long error%d must more 7\n", reqLen);
return MB_EX_ILLEGAL_DATA_VALUE;
}
/************ 解析帧 ************/
slaveAddr = reqFrame[0]; // 从机地址(0x01~0xFF)
protoCmd = reqFrame[3]; // 协议命令码(负载0x11~0x1F,电源0x22~0x2C/0x2F)
rt_kprintf("pro=%04x\n",protoCmd);
pData = &reqFrame[4]; // 数据区起始(跳过地址+命令码+寄存器)
statusChByte = pData[0]; // 状态+通道字节(数据区第1字节)
/************ 地址校验 ************/
if (protoCmd < PRO_REG_START || protoCmd >= TOTAL_PROTOCAL_CNT) {
rt_kprintf("Address error0x%04X\n", protoCmd);
return MB_EX_ILLEGAL_DATA_ADDRESS;
}
/************ 提取通道号和状态 ************/
// bit0-3:状态(0=不变,1=开机,2=关机)
devStatus = statusChByte & 0x0F;
rt_kprintf("status=%d",devStatus);
// bit4-7:通道号(1=CH1,2=CH2,3=CH3,4=CH4)
chNum = (statusChByte >> 4) & 0x0F;
ccSel = pData[1];
rt_uint8_t cv_mode = pData[2];
// 通道号合法性校验
if (chNum < 1 || chNum > 4) {
rt_kprintf("通道号非法:%d(仅支持1~4\n", chNum);
return MB_EX_ILLEGAL_DATA_ADDRESS;
}
ch = (eIDX_SOU_CH)(chNum - 1); // 转换为枚举类型(IDX_SOU_CH1=0)
/************ 硬件结构体绑定 ************/
if (pNOR == RT_NULL) {
rt_kprintf("ERROR: pNOR is NULL!\n");
return MB_EX_SLAVE_DEVICE_FAILURE;
}
pSW = &pNOR->sw[ch]; // 绑定当前通道的协议配置结构体
pSW->protoCmd = protoCmd; //com端协议命令码
pSW->CV_mode = cv_mode; //恒压恒流模式选择
rt_memcpy(g_proto_pData, pData, reqLen - 4);
g_proto_reqLen = reqLen;
rt_kprintf("com_recitive\n");
/************ 按「负载/电源」分支解析 ************/
// ========== 负载协议解析 (0x11~0x1F) ==========
if (protoCmd >= 0x11 && protoCmd <= 0x1F) {
pSW->sink.cc_set = ccSel; //负载CC线选择
if(pSW->source.On_Flag){ //负载切电源
pSW->source.change_sink_Flag = 1;
chrg_sou_stop(ch,pSW,pNOR);
}else{
if(devStatus==2){ //负载关机
chrg_sou_stop(ch,pSW,pNOR);
}
else if(devStatus==1){ //负载开机
//chrg_com_sink_on(ch,pSW,&pNOR->enable[ch]);
}
}
}
// ==========电源协议解析 (0x22~0x2C/0x2F) ==========
else if ((protoCmd >= 0x22 && protoCmd <= 0x2C) || protoCmd == 0x2F) {
pSW->source.cc_set = ccSel; //电源CC线选择
if(pSW->sink.On_work){ //电源切负载
pSW->sink.change_source_flag = 1;
chrg_sou_stop(ch,pSW,pNOR);
}else{
if(devStatus==2){ //电源关机
chrg_sou_stop(ch,pSW,pNOR);
}else if(devStatus==1){ //电源开机
chrg_com_source_on(ch,pSW->protoCmd,pSW,&pNOR->enable[ch]);
}
}
}
// ========== 非法命令码 ==========
else {
rt_kprintf("非法协议命令码:0x%02X\n", protoCmd);
return MB_EX_ILLEGAL_FUNCTION;
}
// /************ 配置参数写入保持寄存器 ************/
eRegStatus = mb_reg_holding_cb(&reqFrame[4], &resFrame[3], regAddress, 1, MB_REG_WRITE);
if (eRegStatus != MB_ENOERR) {
eStatus = mb_error(eRegStatus);
rt_kprintf("寄存器写入失败:%d\n", eRegStatus);
}
/************ 构建响应帧 ************/
rt_memcpy(resFrame, reqFrame, reqLen);
*resLen = reqLen - 2; // 去掉CRC校验位
/************ 调试输出 ************/
// rt_kprintf("Pro Set OK:Ch=%d,Pro0x%02X,Status%d,CC Set%d\n",
// chNum, protoCmd, devStatus, ccSel);
return eStatus;
}
/*****************************************************************
函数名称: funcSinkTest
函数描述: 负载测试
输入参数: reqFrame: 请求数据 reqLen: 请求长度 resFrame:响应数据 resLen:响应长度
输出参数: -
返回说明: -
其它说明: -
*****************************************************************/
eMBException funcSinkTest (rt_uint8_t *reqFrame, rt_uint16_t reqLen,
rt_uint8_t *resFrame, rt_uint16_t *resLen)
{
/************ 局部变量定义 ************/
struct chrg_north_t *pNOR = &chrgnorth;
struct chrg_south_t *pSOU = &chrgsouth;
struct chrg_switch_t *pSW = RT_NULL;
rt_uint8_t slaveAddr = 0; // 从机地址
rt_uint8_t test_mode = 0; // 测试模式 0x01/0x02/0x03
rt_uint16_t regAddress = 0; // 寄存器地址
rt_uint8_t *pData = RT_NULL; // 数据区指针
rt_uint8_t statusChByte = 0; // 状态+通道字节
eIDX_SOU_CH ch = IDX_SOU_CH1; // 通道枚举
rt_uint8_t chNum = 0; // 通道号 1~4
rt_uint8_t devStatus = 0; // 设备状态 0=启动 1=停止,2=继续,3=结束
// Modbus异常
eMBException eStatus = MB_EX_NONE;
eMBErrorCode eRegStatus;
// /************ 长度校验 ************/
// if (reqLen < 11) {
// rt_kprintf("Len error:%d <11\n", reqLen);
// return MB_EX_ILLEGAL_DATA_VALUE;
// }
/************ 解析帧 ************/
slaveAddr = reqFrame[0];
test_mode = reqFrame[3]; // 测试命令:0x01短路 0x02OCP 0x03动态
pData = &reqFrame[4]; // 数据起始
statusChByte= pData[0]; // 状态通道字节
/************ 地址校验 ************/
if (test_mode < 0x01 || test_mode > 0x03) {
rt_kprintf("Test mode err:0x%02X\n", test_mode);
return MB_EX_ILLEGAL_DATA_ADDRESS;
}
/************ 解析状态 & 通道 ************/
devStatus = statusChByte & 0x0F; // 低4位:状态
chNum = (statusChByte >> 4) & 0x0F; // 高4位:通道
/************ 通道校验 ************/
if (chNum <1 || chNum>4) {
rt_kprintf("Ch err:%d\n", chNum);
return MB_EX_ILLEGAL_DATA_ADDRESS;
}
ch = (eIDX_SOU_CH)(chNum -1);
/************ 绑定结构体 ************/
pSW = &pNOR->sw[ch];
pSW->sink.test.test_mode = test_mode; //测试模式
pSW->sink.test.run_flag = devStatus; //设备状态
pSW->change_flag = 0x01;
struct test *pTset = &pSW->sink.test;
#if SINK_TEST_DEBUG
rt_kprintf("test_mode=%d\n",test_mode);
rt_kprintf("test_flag=%d\n",pTset->test_mode);
#endif
/*********************************************************/
// switch(test_mode)
// {
// case 0x01:
// // 短路测试(OCPC
// sink_test_short_set(pSW, pData, devStatus);
// break;
// case 0x02:
// // OCP 测试
// sink_test_ocp_set(pSW, pData, devStatus);
// break;
// case 0x03:
// // 动态测试
// sink_test_dynamic_set(pSW, pData, devStatus);
// break;
// default:
// return MB_EX_ILLEGAL_FUNCTION;
// }
/************ 启动 / 停止控制 ************/
if(devStatus == 0) //启动
{
pNOR->enable[ch] = 1;
pSW->id = ID_SINK;
pSW->sink.test.work_step = 0;
pSOU->online[ch] = 1;
}
else if(devStatus == 1) //停止
{
pSW->id = ID_SINK;
pSW->sink.test.stop_step = 0;
rt_kprintf("Sink Test Stop CH%d\n", chNum);
}
/************ 响应帧 ************/
rt_memcpy(resFrame, reqFrame, reqLen-2);
*resLen = reqLen -2;
return eStatus;
}
/*****************************************************************
函数名称: funcWriteMultipleHoldingRegister
函数描述: 写多个保持寄存器(0x10)
@@ -2170,7 +1798,6 @@ static void chrg_mb_write_src(rt_uint8_t ch, rt_uint16_t reg_offset, rt_uint16_t
{
case SRC_REG_PROTOCOL: // 0x00: 协议
pSW->source.protocol = src_proto_lookup(sou_value);
pSW->source.Set_Pro_Flag = 1;
pSW->protoCmd = (rt_uint8_t)sou_value;
// rt_kprintf("[SRC CH%d] Protocol=0x%02X -> 0x%02X\n", ch + 1, sou_value, pSW->source.protocol);
break;
@@ -2228,7 +1855,6 @@ static eMBException chrg_mb_write_sys(rt_uint8_t ch, rt_uint16_t reg_offset, rt_
else if (sou_value == 0x02)
{
pSW->id = ID_SOURCE;
pSW->source.Set_Pro_Flag = 1;
}
break;
@@ -2334,11 +1960,15 @@ static eMBException chrg_mb_write_sys(rt_uint8_t ch, rt_uint16_t reg_offset, rt_
}
else if (new_id == ID_SOURCE && source_work == 0x01)
{
chrg_com_source_on(ch, pReal->protoCmd, pReal, &pNOR->enable[ch]);
/* COM只触发状态,初始化命令由Source状态机统一下发。 */
pReal->source.On_Flag = 1;
pReal->source.work_mode = SOURCE_WORK_INIT;
}
else if (new_id == ID_SOURCE && source_work == 0x00)
{
chrg_sou_stop(ch, pReal, pNOR);
/* 停止动作同样交给状态机处理,避免COM直接控制硬件。 */
pReal->source.On_Flag = 0;
pReal->source.work_mode = SOURCE_WORK_STOP;
}
rt_mutex_release(pTHR_NOR->mutex);
}
-25
View File
@@ -37,26 +37,6 @@ struct chrg_lcd_t chrglcd = {
// 55 41 00 0D 0A 停止
// 55 41 01 0D 0A 运行
void chrg_sou_work(eIDX_SOU_CH ch,struct chrg_switch_t *pSW)
{
struct chrg_south_t *pSOU = &chrgsouth;
if(pSW->id == ID_SOURCE){
chrg_set_sou_reg(ch, REG_WORK, WORK_START);
// rt_thread_mdelay(50);
pSW->source.Set_CV_Flag = 1;
pSW->source.Set_Pro_Flag = 1;
pSW->source.On_Flag = 1;
pSW->sub = IDX_SET_SOURCE_PD;
}
else if(pSW->id == ID_SINK) {
pSW->sink.On_work = 1;
pSW->sub=IDX_SET_SINK_PD;
}
pSOU->online[ch] = 1;
chrg_nor_sw_rel((eIDX_NOR_CH)ch, pSW->id);
rt_thread_mdelay(50);
}
void chrg_sou_stop(eIDX_SOU_CH ch,struct chrg_switch_t *pSW,struct chrg_north_t *pNOR)
{
struct chrg_south_t *pSOU = &chrgsouth;
@@ -64,7 +44,6 @@ void chrg_sou_stop(eIDX_SOU_CH ch,struct chrg_switch_t *pSW,struct chrg_north_t
return;
}
if(pSW->id == ID_SOURCE){
pSW->source.Stop_step_flag = 0;
pSW->source.On_Flag = 0;
pSW->sub = IDX_GET_SOURCE_VC;
}
@@ -82,7 +61,6 @@ int chrg_pro_set(struct chrg_switch_t *pSW, rt_uint8_t protocol){
if (pSW->id == ID_SOURCE) {
// Source端
pSW->source.protocol = protocol;
pSW->source.LCD_Set_Pro_Flag = 1;
} else if (pSW->id == ID_SINK) {
// Sink端
pSW->sink.protocol = protocol;
@@ -211,7 +189,6 @@ static int chrg_lcd_parse (rt_uint8_t *recv, rt_uint16_t len)
}
pNOR->enable[ch] = 1;
rt_kprintf("ch=%d\n",ch);
chrg_sou_work((eIDX_SOU_CH)ch,pSW);
pSW->continue_flag = 0;
}
//关闭
@@ -237,7 +214,6 @@ static int chrg_lcd_parse (rt_uint8_t *recv, rt_uint16_t len)
// 按角色存入source/sink
pSW->source.vc.set_voltage = Recv_Data; // 电源侧电压(mV
pSW->sink.loadv = Recv_Data; // 负载侧电压(mV,)
pSW->source.Set_Pro_Flag = 1;
// 写入电压寄存器
if(pSW->id==ID_SINK) {
chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_VOLTAGE_OUT+1, Recv_Data);
@@ -257,7 +233,6 @@ static int chrg_lcd_parse (rt_uint8_t *recv, rt_uint16_t len)
//按角色存入source/sink
pSW->source.vc.set_current = Recv_Data; // 电源侧电流(mA
pSW->sink.loadc = Recv_Data; // 负载侧电流(mA
pSW->source.Set_Pro_Flag = 1;
// rt_kprintf("cur=%d",Recv_Data);
// 写入电流寄存器
for(int i = 0;i<10;i++){
-1
View File
@@ -45,7 +45,6 @@ extern void chrg_lcd_thread_entry (void *data);
extern rt_uint8_t On_Flag;
extern rt_uint8_t Flag_start;
extern void chrg_sou_work(eIDX_SOU_CH ch,struct chrg_switch_t *pSW);
extern void chrg_sou_stop(eIDX_SOU_CH ch,struct chrg_switch_t *pSW,struct chrg_north_t *pNOR);
extern void chrg_set_eload_sink(eIDX_SOU_CH ch,struct chrg_switch_t *pSW);
extern void chrg_set_eload_source(eIDX_SOU_CH ch,struct chrg_switch_t *pSW);
+30 -72
View File
@@ -30,42 +30,6 @@ uint16_t chrg_compare(rt_int16_t a, rt_int16_t b)
else return b - a;
}
/*****************************************************************
函数名称: chrg_source_stop
功能描述: 南向功率源停止流程控制函数(分步执行停止操作)
函数描述: 通过状态机分步执行南向功率停止流程:停止功率输出 -> 关闭北向继电器 -> 清空控制标志并禁用使能
输入参数:
frame_data :原始数据帧指针,用于提取当前电压值
pSW :北向通道控制结构体指针
idx :通道编号(功率通道/北向通道索引)
enable :北向通道使能,停止后关掉使能
返回说明: 无返回值
*****************************************************************/
void chrg_source_stop(rt_uint8_t *frame_data,struct chrg_switch_t *pSW,rt_uint8_t idx,rt_uint8_t *enable){
switch(pSW->source.Stop_step_flag){
case 0: // 停止工作
chrg_set_sou_reg((eIDX_SOU_CH)idx, REG_WORK, WORK_STOP);
rt_thread_mdelay(50);
rt_uint16_t volt_mv_Now = (frame_data[4] << 8) | frame_data[5];
volt = volt_mv_Now;
if(volt_mv_Now < 1000){
pSW->source.Stop_step_flag = 1;
}
break;
case 1: // 关闭北向继电器
chrg_nor_sw_rel((eIDX_NOR_CH)idx,0);
rt_thread_mdelay(50);
pSW->source.Stop_step_flag = 2;
break;
case 2: // 状态2:已执行完停止操作,清空标志位
pSW->source.Set_CV_Flag = 0;
*enable = 0;
break;
default:
break;
}
}
/*****************************************************************
函数名称: chrg_source_standard_output
功能描述: 南向功率源标准输出控制函数
@@ -97,48 +61,46 @@ void chrg_source_standard_output(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
}
//电源快充
void chrg_source_fast_output(rt_uint8_t *frame_data, eIDX_SOU_CH idx,
void chrg_source_parse(rt_uint8_t *frame_data, eIDX_SOU_CH idx,
struct chrg_switch_t *pSW, struct chrg_north_t *pNOR)
{
struct chrg_rollsou_t *pROLL = &chrgrollsou;
rt_uint16_t volt_mv = (frame_data[8] << 8) | frame_data[9];
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);
rt_uint16_t Curr_compare = chrg_compare(Curr_mA, Curr_mA_Now);
static rt_uint16_t last_volt_mv[TOTAL_SOU_CHS] = {0};
static rt_uint8_t number = 0;
#if LCD_OPEN
// rt_kprintf("volt_mv=%d,volt_mv_Now=%d,compare=%d\r\n",volt_mv,volt_mv_Now,volt_compare);
if(volt_compare<5000){ //比较设定值与实际值差距,小于2V认为达成设定,允许屏幕开始变换
number++;
number = number%10;
if(number == 9)
{
pSW->change_flag = 0;
int ret;
if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
return;
}
}else { //没有达成设定,屏幕不允许变换
pSW->change_flag = 0x01;
}
#endif
// if(volt_mv_Now==0){
// chrg_set_sou_reg((eIDX_SOU_CH)idx, REG_WORK, WORK_START);
pSW->source.vc.set_voltage = volt_mv;
pSW->source.vc.set_current = Curr_mA;
// #if LCD_OPEN
// // rt_kprintf("volt_mv=%d,volt_mv_Now=%d,compare=%d\r\n",volt_mv,volt_mv_Now,volt_compare);
// if(volt_compare<5000){ //比较设定值与实际值差距,小于2V认为达成设定,允许屏幕开始变换
// number++;
// number = number%10;
// if(number == 9)
// {
// pSW->change_flag = 0;
// }
// else{
if (pSW->source.Set_CV_Flag == 0){
{
chrg_set_sou_reg((eIDX_SOU_CH)idx, REG_VOLTAGE_OUT+1, volt_mv);
// }else { //没有达成设定,屏幕不允许变换
// pSW->change_flag = 0x01;
// }
// #endif
if (pSW->source.On_Flag && (volt_mv_Now > 2000)) {
if ((volt_mv == last_volt_mv[idx])) {
pSW->source.work_mode = SOURCE_WORK_WAIT;
} else {
pSW->source.work_mode = SOURCE_WORK_RUNING;
}
pSW->source.Set_CV_Flag = 1;
#if DEBUG_NORTH
rt_kprintf("Volt_Set%d\r\n",volt_mv);
#endif
}
else if(pSW->source.Set_CV_Flag==1){
chrg_set_sou_reg((eIDX_SOU_CH)idx, REG_WORK, WORK_START);
pSW->source.Set_CV_Flag = 0;
}else{
pSW->source.Set_CV_Flag=0;
ret = chrg_source_work_state(idx, pSW);
if ((ret >= 0) && (pSW->source.work_mode == SOURCE_WORK_RUNING)) {
last_volt_mv[idx] = volt_mv;
}
}
@@ -152,7 +114,7 @@ void chrg_source_setting(rt_uint8_t *frame_data, eIDX_SOU_CH idx,
chrg_source_standard_output(idx, pSW);
}
else{ //快充部分按协商结果输出
chrg_source_fast_output(frame_data, idx, pSW, pNOR);
chrg_source_parse(frame_data, idx, pSW, pNOR);
// rt_kprintf("set_end\r\n");
}
}else if(pSW->source.On_Flag == 0){
@@ -240,7 +202,7 @@ static void chrg_north_handle_Seting_Volt(rt_uint8_t *frame_data, rt_uint16_t fr
static uint8_t number = 0;
//电源部分
if(pSW->id==ID_SOURCE){
chrg_source_setting(frame_data,(eIDX_SOU_CH)idx, pSW, pNOR);
chrg_source_parse(frame_data,(eIDX_SOU_CH)idx, pSW, pNOR);
}
else{
chrg_sink_parse(frame_data,(eIDX_SOU_CH)idx, pSW, pNOR);
@@ -262,7 +224,6 @@ struct chrg_north_t chrgnorth = {
.source = { // 电源侧参数初始化
.On_Flag = 0, // 启动标志初始关闭
.Set_CV_Flag = 1, // 启停控制初始置1
.Set_Pro_Flag = 1 // 电压/电流切换初始置1
}, // 关键:补充逗号分隔source和sink
.sink = {
.protocol = 0xFE,
@@ -280,7 +241,6 @@ struct chrg_north_t chrgnorth = {
.source = {
.On_Flag = 0,
.Set_CV_Flag = 1,
.Set_Pro_Flag = 1
},
.sink = {
.protocol = 0xFE,
@@ -297,7 +257,6 @@ struct chrg_north_t chrgnorth = {
.source = {
.On_Flag = 0,
.Set_CV_Flag = 1,
.Set_Pro_Flag = 1
},
.sink = {
.protocol = 0xFE,
@@ -314,7 +273,6 @@ struct chrg_north_t chrgnorth = {
.source = {
.On_Flag = 0,
.Set_CV_Flag = 1,
.Set_Pro_Flag = 1
},
.sink = {
.protocol = 0xFE,
+5 -78
View File
@@ -162,38 +162,6 @@ int sink_fill_pd_buf(rt_uint8_t group,rt_uint8_t pd_val, rt_uint16_t pd_volt, rt
return 0;
}
rt_uint16_t v1=0,v2=0;
//电源关闭
void chrg_nor_source_stop(struct chrg_switch_t *pSW,rt_uint8_t idx,rt_uint8_t *enable){
switch(pSW->source.Stop_step_flag){
case 0:
chrg_set_sou_reg((eIDX_SOU_CH)idx, REG_WORK, WORK_STOP);
pSW->source.Stop_step_flag = 1;
break;
case 1: // 停止工作
chrg_set_sou_reg((eIDX_SOU_CH)idx, REG_WORK, WORK_STOP);
pSW->source.Stop_step_flag = 2;
break;
case 2: // 关闭北向继电器
chrg_nor_sw_rel((eIDX_NOR_CH)idx,0);
pSW->source.Stop_step_flag = 3;
break;
case 3: // 状态2:已执行完停止操作,清空标志位
pSW->source.Set_CV_Flag = 0;
if(pSW->source.change_sink_Flag == 1){
pSW->source.change_sink_Flag = 0;
// chrg_com_sink_on(idx,pSW,enable);
}else{
*enable = 0;
}
break;
default:
pSW->source.Stop_step_flag = 0;
break;
}
}
/*****************************************************************
函数名称: chrg_roll_nor_sw_uart
@@ -230,20 +198,7 @@ void chrg_roll_nor_sink_pro_set(struct chrg_switch_t *pSW)
//设置电源协议
void chrg_roll_nor_source_pro_set(struct chrg_switch_t *pSW){
if(pSW->source.Set_Pro_Flag == 1){
pSW->source.Set_Pro_Flag = 0;
if(pSW->source.LCD_Set_Pro_Flag==1){
source_set_pd(pSW->source.protocol,0,0,pSW->source.vc.set_voltage,0,pSW->source.vc.set_current);
}
else if(pSW->source.LCD_Set_Pro_Flag==2){
source_set_pd_com(pSW->source.protocol,pSW->source.pro_gear_idx);
}
else if(pSW->source.LCD_Set_Pro_Flag==3){
source_set_pd_new_com(pSW->source.protocol,pSW);
}
}else {
pSW->sub = IDX_GET_SOURCE_VC;
}
source_set_pro(pSW->source.protocol,pSW);
}
static int chrg_roll_nor_parse (struct chrg_rollnor_t *pROLL, rt_uint8_t *data)
{
@@ -329,51 +284,23 @@ void chrg_roll_nor_set(rt_uint8_t ch, struct chrg_switch_t *pSW,rt_uint8_t *enab
if(pSW->id==ID_SOURCE){ //电源
chrg_roll_nor_sw_uart((eIDX_NOR_CH)ch, ID_SOURCE);
switch(pSW->sub){
case IDX_SET_SOURCE_ID: //角色
chrg_set_eload_source(ch,pSW);
if(pSW->continue_flag)
pSW->sub = IDX_SET_SOURCE_CC_SET;
// rt_kprintf("set_start\r\n");
break;
case IDX_SET_SOURCE_CC_SET:
source_set_cc_choose(pSW->source.cc_set);
pSW->sub = IDX_SET_SOURCE_CV;
break;
case IDX_SET_SOURCE_CV: //恒压恒流
pSW->sub = IDX_SER_SOURCE_VOLT;
break;
case IDX_SER_SOURCE_VOLT://电压
chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_VOLTAGE_OUT+1, 0);
pSW->sub = IDX_SER_SOURCE_CURR;
break;
case IDX_SER_SOURCE_CURR://电流
chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_CURRENT_OUT+1, pSW->source.protective_curr);
pSW->sub = IDX_SET_SOURCE_WORK;
break;
case IDX_SET_SOURCE_WORK:
chrg_sou_work(ch,pSW);
pSW->sub = IDX_SET_SOURCE_PD;
break;
case IDX_SET_SOURCE_PD:
chrg_roll_nor_source_pro_set(pSW);
if (pSW->sub == IDX_GET_SOURCE_VC &&
chrg_source_init_submit((eIDX_SOU_CH)ch, pSW) == 0) {
pSW->source.On_Flag = 1;
}
pSW->sub = IDX_GET_SOURCE_VC;
break;
case IDX_GET_SOURCE_VC:
source_get_vc(pSW->source.vc.set_voltage, pSW->source.vc.set_current);
break;
case IDX_SET_SOURCE_CCLVL:
source_set_cc_lvl(pSW->source.vol_lvl);
break;
case IDX_SET_SOURCE_STOP_STATE:
chrg_nor_source_stop(pSW,ch,enable);
break;
default:
break;
}
}else{
}
else{
chrg_roll_nor_sw_uart((eIDX_NOR_CH)ch, ID_SINK);
switch(pSW->sub){
case IDX_GET_SINK_VC: //查询
+97 -31
View File
@@ -15,9 +15,11 @@
#include "chrg_source.h"
#include "chrg_eload.h"
#include "chrg_roll_sou.h"
#include "chrg_rel.h"
int chrg_source_init_submit(rt_uint8_t idx, struct chrg_switch_t *pSW)
{
/* Source启动参数一次入队,最后发送WORK_START使功率板开始输出。 */
rt_uint16_t regs[5] = {
REG_ELOAD,
REG_MODE,
@@ -30,7 +32,7 @@ int chrg_source_init_submit(rt_uint8_t idx, struct chrg_switch_t *pSW)
pSW->CV_mode,
pSW->source.max_vol,
pSW->source.protective_curr,
WORK_STOP
WORK_START
};
if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
@@ -38,6 +40,99 @@ int chrg_source_init_submit(rt_uint8_t idx, struct chrg_switch_t *pSW)
}
return chrg_sou_com_batch_submit(idx, regs, vals, 5);
}
static int chrg_source_work_init(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
{
struct chrg_south_t *pSOU = &chrgsouth;
struct chrg_north_t *pNOR = &chrgnorth;
int ret;
/* 只有整批命令成功入队后,才打开通道并进入等待状态。 */
ret = chrg_source_init_submit(idx, pSW);
if (ret != 0) {
return ret;
}
pSW->source.On_Flag = 1;
pSOU->enable[idx] = 1;
pNOR->enable[idx] = 1;
pSOU->online[idx] = 1;
chrg_nor_sw_rel((eIDX_NOR_CH)idx, ID_SOURCE);
pSW->source.work_mode = SOURCE_WORK_WAIT;
return 0;
}
static int chrg_source_work_wait(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
{
/* WAIT状态不产生南向命令,等待下一帧北向电压数据。 */
return 0;
}
static int chrg_source_work_running(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
{
/* RUNING只下发协商后的目标电压,不重复发送启动命令。 */
rt_uint16_t reg = REG_VOLTAGE_OUT + 1;
rt_uint16_t value = pSW->source.vc.set_voltage;
return chrg_sou_com_batch_submit(idx, &reg, &value, 1);
}
static int chrg_source_work_low(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
{
/* 电压异常时先停止功率板输出,保留状态供上层判断。 */
rt_uint16_t reg = REG_WORK;
rt_uint16_t value = WORK_STOP;
return chrg_sou_com_batch_submit(idx, &reg, &value, 1);
}
static int chrg_source_work_stop(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
{
struct chrg_south_t *pSOU = &chrgsouth;
struct chrg_north_t *pNOR = &chrgnorth;
int ret;
rt_uint16_t reg = REG_WORK;
rt_uint16_t value = WORK_STOP;
/* 停止命令入队成功后再关闭使能和北向继电器。 */
ret = chrg_sou_com_batch_submit(idx, &reg, &value, 1);
if (ret != 0) {
return ret;
}
pSW->source.On_Flag = 0;
pSOU->enable[idx] = 0;
pNOR->enable[idx] = 0;
pSOU->online[idx] = 0;
chrg_nor_sw_rel((eIDX_NOR_CH)idx, 0);
pSW->source.work_mode = SOURCE_WORK_WAIT;
return 0;
}
int chrg_source_work_state(rt_uint8_t idx, struct chrg_switch_t *pSW)
{
if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
return -1;
}
/* 所有Source功率板控制统一从本状态机出口执行。 */
switch (pSW->source.work_mode) {
case SOURCE_WORK_INIT:
return chrg_source_work_init(idx, pSW);
case SOURCE_WORK_WAIT:
return chrg_source_work_wait(idx, pSW);
case SOURCE_WORK_RUNING:
return chrg_source_work_running(idx, pSW);
case SOURCE_WORK_LOW:
return chrg_source_work_low(idx, pSW);
case SOURCE_WORK_STOP:
return chrg_source_work_stop(idx, pSW);
default:
return -1;
}
}
rt_uint8_t Pro_Group_VCMM[11][8] = {
{0} // 11个挡位,8个参数(src, pps, vmin_H,vmin_L, vmax_H,vmax_L,cur_set_H,cur_set_L
};
@@ -346,8 +441,6 @@ void parse_power_pdo_gear(rt_uint8_t protoCmd, rt_uint8_t *pData, rt_uint16_t re
// #endif.
}
/*****************************************************************
函数名称: parse_mulit_gear_more
函数描述: 解析三-四挡位原始数据,填充8参数高低字节缓冲区(同步修改)
@@ -859,34 +952,8 @@ rt_uint8_t pd_fill_single_group_UFCS(rt_uint8_t *data, rt_uint8_t start_idx,stru
return idx - start_idx; // 返回填充的总字节数
}
int source_set_pd_com(rt_uint8_t pro,rt_uint8_t pro_gear_idx)
{
rt_uint16_t len = 0;
rt_uint8_t data[150] = {0};
rt_uint8_t frame[150] = {0};
rt_uint8_t send_len = 0; //数据长度
rt_uint8_t max_group_idx = 0; //挡位索引
data[0] = pro; //协议
rt_uint8_t idx = 1;
for(rt_uint8_t i = 0;i<pro_gear_idx;i++){
rt_uint8_t fill_len = pd_fill_single_group_com(data,idx,i);
if (fill_len == 0) {
rt_kprintf("Error: fill group %d failed\n", i);
return -1;
}
idx += fill_len; // 偏移到下一组起始位置
}
send_len = idx; // 总填充字节数
chrg_north_pkg_encode(ID_SOURCE, SRC_CMD_SET_PROTOCOL, data, send_len, frame, &len);
// for(rt_uint8_t i=0;i<len+5;i++){
// rt_kprintf("%02x",data[i]);
// }
// rt_kprintf("idx=%d",idx);
return chrg_north_send(frame, len);
}
int source_set_pd_new_com(rt_uint8_t pro, struct chrg_switch_t *pSW)
int source_set_pro(rt_uint8_t pro, struct chrg_switch_t *pSW)
{
rt_uint16_t len = 0;
rt_uint8_t data[150] = {0};
@@ -917,4 +984,3 @@ int source_set_pd_new_com(rt_uint8_t pro, struct chrg_switch_t *pSW)
return chrg_north_send(frame, len);
}
+15 -5
View File
@@ -160,16 +160,25 @@ struct chrg_src_t {
rt_uint8_t Now_State; // 当前状态
rt_uint8_t On_Flag; // 启动总标志(0/1
rt_uint8_t Set_CV_Flag; // 电压/电流切换标志(0/1
rt_uint8_t Set_Pro_Flag; // 设置协议标志位(0/1/2)0代表没设置协议,1代表设置了但还没执行,2代表设置了并执行
rt_uint8_t LCD_Set_Pro_Flag; // LCD设置协议标志位
rt_uint8_t Work_step_flag; // 工作步骤标志位
rt_uint8_t Stop_step_flag; // 停止步骤标志位
rt_uint8_t change_sink_Flag; // 从source切换到sink标志位
rt_uint8_t work_mode; // 0=停止 1=工作 2=低电压
rt_uint8_t work_mode;
struct src_vc_t vc; // 读取数据
struct vc_pd_t pd_get[2]; // 读取PD协议数据
struct vc_pd_t pd_set[2]; // 设置PD协议数据
};
// 电源工作状态机:COM只切换状态,具体功率板指令由状态处理函数下发
enum {
SOURCE_WORK_INIT = 0, // 初始化功率板并启动输出
SOURCE_WORK_WAIT, // 参数未变化,不下发功率板指令
SOURCE_WORK_RUNING, // 协商电压变化,下发一次新电压
SOURCE_WORK_LOW, // 电压过低,停止功率板输出
SOURCE_WORK_STOP, // 主动停止并关闭通道
SOURCE_WORK_ON_TEST_DYNA,
SOURCE_WORK_ON_TEST_SHORT,
};
/*****************************************************************
source_get_vc
source电压电流查询请求
@@ -248,10 +257,11 @@ extern void parse_power_single_gear(rt_uint8_t protoCmd, rt_uint8_t *pData, rt_u
extern void parse_power_pdo_gear(rt_uint8_t protoCmd, rt_uint8_t *pData, rt_uint16_t reqLen,uint8_t *pro_gear_idx,uint8_t *pro,rt_uint16_t *protect_ma);
extern void parse_multi_gear_more(rt_uint8_t protoCmd, rt_uint8_t *pData, rt_uint16_t reqLen,uint8_t *pro_gear_idx,uint8_t *pro,rt_uint16_t *protect_ma);
extern void parse_power_ufcs(rt_uint8_t *pData, rt_uint16_t reqLen, uint8_t *pro_gear_idx, uint8_t *pro,rt_uint16_t *protect_ma);
extern int source_set_pd_new_com(rt_uint8_t pro, struct chrg_switch_t *pSW);
extern int source_set_pro(rt_uint8_t pro, struct chrg_switch_t *pSW);
/* 提交 Source 功率板初始化参数;北向协议设置完成后调用。 */
extern int chrg_source_init_submit(rt_uint8_t idx, struct chrg_switch_t *pSW);
extern int chrg_source_work_state(rt_uint8_t idx, struct chrg_switch_t *pSW);
#endif