chore: 整理代码并更新文档

1. 新增并替换通信协议文档,删除旧版V2.0协议文档
2. 重构充电源逻辑,移除Set_CV_Flag相关变量和代码
3. 优化充电源关闭流程,修正寄存器配置逻辑
4. 完善Modbus输入寄存器回调和功能码处理逻辑
5. 调整输入寄存器映射表,简化寄存器定义
6. 为USB设备队列内存添加对齐宏定义
7. 新增南向电源Modbus寄存器头文档
This commit is contained in:
wrh
2026-07-23 10:36:59 +08:00
parent 30ecd7ad83
commit 8f44ae6877
10 changed files with 300 additions and 113 deletions
+18 -5
View File
@@ -221,6 +221,16 @@ static eMBException mb_error (eMBErrorCode eErrorCode)
}
//extern eMBErrorCode Modbus_Protocal_Set(rt_uint16_t Role_value,rt_uint16_t src,rt_uint16_t pps,rt_uint16_t pro_value,rt_uint16_t volt_value,rt_uint16_t curr_value);
/*****************************************************************
函数名称: mb_reg_input_cb
函数描述: Modbus输入寄存器读取回调函数
输入参数: pucRegBuffer:输入寄存器返回数据缓冲区
usAddress:输入寄存器起始地址
usNRegs:需要读取的输入寄存器数量
输出参数: pucRegBuffer:按Modbus高字节在前格式填充寄存器数据
返回说明: MB_ENOERR:读取成功 MB_ENOREG:地址范围错误
其它说明: 只读usRegInBuf,不处理写操作;每个输入寄存器转换为两个字节
*****************************************************************/
eMBErrorCode mb_reg_input_cb (rt_uint8_t *pucRegBuffer, rt_uint16_t usAddress, rt_uint16_t usNRegs)
{
eMBErrorCode eStatus = MB_ENOERR;
@@ -566,11 +576,12 @@ eMBException funcReadHoldingRegister (rt_uint8_t *reqFrame, rt_uint16_t reqLen,
/*****************************************************************
函数名称: funcReadInputRegister
函数描述: 输入寄存器
函数描述: 处理Modbus功能码0x04,读取输入寄存器
输入参数: reqFrame: 请求数据 reqLen: 请求长度 resFrame:响应数据 resLen:响应长度
输出参数: -
返回说明: -
其它说明: -
输出参数: resFrame:输入寄存器响应帧 resLen:响应帧长度
返回说明: MB_EX_NONE:读取成功 其他:Modbus异常码
其它说明: 请求地址和数量校验方式与功能码0x03保持一致;输入寄存器
数据从usRegInBuf读取,响应数据按高字节在前返回
*****************************************************************/
eMBException funcReadInputRegister (rt_uint8_t *reqFrame, rt_uint16_t reqLen,
rt_uint8_t *resFrame, rt_uint16_t *resLen)
@@ -594,13 +605,14 @@ eMBException funcReadInputRegister (rt_uint8_t *reqFrame, rt_uint16_t reqLen,
resFrame[1] = MB_READ_INPUT_REGISTER;
resFrame[2] = cntReg * 2;
eRegStatus = mb_reg_discrete_cb(&resFrame[3], regAddress, cntReg);
eRegStatus = mb_reg_input_cb(&resFrame[3], regAddress, cntReg);
if (eRegStatus != MB_ENOERR) {
eStatus = mb_error(eRegStatus);
} else {
*resLen = 3+cntReg*2;
}
rt_kprintf("------COM READ INPUT addr=%d count=%d-------\n", regAddress, cntReg);
return eStatus;
}
@@ -801,6 +813,7 @@ typedef struct {
} SrcProtoMap_t;
static const SrcProtoMap_t src_proto_map[] = {
{0x20, PRO_NONE}, // 标准协议(无快充)
{0x2A, PRO_PD0PSS}, // PD
{0x22, PRO_FCP}, // FCP
{0x23, PRO_SCPB}, // SCPB
+85 -56
View File
@@ -28,100 +28,133 @@
#define SOURCE_VOLT_RETRY_FRAMES 3U
/*****************************************************************
函数名称: chrg_source_standard_output
功能描述: 南向功率源标准输出控制函数
函数描述: 根据CV标志位,分别设置电源输出电压或输出电流,实现标准模式下的恒压/恒流输出
输入参数:
idx :功率通道编号
pSW :北向通道控制结构体指针,包含电压/电流设定值、CV控制标志等参数
输出参数:
pSW :更新CV控制标志位
返回说明: 无返回值
函数名称: chrg_source_voltage_control
函数描述: 统一处理Source目标电压、误差判断和状态机切换
输入参数: idx:当前通道 pSW:通道控制结构体 volt_mv:目标电压(mV)
curr_ma:目标电流(mA)
输出参数: 更新source.vc及source.work_mode
返回说明: 0:状态处理成功 <0:参数错误或命令提交失败
其它说明: 目标电压变化时立即进入RUNING;实际电压与目标值的绝对误差
小于等于200mV时进入WAIT;连续3次超过误差范围时重发
*****************************************************************/
void chrg_source_standard_output(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
static int chrg_source_voltage_control(eIDX_SOU_CH idx,
struct chrg_switch_t *pSW,
rt_uint16_t volt_mv,
rt_uint16_t curr_ma)
{
if(pSW->source.Set_CV_Flag) {
chrg_set_sou_reg((eIDX_SOU_CH)idx, REG_VOLTAGE_OUT+1, pSW->source.max_vol);
#if DEBUG_NORTH
rt_kprintf("Volt_Set%d\r\n",pSW->source.vc.set_voltage);
#endif
pSW->source.Set_CV_Flag = 1;
pSW->change_flag = 0;
}
}
/*****************************************************************
函数名称: chrg_source_parse
函数描述: 解析北向电源板电压电流回码并驱动Source状态机
输入参数: frame_data:完整北向回码 idx:当前通道 pSW:通道控制结构体
pNOR:北向总控结构体
输出参数: 更新电压、电流、source.work_mode及电压重试计数
返回说明: -
其它说明: frame_data[4~7]为实测值,[8~11]为协议协商目标值;
新目标立即进入RUNING;实际误差连续3帧超过200mV时重发
*****************************************************************/
void chrg_source_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;
rt_uint16_t curr_ma;
rt_uint16_t volt_error;
static rt_uint16_t last_volt_mv[TOTAL_SOU_CHS] = {0};
static rt_uint8_t last_volt_valid[TOTAL_SOU_CHS] = {0};
static rt_uint8_t last_protocol[TOTAL_SOU_CHS] = {0};
static rt_uint8_t volt_retry_count[TOTAL_SOU_CHS] = {0};
rt_bool_t need_set = RT_FALSE;
int ret;
if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL) ||
(frame_data == RT_NULL)) {
return;
if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
return -1;
}
volt_mv = (frame_data[8] << 8) | frame_data[9];
curr_ma = (frame_data[10] << 8) | frame_data[11];
/* 保存北向协议板返回的实测值和协商目标值。 */
/* 保存本次目标值,RUNING状态只使用其中的目标电压下发命令。 */
pSW->source.vc.set_voltage = volt_mv;
pSW->source.vc.set_current = curr_ma;
if (!pSW->source.On_Flag) {
/* 关机后清除历史值,确保下次启动至少下发一次目标电压。 */
/* 关机后清除历史缓存,下一次启动必须重新设置目标电压。 */
last_volt_valid[idx] = 0;
volt_retry_count[idx] = 0;
return;
return 0;
}
/* 使用绝对误差,避免无符号减法在实际电压较小时发生下溢。 */
/* 使用绝对误差,避免实际电压低于目标值时发生无符号下溢。 */
volt_error = (pSW->Now_voltage >= volt_mv) ?
(pSW->Now_voltage - volt_mv) :
(volt_mv - pSW->Now_voltage);
if (!last_volt_valid[idx] || (volt_mv != last_volt_mv[idx])) {
/* 首次设置或目标变化,立即进入RUNING下发新电压。 */
if (!last_volt_valid[idx] ||
(last_protocol[idx] != (rt_uint8_t)pSW->source.protocol) ||
(volt_mv != last_volt_mv[idx])) {
/* 首次设置、协议切换或目标变化时立即下发新电压。 */
need_set = RT_TRUE;
} else if (volt_error <= SOURCE_VOLT_ERROR_MV) {
/* 实际电压已进入允许范围,清除连续失败计数。 */
/* 实际电压误差不超过200mV即可视为设置成功。 */
volt_retry_count[idx] = 0;
} else {
/* 给功率板三个反馈周期的稳定时间,避免每帧重复写电压。 */
if (volt_retry_count[idx] < SOURCE_VOLT_RETRY_FRAMES) {
volt_retry_count[idx]++;
}
if (volt_retry_count[idx] >= SOURCE_VOLT_RETRY_FRAMES) {
need_set = RT_TRUE;
}
}
/* 解析函数只决定状态,具体寄存器操作仍由Source状态机执行。 */
pSW->source.work_mode = need_set ?
SOURCE_WORK_RUNING : SOURCE_WORK_WAIT;
ret = chrg_source_work_state(idx, pSW);
if ((ret == 0) && need_set) {
/* 成功入队后更新缓存;重发成功后重新开始计算连续超差帧数。 */
/* 只有命令成功提交后才更新缓存,失败时下一次继续重试。 */
last_volt_mv[idx] = volt_mv;
last_protocol[idx] = (rt_uint8_t)pSW->source.protocol;
last_volt_valid[idx] = 1;
volt_retry_count[idx] = 0;
}
return ret;
}
/*****************************************************************
函数名称: chrg_source_standard_output
函数描述: 使用COM配置值驱动标准协议电源输出
输入参数: idx:当前通道 pSW:通道控制结构体
输出参数: 更新source.vc及source.work_mode
返回说明: 无返回值
其它说明: 外部协议值0x20映射为PRO_NONE;本函数不解析北向协议返回
数据,目标电压和保护电流直接使用COM配置值
*****************************************************************/
void chrg_source_standard_output(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
{
if (pSW == RT_NULL) {
return;
}
(void)chrg_source_voltage_control(idx, pSW,
pSW->source.max_vol, pSW->source.protective_curr);
}
/*****************************************************************
函数名称: chrg_source_parse
函数描述: 按电源协议类型处理目标电压并驱动Source状态机
输入参数: frame_data:完整北向回码 idx:当前通道 pSW:通道控制结构体
pNOR:北向总控结构体
输出参数: 更新电压、电流、source.work_mode及电压重试计数
返回说明: -
其它说明: 标准协议不解析frame_data,直接使用COM配置值;快充协议读取
frame_data[8~11]中的协商目标值。新目标立即进入RUNING,
实际误差连续3帧超过200mV时重发
*****************************************************************/
void chrg_source_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;
rt_uint16_t curr_ma;
if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
return;
}
/* 标准协议使用COM设定值,不读取北向协议返回帧。 */
if (pSW->source.protocol == PRO_NONE) {
chrg_source_standard_output(idx, pSW);
return;
}
if (frame_data == RT_NULL) {
return;
}
volt_mv = (frame_data[8] << 8) | frame_data[9];
curr_ma = (frame_data[10] << 8) | frame_data[11];
/* 快充只负责解析北向协商结果,后续控制逻辑与标准协议共用。 */
(void)chrg_source_voltage_control(idx, pSW, volt_mv, curr_ma);
}
/*****************************************************************
@@ -138,7 +171,7 @@ void chrg_source_setting(rt_uint8_t *frame_data, eIDX_SOU_CH idx,
{
//执行输出调整
if (pSW->source.On_Flag == 1) {
if(pSW->source.protocol==0x00){//标准下输出设定值
if(pSW->source.protocol == PRO_NONE){//标准下输出设定值
chrg_source_standard_output(idx, pSW);
}
else{ //快充部分按协商结果输出
@@ -258,7 +291,6 @@ struct chrg_north_t chrgnorth = {
.id = ID_SINK, // 初始为负载模式
.source = { // 电源侧参数初始化
.On_Flag = 0, // 启动标志初始关闭
.Set_CV_Flag = 1, // 启停控制初始置1
.work_mode = SOURCE_WORK_WAIT, // 上电保持等待,禁止自动执行Source INIT
}, // 关键:补充逗号分隔source和sink
.sink = {
@@ -276,7 +308,6 @@ struct chrg_north_t chrgnorth = {
.change_flag = 0,
.source = {
.On_Flag = 0,
.Set_CV_Flag = 1,
.work_mode = SOURCE_WORK_WAIT, // 上电保持等待,禁止自动执行Source INIT
},
.sink = {
@@ -293,7 +324,6 @@ struct chrg_north_t chrgnorth = {
.change_flag = 0,
.source = {
.On_Flag = 0,
.Set_CV_Flag = 1,
.work_mode = SOURCE_WORK_WAIT, // 上电保持等待,禁止自动执行Source INIT
},
.sink = {
@@ -310,7 +340,6 @@ struct chrg_north_t chrgnorth = {
.change_flag = 0,
.source = {
.On_Flag = 0,
.Set_CV_Flag = 1,
.work_mode = SOURCE_WORK_WAIT, // 上电保持等待,禁止自动执行Source INIT
},
.sink = {
+5 -48
View File
@@ -93,60 +93,17 @@ enum {
TOTAL_COIL_REGS // 继电器总数(24个)
};
#define TOTAL_INPUT_CH_REGS (10) // 单通道 输入寄存器
#define TOTAL_INPUT_CH_REGS (50) // 单通道输入寄存器,通道地址步长为50
#define TOTAL_INPUT_REGS TOTAL_INPUT_CH_REGS * 4
// 输入寄存器列表
// 每个通道占用50个地址,当前实际使用前4个寄存器,其余地址预留。
enum {
INPUT_REG_CH0_STA1 = INPUT_REG_START, // 通道0 工作状态1 定义同源载
INPUT_REG_CH0_STA2, // 通道0 工作状态2 定义同源载
INPUT_REG_CH0_FAULT1, // 通道0 故障状态1 定义同源载
INPUT_REG_CH0_FAULT2, // 通道0 故障状态2 定义同源载
INPUT_REG_04, // 输入寄存器04
INPUT_REG_05, // 输入寄存器05
INPUT_REG_06, // 输入寄存器06
INPUT_REG_07, // 输入寄存器07
INPUT_REG_08, // 输入寄存器08
INPUT_REG_09, // 输入寄存器09
// add more TOTAL_INPUT_CH_REGS
INPUT_REG_CH1_STA1, // 通道1 工作状态1
INPUT_REG_CH1_STA2, // 通道1 工作状态2
INPUT_REG_CH1_FAULT1, // 通道1 故障状态1
INPUT_REG_CH1_FAULT2, // 通道1 故障状态2
INPUT_REG_14, // 输入寄存器14
INPUT_REG_15, // 输入寄存器15
INPUT_REG_16, // 输入寄存器16
INPUT_REG_17, // 输入寄存器17
INPUT_REG_18, // 输入寄存器18
INPUT_REG_19, // 输入寄存器19
INPUT_REG_CH2_STA1, // 通道2 工作状态1
INPUT_REG_CH2_STA2, // 通道2 工作状态2
INPUT_REG_CH2_FAULT1, // 通道2 故障状态1
INPUT_REG_CH2_FAULT2, // 通道2 故障状态2
INPUT_REG_24, // 输入寄存器24
INPUT_REG_25, // 输入寄存器25
INPUT_REG_26, // 输入寄存器26
INPUT_REG_27, // 输入寄存器27
INPUT_REG_28, // 输入寄存器28
INPUT_REG_29, // 输入寄存器29
INPUT_REG_CH3_STA1, // 通道3 工作状态1
INPUT_REG_CH3_STA2, // 通道3 工作状态2
INPUT_REG_CH3_FAULT1, // 通道3 故障状态1
INPUT_REG_CH3_FAULT2, // 通道3 故障状态2
INPUT_REG_34, // 输入寄存器34
INPUT_REG_35, // 输入寄存器35
INPUT_REG_36, // 输入寄存器36
INPUT_REG_37, // 输入寄存器37
INPUT_REG_38, // 输入寄存器38
INPUT_REG_39, // 输入寄存器39
INPUT_REG_40, // 输入寄存器40
TOTAL_INPUT_REGS // 输入寄存器总数
INPUT_REG_CH0_FAULT2 // 通道0 故障状态2 定义同源载
};
//AI修改,不一定准确
// ======================== 新寄存器映射 (基于0x06/0x10标准Modbus功能码) ========================
// 地址空间规划:
// 负载(Sink): 0x0000 + 通道号×29 + 参数偏移 (4通道×29=116个, 0x0000~0x0073)
-1
View File
@@ -228,7 +228,6 @@ static int chrg_sink_nor_work_off(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
}
pSW->sink.On_work = 0;
pSOU->enable[idx] = 0;
pSOU->online[idx] = 0;
pNOR->enable[idx] = 0;
+1 -2
View File
@@ -135,8 +135,7 @@ static int chrg_source_work_stop(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
}
pSW->source.On_Flag = 0;
pSOU->enable[idx] = 0;
pNOR->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;
@@ -156,7 +156,6 @@ struct chrg_src_t {
rt_uint16_t protective_curr; // 保护电流
rt_uint8_t Now_State; // 当前状态
rt_uint8_t On_Flag; // 启动总标志(0/1
rt_uint8_t Set_CV_Flag; // 电压/电流切换标志(0/1
rt_uint8_t LCD_Set_Pro_Flag; // LCD设置协议标志位
rt_uint8_t change_sink_Flag; // 从source切换到sink标志位
rt_uint8_t work_mode;