diff --git a/apps/chrg/applications/thread/chrg_north.c b/apps/chrg/applications/thread/chrg_north.c index 75c83a0..ea4f291 100644 --- a/apps/chrg/applications/thread/chrg_north.c +++ b/apps/chrg/applications/thread/chrg_north.c @@ -24,6 +24,9 @@ #define DBG_LEVEL DBG_LOG #include +#define SOURCE_VOLT_ERROR_MV 200U +#define SOURCE_VOLT_RETRY_FRAMES 3U + /***************************************************************** 函数名称: chrg_source_standard_output 功能描述: 南向功率源标准输出控制函数 @@ -52,37 +55,72 @@ void chrg_source_standard_output(eIDX_SOU_CH idx, struct chrg_switch_t *pSW) 函数描述: 解析北向电源板电压电流回码并驱动Source状态机 输入参数: frame_data:完整北向回码 idx:当前通道 pSW:通道控制结构体 pNOR:北向总控结构体 -输出参数: 更新协商电压、电流、source.work_mode及上次下发电压缓存 +输出参数: 更新电压、电流、source.work_mode及电压重试计数 返回说明: - 其它说明: frame_data[4~7]为实测值,[8~11]为协议协商目标值; - 目标电压变化时进入RUNING,相同时进入WAIT + 新目标立即进入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 = (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_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 number = 0; + static rt_uint8_t last_volt_valid[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)) { + if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL) || + (frame_data == RT_NULL)) { return; } + volt_mv = (frame_data[8] << 8) | frame_data[9]; + curr_ma = (frame_data[10] << 8) | frame_data[11]; + /* 保存北向协议板返回的实测值和协商目标值。 */ pSW->source.vc.set_voltage = volt_mv; - pSW->source.vc.set_current = Curr_mA; - if (pSW->source.On_Flag) { - if ((volt_mv == last_volt_mv[idx])) { - pSW->source.work_mode = SOURCE_WORK_WAIT; - } else { - pSW->source.work_mode = SOURCE_WORK_RUNING; + pSW->source.vc.set_current = curr_ma; + + if (!pSW->source.On_Flag) { + /* 关机后清除历史值,确保下次启动至少下发一次目标电压。 */ + last_volt_valid[idx] = 0; + volt_retry_count[idx] = 0; + return; + } + + /* 使用绝对误差,避免无符号减法在实际电压较小时发生下溢。 */ + 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下发新电压。 */ + need_set = RT_TRUE; + } else if (volt_error <= SOURCE_VOLT_ERROR_MV) { + /* 实际电压已进入允许范围,清除连续失败计数。 */ + 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) && (pSW->source.work_mode == SOURCE_WORK_RUNING)) { + if ((ret == 0) && need_set) { + /* 成功入队后更新缓存;重发成功后重新开始计算连续超差帧数。 */ last_volt_mv[idx] = volt_mv; + last_volt_valid[idx] = 1; + volt_retry_count[idx] = 0; } } diff --git a/apps/chrg/applications/utils/chrg_source.c b/apps/chrg/applications/utils/chrg_source.c index c437f8c..f8c8c23 100644 --- a/apps/chrg/applications/utils/chrg_source.c +++ b/apps/chrg/applications/utils/chrg_source.c @@ -111,23 +111,6 @@ 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) -{ - /* 电压异常时先停止功率板输出,保留状态供上层判断。 */ - rt_uint16_t reg = REG_WORK; - rt_uint16_t value = WORK_STOP; - - return chrg_sou_com_batch_submit(idx, ®, &value, 1); -} - /***************************************************************** 函数名称: chrg_source_work_stop 函数描述: 执行电源主动关机流程 @@ -211,8 +194,6 @@ int chrg_source_work_state(rt_uint8_t idx, struct chrg_switch_t *pSW) 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); case SOURCE_WORK_SWITCH: diff --git a/apps/chrg/applications/utils/chrg_source.h b/apps/chrg/applications/utils/chrg_source.h index a17fb38..937b0a7 100644 --- a/apps/chrg/applications/utils/chrg_source.h +++ b/apps/chrg/applications/utils/chrg_source.h @@ -145,9 +145,6 @@ struct src_vc_t { #define PD_GEAR_ARRAY_LEN 4 // 非5V挡位最多4个,数组长度设为4 // source 参数结构 struct chrg_src_t { - rt_uint16_t voltage; // 当前电压 mV - rt_uint16_t current; // 当前电流 mA - eSRC_PRO protocol; // 协议类型 rt_uint8_t src; // 源类型 rt_uint8_t pps; // PPS类型 diff --git a/docs/副本BMP4810300-4多协议可编程双向电源通信协议V_2.0 - 副本(1).xlsx b/docs/副本BMP4810300-4多协议可编程双向电源通信协议V_2.0 - 副本(1).xlsx new file mode 100644 index 0000000..8307457 Binary files /dev/null and b/docs/副本BMP4810300-4多协议可编程双向电源通信协议V_2.0 - 副本(1).xlsx differ