feat: 新增Sink板D+/D-校准参数写入功能

1. 新增SINK_CMD_SET_DPDM_CAL命令定义及对应寄存器
2. 新增校准参数结构体及相关任务提交、查询接口
3. 修改北向帧校验逻辑适配校准写入的6字节长度要求
4. 更新协议板版本至V1.1.56,寄存器版本号更新为0x0148
5. 修改Sink电压稳定确认参数,优化5V电压确认计数
6. 新增校准参数配置比较函数,独立处理校准写入事务
7. 更新修改日志,记录本次版本新增功能详情
This commit is contained in:
wrh
2026-10-09 11:05:31 +08:00
parent 42e1174516
commit a8f2edd624
11 changed files with 211 additions and 7 deletions
+44 -1
View File
@@ -27,7 +27,7 @@
#include "stm32f4xx_hal.h"
#define HOLD_REG_FIRMWARE_VERSION 0x0300U /* 协议板固件版本,只读 */
#define CHRG_FIRMWARE_VERSION 0x0147U /* 当前协议板版本:V1.1.55 */
#define CHRG_FIRMWARE_VERSION 0x0148U /* 当前协议板版本:V1.1.56 */
rt_uint8_t ucDiscInBuf[(TOTAL_DISC_REGS+BITS_UCHAR-1)/BITS_UCHAR];
@@ -1735,6 +1735,18 @@ static void chrg_mb_write_sink(rt_uint8_t ch, rt_uint16_t reg_offset, rt_uint16_
case SINK_REG_DYNA_UNLOAD: // 0x1E: 卸载斜率
pSW->sink.test.change_test.k_Fall = sou_value;
break;
case SINK_REG_DPDM_DZ_K: // D+ K,实际比例系数放大10000倍
pSW->sink.dpdm_cal.dz_k = sou_value;
break;
case SINK_REG_DPDM_DZ_B: // D+ B,单位0.01V,有符号16位
pSW->sink.dpdm_cal.dz_b = (rt_int16_t)sou_value;
break;
case SINK_REG_DPDM_DF_K: // D- K,实际比例系数放大10000倍
pSW->sink.dpdm_cal.df_k = sou_value;
break;
case SINK_REG_DPDM_DF_B: // D- B,单位0.01V,有符号16位
pSW->sink.dpdm_cal.df_b = (rt_int16_t)sou_value;
break;
default:
rt_kprintf("[SINK CH%d] Unknown reg offset=0x%02X\n", ch + 1, reg_offset);
break;
@@ -1868,6 +1880,16 @@ static rt_bool_t chrg_comm_sink_config_equal(const struct chrg_switch_t *a,
sizeof(a->sink.test.change_test)) == 0);
}
/* D+/D-校准参数为独立北向事务,不并入普通负载状态机配置比较。 */
static rt_bool_t chrg_comm_sink_dpdm_cal_equal(const struct chrg_switch_t *a,
const struct chrg_switch_t *b)
{
return (a->sink.dpdm_cal.dz_k == b->sink.dpdm_cal.dz_k) &&
(a->sink.dpdm_cal.dz_b == b->sink.dpdm_cal.dz_b) &&
(a->sink.dpdm_cal.df_k == b->sink.dpdm_cal.df_k) &&
(a->sink.dpdm_cal.df_b == b->sink.dpdm_cal.df_b);
}
/*****************************************************************
函数名称: chrg_comm_copy_sink_config
函数描述: 将PC配置逐项应用到Sink,保留实际运行状态、旧测试模式和量测
@@ -2373,6 +2395,27 @@ static eMBException chrg_mb_write_sys(rt_uint8_t ch, rt_uint16_t reg_offset,
}
status = (switch_ret == 0) ? MB_EX_NONE : MB_EX_SLAVE_BUSY;
} else if (new_id == ID_SINK) {
/*
* D+/D-校准参数不是负载工作参数:上位机依次写入四个保持寄存器后,
* 必须单独写PARAM_EFFECT提交。若同时改了协议、CC或带载参数,
* 本次拒绝提交,避免校准写入抢占正在进行的负载状态机。
*/
if (!chrg_comm_sink_dpdm_cal_equal(pReal, pSW)) {
if (!chrg_comm_sink_config_equal(pReal, pSW)) {
status = MB_EX_SLAVE_BUSY;
} else if (chrg_roll_nor_sink_dpdm_cal_submit(ch, pReal,
&pSW->sink.dpdm_cal) != 0) {
status = MB_EX_SLAVE_BUSY;
} else {
pNOR->config_version[ch]++;
status = MB_EX_NONE;
}
if (status != MB_EX_NONE) {
g_shadow_dirty[ch] = 1;
}
rt_mutex_release(pTHR_NOR->mutex);
return status;
}
sink_config_changed = !chrg_comm_sink_config_equal(pReal, pSW);
old_sink_sub = pReal->sub;
old_sink_on = pReal->sink.On_work;
+4 -1
View File
@@ -429,6 +429,7 @@ static rt_bool_t chrg_north_frame_shape_valid(eIDX_ID id,
if (id == ID_SINK) {
switch (command) {
case SINK_CMD_RESET:
case SINK_CMD_SET_DPDM_CAL:
case SINK_CMD_SET_CC:
case SINK_CMD_SET_LEVEL:
case SINK_CMD_SET_QC20:
@@ -445,7 +446,9 @@ static rt_bool_t chrg_north_frame_shape_valid(eIDX_ID id,
case SINK_CMD_SET_VOOC:
case SINK_CMD_SET_AVS:
case LOAD_PRO_NONE:
return (length == MIN_FRAME_LENGTH) ? RT_TRUE : RT_FALSE;
return (command == SINK_CMD_SET_DPDM_CAL) ?
((length == 6U) ? RT_TRUE : RT_FALSE) :
((length == MIN_FRAME_LENGTH) ? RT_TRUE : RT_FALSE);
default:
return RT_FALSE;
}
+1 -1
View File
@@ -16,7 +16,7 @@
#include "chrg_def.h"
/* V_On启停判定电压源:切换后需重新编译固件。 */
#define SINK_VON_VOLTAGE_FROM_PROTOCOL 6U
#define SINK_VON_VOLTAGE_FROM_PROTOCOL 1U
#define SINK_VON_VOLTAGE_FROM_POWER 2U
#ifndef SINK_VON_VOLTAGE_SOURCE
#define SINK_VON_VOLTAGE_SOURCE SINK_VON_VOLTAGE_FROM_POWER
@@ -61,6 +61,17 @@ static rt_uint8_t g_sink_reset_next_sub[TOTAL_NOR_CHS] = {0};
/* 仅CC参数实际变化的通道才会断开D+/D-/CC,并在CC稳定后恢复。 */
static rt_uint8_t g_sink_cc_relay_close_mask = 0U;
static rt_uint8_t g_sink_cc_relay_restore_mask = 0U;
/* D+/D-校准写入任务按通道独立保存,避免与普通0x20轮询共用参数缓存。 */
struct sink_dpdm_cal_job_t {
struct sink_dpdm_cal_t cal;
rt_bool_t pending;
rt_uint8_t status;
};
#define SINK_DPDM_CAL_STATUS_IDLE 0U
#define SINK_DPDM_CAL_STATUS_PENDING 1U
#define SINK_DPDM_CAL_STATUS_SUCCESS 2U
#define SINK_DPDM_CAL_STATUS_TIMEOUT 0x80U
static struct sink_dpdm_cal_job_t g_sink_dpdm_cal_job[TOTAL_NOR_CHS] = {0};
/* Sink协议/CC握手期间的0x20查询节流记录,按通道独立计时。 */
static rt_bool_t g_sink_query_throttle[TOTAL_NOR_CHS] = {RT_FALSE};
static rt_bool_t g_sink_query_first_pending[TOTAL_NOR_CHS] = {RT_FALSE};
@@ -144,6 +155,29 @@ void chrg_roll_nor_sink_reset_cancel(rt_uint8_t ch)
g_sink_cc_relay_restore_mask &= (rt_uint8_t)~SOURCE_CHANNEL_BIT(ch);
}
rt_bool_t chrg_roll_nor_sink_dpdm_cal_pending(rt_uint8_t ch)
{
return (ch < TOTAL_NOR_CHS) && g_sink_dpdm_cal_job[ch].pending;
}
int chrg_roll_nor_sink_dpdm_cal_submit(rt_uint8_t ch,
struct chrg_switch_t *pSW, const struct sink_dpdm_cal_t *pCal)
{
if ((ch >= TOTAL_NOR_CHS) || (pSW == RT_NULL) || (pCal == RT_NULL)) {
return -1;
}
/* 校准写入只抢占普通量测,不能覆盖初始化、协议/CC切换等事务。 */
if (g_sink_dpdm_cal_job[ch].pending || (pSW->id != ID_SINK) ||
(pSW->sub != IDX_GET_SINK_VC)) {
return -2;
}
g_sink_dpdm_cal_job[ch].cal = *pCal;
g_sink_dpdm_cal_job[ch].pending = RT_TRUE;
g_sink_dpdm_cal_job[ch].status = SINK_DPDM_CAL_STATUS_PENDING;
pSW->sub = IDX_SET_SINK_DPDM_CAL;
return 0;
}
void chrg_roll_nor_sink_cc_switch_prepare(rt_uint8_t ch,
rt_bool_t cc_changed)
{
@@ -686,6 +720,8 @@ static rt_uint8_t chrg_roll_nor_expected_cmd(const struct chrg_switch_t *pSW)
return SINK_CMD_SET_CC;
case IDX_SET_SINK_CCLVL:
return SINK_CMD_SET_LEVEL;
case IDX_SET_SINK_DPDM_CAL:
return SINK_CMD_SET_DPDM_CAL;
default:
return 0;
}
@@ -729,8 +765,12 @@ static int chrg_roll_nor_response_matches(const struct mb_msg_t *pMB,
if ((expected_cmd == SRC_CMD_GET_VOLTAGE) && (pMB->length != 21U)) {
return -3;
}
if ((expected_cmd == SINK_CMD_SET_DPDM_CAL) && (pMB->length != 6U)) {
return -4;
}
if ((expected_cmd != SRC_CMD_GET_VOLTAGE) &&
(expected_cmd != SRC_CMD_GET_PROTOCOL) &&
(expected_cmd != SINK_CMD_SET_DPDM_CAL) &&
(pMB->length != MIN_FRAME_LENGTH)) {
return -4;
}
@@ -910,6 +950,11 @@ static int chrg_roll_nor_set(rt_uint8_t ch, struct chrg_switch_t *pSW,
return sink_set_cc_line(pSW->sink.cc_set);
case IDX_SET_SINK_CCLVL: //CC电平
return sink_set_cc_lvl(pSW->sink.cc_lvl);
case IDX_SET_SINK_DPDM_CAL:
if (!g_sink_dpdm_cal_job[ch].pending) {
return -1;
}
return sink_set_dpdm_cal(&g_sink_dpdm_cal_job[ch].cal);
case IDX_SET_SINK_PD:
/* 只有协议回码确认后,下一轮才允许进入电压查询。 */
*next_sub = IDX_WAIT_SINK_PD_ACK;
@@ -1030,6 +1075,26 @@ static int chrg_roll_nor_auto_request(rt_uint8_t idx,
g_sink_reset_next_sub[idx] = 0U;
advance_sub = RT_FALSE;
}
} else if ((expected_id == ID_SINK) &&
(request_sub == IDX_SET_SINK_DPDM_CAL)) {
/*
* 0x32回码格式:06 NC ID 32 STATUS CRC。
* 只有STATUS为0才把任务参数提交到实时结构;否则保留原参数,
* 并回到0x20普通量测状态,避免失败写入影响负载流程。
*/
g_sink_dpdm_cal_job[idx].pending = RT_FALSE;
g_sink_dpdm_cal_job[idx].status = pMB->payload[4];
pSW->sub = IDX_GET_SINK_VC;
advance_sub = RT_FALSE;
if (pMB->payload[4] == 0U) {
pSW->sink.dpdm_cal = g_sink_dpdm_cal_job[idx].cal;
g_sink_dpdm_cal_job[idx].status =
SINK_DPDM_CAL_STATUS_SUCCESS;
LOG_I("sink dpdm cal write success: ch=%d", idx + 1U);
} else {
LOG_E("sink dpdm cal write failed: ch=%d status=%u",
idx + 1U, pMB->payload[4]);
}
} else if ((expected_id == ID_SINK) &&
((request_sub == IDX_SET_SINK_CCLINE) ||
(request_sub == IDX_SET_SINK_CC_BEFORE_PD) ||
@@ -1053,6 +1118,16 @@ static int chrg_roll_nor_auto_request(rt_uint8_t idx,
LOG_W("north request failed: ch=%d id=%02x cmd=%02x sub=%d attempts=%d",
idx + 1U, expected_id, expected_cmd, request_sub,
max_attempts);
if ((expected_id == ID_SINK) &&
(request_sub == IDX_SET_SINK_DPDM_CAL)) {
rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
g_sink_dpdm_cal_job[idx].pending = RT_FALSE;
g_sink_dpdm_cal_job[idx].status = SINK_DPDM_CAL_STATUS_TIMEOUT;
if (pSW->sub == IDX_SET_SINK_DPDM_CAL) {
pSW->sub = IDX_GET_SINK_VC;
}
rt_mutex_release(pTHR->mutex);
}
return -1;
}
@@ -1152,6 +1227,18 @@ void chrg_roll_nor_thread_entry (void *data)
rt_thread_mdelay(2);
continue;
}
/* 校准写入任务不依赖通道运行使能,优先占用一次北向事务。 */
if (chrg_roll_nor_sink_dpdm_cal_pending(idx)) {
if ((chrg_north_switch((eIDX_NOR_CH)idx) == 0) &&
(chrg_north_request_begin((eIDX_NOR_CH)idx) != 0U)) {
pROLL->idx = idx;
(void)chrg_roll_nor_auto_request(idx, pSW,
pTHR, pTN, pNOR);
}
CHRG_CHANNEL_NEXT(index);
rt_thread_mdelay(NORTH_POLL_INTERVAL_MS);
continue;
}
if (source_waiting || sink_waiting) {
CHRG_CHANNEL_NEXT(index);
rt_thread_mdelay(2);
+11 -1
View File
@@ -11,6 +11,9 @@
#include <rtthread.h>
struct chrg_switch_t;
struct sink_dpdm_cal_t;
#define THR_NAME_ROLL_NOR "thr.rollnor"
#define STATE_WORKING 0x03//运行标志位
enum {
@@ -41,7 +44,8 @@ enum {
IDX_SET_SINK_CC_BEFORE_PD_WITH_MODE,
IDX_WAIT_SINK_CC_BEFORE_PD_WITH_MODE,
IDX_SET_SINK_MODE_AFTER_PD,
IDX_WAIT_SINK_MODE_AFTER_PD
IDX_WAIT_SINK_MODE_AFTER_PD,
IDX_SET_SINK_DPDM_CAL // 上位机校准参数写入Sink板0x32
};
struct chrg_rollnor_t {
@@ -112,6 +116,12 @@ extern void chrg_roll_nor_sink_cc_switch_prepare(rt_uint8_t ch,
/* 低电流确认完成后,按登记结果断开D+/D-/CC继电器。 */
extern void chrg_roll_nor_sink_cc_relay_close(rt_uint8_t ch);
/* 提交Sink板D+/D-校准参数写入任务;仅空闲量测状态允许提交。 */
extern int chrg_roll_nor_sink_dpdm_cal_submit(rt_uint8_t ch,
struct chrg_switch_t *pSW, const struct sink_dpdm_cal_t *pCal);
/* 查询指定通道是否存在待执行的D+/D-校准写入任务。 */
extern rt_bool_t chrg_roll_nor_sink_dpdm_cal_pending(rt_uint8_t ch);
#define sink_time 3
#endif
+1 -2
View File
@@ -14,8 +14,7 @@
/* CHRG application version. Keep this value synchronized with the changelog. */
#define CHRG_VERSION_MAJOR 1U
#define CHRG_VERSION_MINOR 1U
#define CHRG_VERSION_PATCH 55U
#define CHRG_VERSION_STRING "V1.1.55"
/*
* Channel polling mode:
+6
View File
@@ -152,6 +152,12 @@ enum {
#define SINK_REG_DYNA_TIME2 0x1C // 负载2保持时间 (0.01ms)
#define SINK_REG_DYNA_SLOPE 0x1D // 动态加载斜率 (0.001A/us)
#define SINK_REG_DYNA_UNLOAD 0x1E // 动态卸载斜率 (0.001A/us)
/* D+/D-校准参数:K为无符号16位(实际比例系数×10000),B为有符号16位(0.01V)。
* 上位机写完四项后,写本通道SYS_REG_PARAM_EFFECT=1,由405转发Sink 0x32。 */
#define SINK_REG_DPDM_DZ_K 0x1F // D+ K
#define SINK_REG_DPDM_DZ_B 0x20 // D+ B
#define SINK_REG_DPDM_DF_K 0x21 // D- K
#define SINK_REG_DPDM_DF_B 0x22 // D- B
// ---- 电源(Source)参数偏移 (相对通道基地址: HOLD_REG_SRC_BASE + ch*6) ----
#define SRC_REG_PROTOCOL 0x00 // 协议类型
+27
View File
@@ -302,6 +302,33 @@ int sink_set_pd (rt_uint8_t pd, rt_uint8_t *buf)
return chrg_north_send(frame, len);
}
/*****************************************************************
函数名称: sink_set_dpdm_cal
函数描述: 向Sink协议板写入D+/D-校准参数
输入参数: pCal:四个16位校准参数
输出参数: -
返回说明: <0:发送失败 >0:发送长度
其它说明: 所有字段按高字节在前发送;B按int16_t补码原样发送
*****************************************************************/
int sink_set_dpdm_cal(const struct sink_dpdm_cal_t *pCal)
{
rt_uint16_t len = 0U;
rt_uint8_t data[8] = {0};
rt_uint8_t frame[16] = {0};
if (pCal == RT_NULL) {
return -1;
}
u16_to_u8v(pCal->dz_k, &data[0]);
u16_to_u8v((rt_uint16_t)pCal->dz_b, &data[2]);
u16_to_u8v(pCal->df_k, &data[4]);
u16_to_u8v((rt_uint16_t)pCal->df_b, &data[6]);
/* 发送帧:0D NC 01 32 DZ_K DZ_B DF_K DF_B CRC,四个16位字段均为大端。 */
chrg_north_pkg_encode(ID_SINK, SINK_CMD_SET_DPDM_CAL,
data, sizeof(data), frame, &len);
return chrg_north_send(frame, len);
}
static rt_uint8_t chrg_sink_init_build_commands(struct chrg_switch_t *pSW,
rt_uint16_t *regs, rt_uint16_t *vals)
{
+20 -1
View File
@@ -71,7 +71,15 @@ struct test
#define SINK_CMD_GET_VOLTAGE 0x20 // 读取变电压板电压
#define SINK_CMD_RESET 0x01 // 复位Sink协议板
#define SINK_CMD_SET_DPDM_CAL 0x32 // 写入D+/D-校准参数
/* D+/D-校准系数:K为实际比例系数放大10000倍,B单位为0.01V。 */
struct sink_dpdm_cal_t {
rt_uint16_t dz_k;
rt_int16_t dz_b;
rt_uint16_t df_k;
rt_int16_t df_b;
};
struct sink_vc_t {
rt_uint8_t voltage; // 电压 0.01V
@@ -215,7 +223,7 @@ enum {
/* Sink电压稳定确认参数,供chrg_sink_volt_judge使用。 */
#define SINK_VOLT_5V_TARGET_MV 5000U
#define SINK_VOLT_CONFIRM_NORMAL_COUNT 3U
#define SINK_VOLT_CONFIRM_5V_COUNT 12U
#define SINK_VOLT_CONFIRM_5V_COUNT 3U
#define SINK_CURRENT_START_GRACE_MS 200U
/* 主继电器闭合后的0V持续监控:由北向轮询线程每轮调用,掉电立即转掉电保护。 */
@@ -266,6 +274,7 @@ struct chrg_sink_t {
rt_uint8_t change_cv_flag;
rt_uint8_t change_source_flag; // 从sink切换到source标志位
rt_uint8_t work_mode; // 0=停止 1=工作 2=低电压
struct sink_dpdm_cal_t dpdm_cal; // 上位机待写入Sink板的D+/D-校准参数
};
//纹波寄存器
@@ -408,6 +417,16 @@ extern int sink_set_cc_lvl (rt_uint8_t lvl);
其它说明: -
*****************************************************************/
extern int sink_set_pd (rt_uint8_t pd, rt_uint8_t *buf);
/*****************************************************************
函数名称: sink_set_dpdm_cal
函数描述: 向Sink协议板写入D+/D-校准参数
输入参数: pCal:四个16位校准参数
输出参数: -
返回说明: <0:发送失败 >0:发送长度
其它说明: 发送0x32;K为×10000,B为0.01V有符号补码
*****************************************************************/
extern int sink_set_dpdm_cal(const struct sink_dpdm_cal_t *pCal);
// ===================== 负载测试函数声明 =====================
extern void sink_test_short_set (struct chrg_switch_t *pSW, rt_uint8_t *pData, rt_uint8_t run_flag);
extern void sink_test_ocp_set (struct chrg_switch_t *pSW, rt_uint8_t *pData, rt_uint8_t run_flag);
+10
View File
@@ -1,5 +1,15 @@
# 修改日志
## V1.1.56 - 2026-10-09
### Sink板D+/D-校准参数写入
- 增加每通道四个16位D+/D-校准参数:D+K、D+B、D-K、D-B;K按10000倍传递,B为0.01V有符号值。
- 上位机写入参数并触发原有 `PARAM_EFFECT` 后,405通过北向Sink板 `0x32` 指令写入参数。
- 写入任务复用北向通道切换、事务号和回码校验;仅在通道空闲量测状态提交,完成后恢复普通轮询。
- 本版本不包含 `0x31` 采样、`0x33` 读取、`0x34` 恢复和五点拟合。
- 协议板版本寄存器 `0x0300` 更新为 `0x0148`。
## V1.1.55 - 2026-10-09
### Sink协议切换复位开关