Merge pull request 'Feature' (#2) from feature into master
Reviewed-on: chrg/chrg#2
This commit is contained in:
@@ -166,6 +166,56 @@ void MX_USART_DeInit (void)
|
||||
HAL_UART_DeInit(&huart2);
|
||||
}
|
||||
|
||||
static void boot_JumpToAPP (void)
|
||||
{
|
||||
static uint32_t _stack_addr; /* APP 栈顶地址 */
|
||||
static uint32_t _reset_handler; /* APP reset handler 地址 */
|
||||
typedef void(*APP_MAIN_FUNC)(void);
|
||||
APP_MAIN_FUNC APP_Main;
|
||||
|
||||
_stack_addr = *(volatile uint32_t *)BASE_APPLICATION;
|
||||
_reset_handler = *(volatile uint32_t *)(BASE_APPLICATION + 4);
|
||||
|
||||
/* 设置所有时钟到默认状态,使用HSI时钟 */
|
||||
HAL_RCC_DeInit();
|
||||
|
||||
/* 关闭全局中断 */
|
||||
__disable_irq();
|
||||
|
||||
/* 关闭滴答定时器,复位到默认值 */
|
||||
SysTick->CTRL = 0;
|
||||
SysTick->LOAD = 0;
|
||||
SysTick->VAL = 0;
|
||||
|
||||
/* 关闭所有中断,清除所有中断挂起标志 */
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
NVIC->ICER[i] = 0xFFFFFFFF;
|
||||
NVIC->ICPR[i] = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
/* 外设 deinit */
|
||||
HAL_DeInit();
|
||||
MX_USART_DeInit();
|
||||
MX_DMA_DeInit();
|
||||
|
||||
|
||||
/* 设置主堆栈指针 */
|
||||
__set_MSP(_stack_addr);
|
||||
|
||||
/* 在 RTOS 工程,这条语句很重要,设置为特权级模式,使用 MSP 指针 */
|
||||
__set_CONTROL(0);
|
||||
|
||||
/* 设置中断向量表 */
|
||||
SCB->VTOR = BASE_APPLICATION;
|
||||
|
||||
/* 跳转到 APP ,首地址是 MSP ,地址 +4 是复位中断服务程序地址 */
|
||||
APP_Main = (APP_MAIN_FUNC)_reset_handler;
|
||||
APP_Main();
|
||||
|
||||
/* 复位或跳转成功的话,不会执行到这里 */
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
|
||||
int main (void)
|
||||
{
|
||||
@@ -190,9 +240,10 @@ int main (void)
|
||||
VERSION_MAIN, VERSION_SUB, VERSION_FIX, BUILD_TIMESTAMP);
|
||||
#endif
|
||||
APP_Init();
|
||||
|
||||
boot_JumpToAPP();
|
||||
while (1) {
|
||||
APP_Running();
|
||||
|
||||
//APP_Running();
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
@@ -32,18 +32,18 @@
|
||||
#define GPO_PIN_CH1_P2 GET_PIN(C, 1) // P2 connect K5 for GND/PGND
|
||||
|
||||
// 北向继电器2组
|
||||
#define GPO_PIN_CH2_P0 GET_PIN(A, 5) // P0
|
||||
#define GPO_PIN_CH2_P1 GET_PIN(A, 4) // P1
|
||||
#define GPO_PIN_CH2_P0 GET_PIN(A, 5) // P0 //SINK D+D- CC
|
||||
#define GPO_PIN_CH2_P1 GET_PIN(A, 4) // P1 //SOURCE D+D- CC
|
||||
#define GPO_PIN_CH2_P2 GET_PIN(A, 1) // P2
|
||||
|
||||
// 北向继电器3组
|
||||
#define GPO_PIN_CH3_P0 GET_PIN(C, 5) // P0
|
||||
#define GPO_PIN_CH3_P1 GET_PIN(C, 4) // P1
|
||||
#define GPO_PIN_CH3_P0 GET_PIN(C, 5) // P0 //SINK D+D- CC
|
||||
#define GPO_PIN_CH3_P1 GET_PIN(C, 4) // P1 //SOURCE D+D- CC
|
||||
#define GPO_PIN_CH3_P2 GET_PIN(A, 7) // P2
|
||||
|
||||
// 北向继电器4组
|
||||
#define GPO_PIN_CH4_P0 GET_PIN(B, 15) // P0
|
||||
#define GPO_PIN_CH4_P1 GET_PIN(B, 14) // P1
|
||||
#define GPO_PIN_CH4_P0 GET_PIN(B, 15) // P0 //SINK D+D- CC
|
||||
#define GPO_PIN_CH4_P1 GET_PIN(B, 14) // P1 //SOURCE D+D- CC
|
||||
#define GPO_PIN_CH4_P2 GET_PIN(B, 13) // P2
|
||||
|
||||
// 北向通信口选通 U14
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
文件名称 : chrg_comm.h
|
||||
完成日期 :
|
||||
当前版本号 : V1.0
|
||||
当前版本号 : V1.1.9
|
||||
主要功能 : 实现对外通讯协议 MODBUS 服务端,以独立线程等待处理响应请求数据。
|
||||
版本历史 : 创建原始版本
|
||||
说明 :
|
||||
@@ -19,23 +19,8 @@
|
||||
|
||||
#define MB_HANDLERS_MAX (16)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
//北向协议设置
|
||||
rt_uint8_t proto_changed;
|
||||
rt_uint8_t group_changed;
|
||||
rt_uint16_t pro_volt_changed;
|
||||
rt_uint16_t pro_curr_changed;
|
||||
//南向功率设置
|
||||
rt_uint8_t volt_changed;
|
||||
rt_uint8_t curr_changed;
|
||||
rt_uint8_t ccset_changed;
|
||||
rt_uint8_t cvmode_changed;
|
||||
} sink_proto_diff_t;
|
||||
static void chrg_sink_get_proto_diff(struct chrg_switch_t *pReal,
|
||||
struct chrg_switch_t *pShadow,
|
||||
sink_proto_diff_t *pDiff,
|
||||
rt_uint8_t *pNoChange);
|
||||
/* 北向Source协议设置成功后,通知COM保存本通道的PD/非PD类别。 */
|
||||
extern void chrg_comm_source_protocol_ack(rt_uint8_t ch, rt_uint8_t protocol);
|
||||
|
||||
typedef enum {
|
||||
MB_REG_READ, /*!< Read register values and pass to protocol stack. */
|
||||
@@ -228,8 +213,6 @@ extern void chrg_comm_thread_entry (void *data);
|
||||
|
||||
extern rt_uint8_t chrg_com_sink_on(rt_uint8_t ch, struct chrg_switch_t *pSW, rt_uint8_t *enable);
|
||||
extern rt_uint8_t chrg_com_source_on(rt_uint8_t ch, rt_uint8_t protoCmd, struct chrg_switch_t *pSW, rt_uint8_t *enable);
|
||||
extern void chrg_sink_diff_send_reg(eIDX_SOU_CH ch, sink_proto_diff_t *pDiff, struct chrg_switch_t *pReal);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
//关闭
|
||||
@@ -235,14 +212,16 @@ static int chrg_lcd_parse (rt_uint8_t *recv, rt_uint16_t len)
|
||||
Recv_Data = recv[LCD_IDX_VAL+1]<<8 | recv[LCD_IDX_VAL]; // 拼接16位电压值
|
||||
pSW = &pNOR->sw[ch];
|
||||
// 按角色存入source/sink
|
||||
pSW->source.vc.set_voltage = Recv_Data; // 电源侧电压(mV)
|
||||
pSW->source.pd_set.mm.max_vol = Recv_Data; // 电源协议目标电压(mV)
|
||||
pSW->source.set_volt = Recv_Data; // 当前准备写入功率板的电压目标
|
||||
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);
|
||||
/* Sink保留原直接设置方式;Source电压必须统一经过RUNING状态补偿后下发。 */
|
||||
if (pSW->id == ID_SINK) {
|
||||
chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_VOLTAGE_OUT + 1, Recv_Data);
|
||||
} else if (pSW->source.On_Flag == 1) {
|
||||
pSW->source.work_mode = SOURCE_WORK_RUNING;
|
||||
(void)chrg_source_work_state(ch, pSW);
|
||||
}
|
||||
else chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_VOLTAGE_OUT+1, 5000);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -255,9 +234,9 @@ static int chrg_lcd_parse (rt_uint8_t *recv, rt_uint16_t len)
|
||||
Recv_Data = recv[LCD_IDX_VAL+1]<<8 | recv[LCD_IDX_VAL]; // 拼接16位电流值
|
||||
pSW = &pNOR->sw[ch];
|
||||
//按角色存入source/sink
|
||||
pSW->source.vc.set_current = Recv_Data; // 电源侧电流(mA)
|
||||
pSW->source.pd_set.mm.max_cur = Recv_Data; // 电源协议最大电流(mA)
|
||||
pSW->source.set_curr = Recv_Data; // 当前准备写入功率板的电流目标
|
||||
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++){
|
||||
@@ -390,7 +369,9 @@ void chrg_lcd_thread_entry (void *data)
|
||||
return ;
|
||||
}
|
||||
|
||||
#if LCD_RX_ENABLE
|
||||
int len = 0;
|
||||
#endif
|
||||
struct chrg_tty_t *pTTY = RT_NULL;
|
||||
struct chrg_lcd_t *pLCD = &chrglcd;
|
||||
pTTY = chrg_tty_create(pLCD->devname, 921600, 0, -1, 1);
|
||||
@@ -398,8 +379,10 @@ void chrg_lcd_thread_entry (void *data)
|
||||
LOG_E("tty can't create.");
|
||||
return ;
|
||||
}
|
||||
|
||||
#if LCD_RX_ENABLE
|
||||
/* LCD接收功能开启时,最多等待100ms屏幕回传数据。 */
|
||||
chrg_tty_set_recv_tmo(pTTY, 100);
|
||||
#endif
|
||||
if (chrg_tty_connect(pTTY) != RT_EOK) {
|
||||
chrg_tty_destory(pTTY);
|
||||
return;
|
||||
@@ -407,6 +390,12 @@ void chrg_lcd_thread_entry (void *data)
|
||||
|
||||
pLCD->tty = pTTY;
|
||||
|
||||
#if LCD_RX_ENABLE
|
||||
/*
|
||||
* 保留原LCD接收及控制解析流程,需要恢复屏幕控制时只需将
|
||||
* LCD_RX_ENABLE改为1。接收关闭时本段不参与编译,避免chrg_tty_recv
|
||||
* 在等待回传期间持有TTY锁并阻塞chrg_lcd_send。
|
||||
*/
|
||||
while (1) {
|
||||
rt_memset(pLCD->rx_buf, 0, SIZE_BUF_TTY);
|
||||
len = chrg_tty_recv(pTTY, pLCD->rx_buf, sizeof(pLCD->rx_buf));
|
||||
@@ -420,6 +409,15 @@ void chrg_lcd_thread_entry (void *data)
|
||||
chrg_lcd_parse(pLCD->rx_buf, len);
|
||||
}
|
||||
}
|
||||
#else
|
||||
/*
|
||||
* 仅发送模式仍保留LCD线程和串口实例。线程低频休眠且不访问TTY,
|
||||
* 量测解析中的LCD发送可以直接取得TTY锁,不再受100ms接收超时影响。
|
||||
*/
|
||||
while (1) {
|
||||
rt_thread_mdelay(1000);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
#define THR_NAME_LCD "thr.lcd"
|
||||
#define DEV_NAME_LCD "uart2"
|
||||
|
||||
/* LCD发送保持启用;当前产品不使用屏幕回传控制,关闭接收可避免接收线程持有TTY锁阻塞量测上报。 */
|
||||
#define LCD_RX_ENABLE 0
|
||||
|
||||
|
||||
#define LCD_FRAME_HEAD 0x55
|
||||
|
||||
@@ -45,7 +48,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);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -19,15 +19,20 @@
|
||||
#define THR_NAME_NORTH "thr.nor"
|
||||
#define DEV_NAME_NORTH "uart3"
|
||||
|
||||
#define LEN_FRAME_HEAD (3) // [帧长, 0x00, id]
|
||||
#define LEN_FRAME_HEAD (4) // [帧长, 0x00, id, 命令]
|
||||
#define MIN_FRAME_LENGTH (5) // 帧最短5字节
|
||||
#define WORK_MIN_VOLT 3000 // 工作电压下限,单位mV
|
||||
#define DEBUG_NORTH 0x00 // 0 = 关闭,1 = 开启
|
||||
#define NORTH_FRAME_DEBUG 0x00 // 北向UART原始收发帧
|
||||
#define NORTH_SOURCE_DEBUG 0x01 // Source协议解析及组帧
|
||||
#define NORTH_SINK_DEBUG 0x00 // Sink协议解析及组帧
|
||||
#define SOUTH_FRAME_DEBUG 0x00 // 南向UART原始收发帧
|
||||
#define SOUTH_COMMAND_DEBUG 0x01 // 南向寄存器写命令
|
||||
#define COMM_FRAME_DEBUG 0x00 // COM UART原始收发帧
|
||||
#define COMM_DEBUG 0x00 // COM寄存器读写过程
|
||||
#define COMM_TRIM_DEBUG 0x00 // COM校准参数解析
|
||||
#define LCD_OPEN 0x01 // 0为关闭屏幕显示 1为打开
|
||||
#define TRIM_NORTH 0x00 // 0 = 关闭, 1 = 开启
|
||||
#define SINK_TEST_DEBUG 0x00 // 0 = 关闭,1 = 开启
|
||||
#define PRO_TEST_DEBUG 0x00 //
|
||||
#define DEBUG_SOUTH 0x00 // 0 = 关闭,1 = 开启
|
||||
// 北向4通路索引 U14 ->
|
||||
typedef enum {
|
||||
IDX_NOR_CH1 = IDX_CH1, // J3
|
||||
@@ -95,7 +100,6 @@ struct chrg_trim {
|
||||
rt_int16_t trim_source_curr_b; // 校准电源电流值b mA
|
||||
rt_int16_t trim_zero; // 校准飘零值 mV/mA
|
||||
rt_uint8_t trim_mode; // 校准模式, 0-默认值,1-校准电压,2-校准电流,3-校准电源电流
|
||||
rt_uint8_t trim_step;
|
||||
rt_uint8_t trim_enable_flag; //0就是默认写用户区,1则写出场数据区
|
||||
};
|
||||
|
||||
@@ -105,6 +109,7 @@ struct chrg_north_t {
|
||||
struct chrg_tty_t *tty;
|
||||
struct rt_ringbuffer *rb;
|
||||
struct pickup_info_t frame;
|
||||
rt_uint32_t config_version[TOTAL_NOR_CHS]; // COM配置版本,用于识别等待期间到达的旧回码
|
||||
struct chrg_trim trim[TOTAL_NOR_CHS];
|
||||
rt_uint8_t rx_buf[SIZE_BUF_TTY];
|
||||
rt_uint8_t free_flag;
|
||||
@@ -112,11 +117,34 @@ struct chrg_north_t {
|
||||
rt_uint8_t manual; // 手动插入命令
|
||||
eIDX_NOR_CH idx; // 当前通路
|
||||
struct chrg_switch_t sw[TOTAL_NOR_CHS];
|
||||
rt_uint8_t north_mode; // 0-正常模式, 1-校准模式
|
||||
};
|
||||
|
||||
extern struct chrg_north_t chrgnorth;
|
||||
|
||||
/*****************************************************************
|
||||
函数名称: chrg_source_parse
|
||||
函数描述: 解析Source的0x20电压电流回码并驱动电源状态机
|
||||
输入参数: frame_data:已通过CRC校验的完整回码 idx:对应通道
|
||||
pSW:通道控制结构体 pNOR:北向控制结构体
|
||||
输出参数: 更新Source目标电压、电流和工作状态
|
||||
返回说明: 0:回码正常 <0:参数错误、Source切换错误或功率命令提交失败
|
||||
其它说明: 仅由北向轮询线程在确认回码角色、命令和通道匹配后调用
|
||||
*****************************************************************/
|
||||
extern int chrg_source_parse(rt_uint8_t *frame_data, eIDX_SOU_CH idx,
|
||||
struct chrg_switch_t *pSW, struct chrg_north_t *pNOR);
|
||||
|
||||
/*****************************************************************
|
||||
函数名称: chrg_sink_parse
|
||||
函数描述: 解析Sink的0x20电压电流回码并驱动负载状态机
|
||||
输入参数: frame_data:已通过CRC校验的完整回码 idx:对应通道
|
||||
pSW:通道控制结构体 pNOR:北向控制结构体
|
||||
输出参数: 更新Sink协议量测值和工作状态
|
||||
返回说明: -
|
||||
其它说明: 仅由北向轮询线程在确认回码角色、命令和通道匹配后调用
|
||||
*****************************************************************/
|
||||
extern void chrg_sink_parse(rt_uint8_t *frame_data, eIDX_SOU_CH idx,
|
||||
struct chrg_switch_t *pSW, struct chrg_north_t *pNOR);
|
||||
|
||||
/*****************************************************************
|
||||
函数名称: chrg_north_switch
|
||||
函数描述: 北向通道选择
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
文件名称 : chrg_roll_nor.h
|
||||
完成日期 :
|
||||
当前版本号 : V1.0
|
||||
当前版本号 : V1.1.9
|
||||
主要功能 : 实现北向通信轮巡请求命令。以独立线程处理。
|
||||
版本历史 : 创建原始版本
|
||||
说明 :
|
||||
@@ -41,6 +41,20 @@ enum {
|
||||
IDX_SET_SINK_WORK_STATE,
|
||||
IDX_SET_SINK_STOP_TEST,//停止负载测试
|
||||
IDX_SET_SINK_STORP_WAIT,
|
||||
|
||||
/* Source北向事务状态,追加在末尾以保持原有sub数值不变。 */
|
||||
IDX_SET_SOURCE_RESET, // PD与非PD协议跨类切换前发送Source复位
|
||||
IDX_WAIT_SOURCE_PROTOCOL, // 0xD0应答后的协议生效等待
|
||||
|
||||
/* Sink北向事务状态追加在末尾,避免改变已有sub数值。 */
|
||||
IDX_SET_SINK_PD_ONLY, // 仅重发协议,协议应答后直接查询协商电压
|
||||
IDX_WAIT_SINK_CC, // CC设置应答后的非阻塞稳定等待
|
||||
IDX_SET_SINK_CC_BEFORE_PD, // 先设置CC,稳定后再设置协议
|
||||
IDX_WAIT_SINK_CC_BEFORE_PD, // 等待CC稳定后进入协议设置
|
||||
IDX_WAIT_SINK_PD_ACK, // 协议回码确认后的非发送过渡状态
|
||||
#if 0
|
||||
IDX_SET_SINK_PD_BEFORE_CC, // 先设置协议,协议回码后再设置CC
|
||||
#endif
|
||||
};
|
||||
|
||||
struct chrg_rollnor_t {
|
||||
@@ -80,8 +94,26 @@ extern struct chrg_rollnor_t chrgrollnor;
|
||||
extern void chrg_roll_nor_thread_entry (void *data);
|
||||
extern int sink_fill_pd_buf(rt_uint8_t group,rt_uint8_t pd_val, rt_uint16_t pd_volt, rt_uint16_t pd_curr, rt_uint8_t *buf);
|
||||
|
||||
extern void chrg_roll_trim_set(rt_uint8_t ch, struct chrg_north_t *pNOR);
|
||||
extern void roll_nor_set(void);
|
||||
|
||||
/*****************************************************************
|
||||
函数名称: chrg_roll_nor_source_cc_close_register
|
||||
函数描述: 将Source通道登记到本轮共享CC_CLOSE等待屏障
|
||||
输入参数: ch:北向通道编号
|
||||
输出参数: -
|
||||
返回说明: -
|
||||
其它说明: 仅需要在协议切换入口为IDX_SET_SOURCE_CC_CLOSE时调用
|
||||
*****************************************************************/
|
||||
/*****************************************************************
|
||||
函数名称: chrg_roll_nor_source_switch_reset
|
||||
函数描述: 清理指定Source通道的CC_CLOSE及协议等待记录
|
||||
输入参数: ch:北向通道编号
|
||||
输出参数: -
|
||||
返回说明: -
|
||||
其它说明: 停止、角色切换或新配置覆盖旧切换状态时调用
|
||||
*****************************************************************/
|
||||
extern void chrg_roll_nor_source_switch_reset(rt_uint8_t ch);
|
||||
|
||||
#define sink_time 3
|
||||
#endif
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,11 +12,13 @@
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
struct chrg_trim;
|
||||
|
||||
#define THR_NAME_ROLL_SOU "thr.rollsou"
|
||||
|
||||
// 单通道批量下发缓存:保存当前需要同步的寄存器列表
|
||||
#define SOU_COM_BATCH_REG_MAX 16
|
||||
/* 为连续提交初始化、普通启动和动态启动命令预留足够空间。 */
|
||||
#define SOU_COM_BATCH_REG_MAX 32
|
||||
typedef struct
|
||||
{
|
||||
rt_uint16_t reg_cnt; // 当前待下发寄存器数量
|
||||
@@ -24,6 +26,8 @@ typedef struct
|
||||
rt_uint16_t val_list[SOU_COM_BATCH_REG_MAX]; // 对应寄存器值数组
|
||||
rt_uint8_t cur_idx; // 当前下发到第几条
|
||||
rt_bool_t pending; // 本通道有待下发批量指令
|
||||
rt_int8_t result; // 0:执行中/无结果 1:成功 -1:失败取消
|
||||
rt_tick_t next_send_tick; // 非0时下一条命令不得早于该tick发送
|
||||
} sou_com_batch_ch_t;
|
||||
|
||||
// COM批量下发总控结构体
|
||||
@@ -46,9 +50,10 @@ struct chrg_rollsou_t {
|
||||
rt_uint16_t reg; // LCD 触发时,寄存器地址
|
||||
rt_uint16_t value; // LCD 触发时,寄存器值
|
||||
|
||||
rt_uint8_t *updata_data;//南向升级的数据
|
||||
rt_uint16_t leng;
|
||||
rt_uint8_t send_flag; //发送标志位
|
||||
rt_uint8_t updata_buf[YMODEM_STX_SIZE];/* 南向升级帧缓存,避免上层缓冲区被提前覆盖 */
|
||||
rt_uint16_t leng; /* 当前待发送升级帧的实际长度 */
|
||||
rt_int16_t updata_result;/* 最近一次升级帧发送结果 */
|
||||
rt_uint8_t send_flag; /* 1:升级帧待发送或正在发送,0:允许提交下一帧 */
|
||||
rt_uint8_t mode;// 0 为正常轮询,1为升级,2为校准
|
||||
};
|
||||
|
||||
@@ -82,9 +87,56 @@ extern void chrg_set_sou_reg_com (eIDX_SOU_CH idx, rt_uint16_t reg, rt_uint16_t
|
||||
*****************************************************************/
|
||||
extern void chrg_roll_sou_thread_entry (void *data);
|
||||
|
||||
extern void chrg_send_sou_upadata_data (rt_uint8_t *buf,rt_uint16_t leng);
|
||||
extern void chrg_sou_com_sou_set(void);
|
||||
/*****************************************************************
|
||||
函数名称: chrg_send_sou_upadata_data
|
||||
函数描述: 将一帧升级数据复制到南向升级缓存并唤醒升级发送分支
|
||||
输入参数: buf:升级帧数据 leng:升级帧长度
|
||||
输出参数: -
|
||||
返回说明: 0:提交成功 -1:参数错误 -2:上一帧尚未发送 -3:互斥锁超时
|
||||
其它说明: 数据在函数内完成复制,调用者返回后可以立即复用原缓冲区
|
||||
*****************************************************************/
|
||||
extern int chrg_send_sou_upadata_data(const rt_uint8_t *buf, rt_uint16_t leng);
|
||||
extern int chrg_sou_com_batch_add_reg(eIDX_SOU_CH ch, rt_uint16_t reg, rt_uint16_t val);
|
||||
extern int chrg_sou_com_batch_submit(eIDX_SOU_CH ch, const rt_uint16_t *regs,
|
||||
const rt_uint16_t *vals, rt_uint8_t count);
|
||||
/*****************************************************************
|
||||
函数名称: chrg_sou_com_batch_cancel
|
||||
函数描述: 取消指定通道尚未完成的南向COM批次
|
||||
输入参数: ch:南向功率板通道
|
||||
输出参数: -
|
||||
返回说明: 0:批次已取消 <0:参数或互斥锁错误
|
||||
其它说明: 已发送到功率板的当前命令无法撤回,但其后续未发送命令将被清除;
|
||||
当前命令的迟到回码会按批次已变更处理,不再推进旧批次
|
||||
*****************************************************************/
|
||||
extern int chrg_sou_com_batch_cancel(eIDX_SOU_CH ch);
|
||||
extern rt_bool_t chrg_sou_com_batch_is_pending(eIDX_SOU_CH ch);
|
||||
/*****************************************************************
|
||||
函数名称: chrg_sou_com_batch_get_result
|
||||
函数描述: 获取指定通道最近一次南向COM批次的执行结果
|
||||
输入参数: ch:南向功率板通道
|
||||
输出参数: -
|
||||
返回说明: 1:全部命令收到匹配回码 0:执行中/无结果 -1:失败取消 -2:参数或锁错误
|
||||
其它说明: 用于区分pending清零是正常完成还是重试耗尽后的失败取消
|
||||
*****************************************************************/
|
||||
extern int chrg_sou_com_batch_get_result(eIDX_SOU_CH ch);
|
||||
/*****************************************************************
|
||||
函数名称: chrg_sou_measure_once_submit
|
||||
函数描述: 请求南向线程优先查询指定通道的一帧P1量测数据
|
||||
输入参数: ch:南向功率板通道
|
||||
输出参数: -
|
||||
返回说明: 0:请求成功或已存在同通道请求 <0:参数或互斥锁错误
|
||||
其它说明: 只登记一次性请求,实际切通道、发送0x03和解析仍由南向线程完成
|
||||
*****************************************************************/
|
||||
extern int chrg_sou_measure_once_submit(eIDX_SOU_CH ch);
|
||||
/*****************************************************************
|
||||
函数名称: chrg_sou_trim_submit
|
||||
函数描述: 根据校准类型组装功率板校准指令并提交到南向COM队列
|
||||
输入参数: ch:南向功率板通道 pTrim:已解析的校准参数
|
||||
输出参数: -
|
||||
返回说明: 0:提交成功 <0:参数、校准模式或队列提交失败
|
||||
其它说明: 实际发送、应答校验和重试由RUN_COM分支统一管理
|
||||
*****************************************************************/
|
||||
extern int chrg_sou_trim_submit(eIDX_SOU_CH ch, const struct chrg_trim *pTrim);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#define DBG_LEVEL DBG_LOG
|
||||
#include <rtdbg.h>
|
||||
|
||||
#define SOUTH_FRAME_TIMEOUT_MS 100
|
||||
|
||||
#define MB_ACK_HEAD_SIZE 3 // modbus 响应头3字节
|
||||
|
||||
struct chrg_south_t chrgsouth = {
|
||||
@@ -157,6 +159,9 @@ int chrg_south_send (rt_uint8_t *data, rt_size_t length)
|
||||
struct chrg_tty_t *pTTY = chrgsouth.tty;
|
||||
|
||||
if (RT_NULL != pTTY) {
|
||||
#if SOUTH_FRAME_DEBUG
|
||||
LOG_HEX("sendS", 32, data, length);
|
||||
#endif
|
||||
ret = chrg_tty_send(pTTY, data, length);
|
||||
}
|
||||
return ret;
|
||||
@@ -183,7 +188,9 @@ static int chrg_south_frame_head (struct rt_ringbuffer *rb, rt_uint8_t *head, eI
|
||||
|
||||
len_rb = rt_ringbuffer_data_len(rb);
|
||||
if (len_rb < MB_ACK_HEAD_SIZE) { // 帧头3字节
|
||||
#if SOUTH_FRAME_DEBUG
|
||||
rt_kprintf("len_rb=:%d",len_rb);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -249,10 +256,70 @@ static int chrg_south_frame_head (struct rt_ringbuffer *rb, rt_uint8_t *head, eI
|
||||
返回说明: <0: 错误 >0:帧长度
|
||||
其它说明: -
|
||||
*****************************************************************/
|
||||
static void chrg_south_frame_reset(struct pickup_info_t *pFrame, rt_bool_t release)
|
||||
{
|
||||
if (RT_NULL == pFrame) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (release && (RT_NULL != pFrame->pMB)) {
|
||||
if (RT_NULL != pFrame->pMB->payload) {
|
||||
rt_free(pFrame->pMB->payload);
|
||||
}
|
||||
rt_free(pFrame->pMB);
|
||||
}
|
||||
|
||||
pFrame->last_tick = 0;
|
||||
pFrame->length = 0;
|
||||
pFrame->findhead = 0;
|
||||
pFrame->len_msg = 0;
|
||||
pFrame->pMB = RT_NULL;
|
||||
}
|
||||
|
||||
static int chrg_south_frame_append(struct rt_ringbuffer *rb,
|
||||
struct pickup_info_t *pFrame)
|
||||
{
|
||||
rt_size_t remaining;
|
||||
rt_size_t copied;
|
||||
|
||||
if ((RT_NULL == rb)||(RT_NULL == pFrame)||(RT_NULL == pFrame->pMB)||
|
||||
(RT_NULL == pFrame->pMB->payload)||(pFrame->len_msg <= 0)||
|
||||
(pFrame->length > (rt_size_t)pFrame->len_msg)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
remaining = (rt_size_t)pFrame->len_msg - pFrame->length;
|
||||
if (0 == remaining) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
copied = rt_ringbuffer_data_len(rb);
|
||||
if (copied > remaining) {
|
||||
copied = remaining;
|
||||
}
|
||||
if (copied > 0) {
|
||||
copied = rt_ringbuffer_get(rb,
|
||||
&pFrame->pMB->payload[pFrame->length], copied);
|
||||
pFrame->length += copied;
|
||||
pFrame->last_tick = rt_tick_get();
|
||||
}
|
||||
|
||||
return (pFrame->length == (rt_size_t)pFrame->len_msg) ? 1 : 0;
|
||||
}
|
||||
|
||||
static void chrg_south_frame_dispatch(struct pickup_info_t *pFrame)
|
||||
{
|
||||
struct mb_msg_t *pMB = pFrame->pMB;
|
||||
|
||||
chrg_south_frame_reset(pFrame, RT_FALSE);
|
||||
chrg_thread_mb_send(IDX_THR_SOUTH, pMB);
|
||||
}
|
||||
|
||||
static int chrg_south_pickup_frame (struct rt_ringbuffer *rb,
|
||||
struct pickup_info_t *pFrame)
|
||||
{
|
||||
int cnt = 0;
|
||||
int status = 0;
|
||||
rt_size_t len_rb = 0;
|
||||
|
||||
if ((RT_NULL == rb)||(RT_NULL == pFrame)) {
|
||||
@@ -263,63 +330,55 @@ static int chrg_south_pickup_frame (struct rt_ringbuffer *rb,
|
||||
if (0 == pFrame->findhead) {
|
||||
pFrame->len_msg = chrg_south_frame_head(rb, pFrame->head, ID_ELOAD);
|
||||
if (pFrame->len_msg > 0) {
|
||||
if ((pFrame->len_msg < MB_ACK_HEAD_SIZE)||
|
||||
(pFrame->len_msg >= SIZE_BUF_TTY)) {
|
||||
LOG_E("invalid msg length: %d", pFrame->len_msg);
|
||||
chrg_south_frame_reset(pFrame, RT_TRUE);
|
||||
return -3;
|
||||
}
|
||||
|
||||
pFrame->pMB = (struct mb_msg_t *)rt_malloc(sizeof(struct mb_msg_t));
|
||||
if (RT_NULL == pFrame->pMB) {
|
||||
LOG_E("malloc mb failed.");
|
||||
chrg_south_frame_reset(pFrame, RT_FALSE);
|
||||
return -2;
|
||||
}
|
||||
|
||||
pFrame->pMB->length = pFrame->len_msg;
|
||||
if (pFrame->pMB->length >= SIZE_BUF_TTY) {
|
||||
rt_free(pFrame->pMB);
|
||||
pFrame->pMB = RT_NULL;
|
||||
LOG_E("too long msg.");
|
||||
return -3;
|
||||
}
|
||||
|
||||
pFrame->pMB->payload = RT_NULL;
|
||||
pFrame->pMB->payload = (rt_uint8_t *)rt_malloc(pFrame->len_msg);
|
||||
if (RT_NULL == pFrame->pMB->payload) {
|
||||
LOG_E("malloc buf failed.");
|
||||
chrg_south_frame_reset(pFrame, RT_TRUE);
|
||||
return -4;
|
||||
}
|
||||
|
||||
rt_memcpy(pFrame->pMB->payload, pFrame->head, MB_ACK_HEAD_SIZE);
|
||||
|
||||
len_rb = rt_ringbuffer_data_len(rb);
|
||||
if (len_rb >= pFrame->len_msg - MB_ACK_HEAD_SIZE) {
|
||||
rt_ringbuffer_get(rb, &pFrame->pMB->payload[MB_ACK_HEAD_SIZE],
|
||||
pFrame->len_msg - MB_ACK_HEAD_SIZE);
|
||||
|
||||
chrg_thread_mb_send(IDX_THR_SOUTH, pFrame->pMB);
|
||||
|
||||
pFrame->length = 0;
|
||||
pFrame->len_msg = 0;
|
||||
cnt++;
|
||||
} else {
|
||||
rt_ringbuffer_get(rb, &pFrame->pMB->payload[MB_ACK_HEAD_SIZE], len_rb);
|
||||
pFrame->length = MB_ACK_HEAD_SIZE + len_rb;
|
||||
pFrame->length = MB_ACK_HEAD_SIZE;
|
||||
pFrame->findhead = 1;
|
||||
pFrame->last_tick = rt_tick_get();
|
||||
|
||||
status = chrg_south_frame_append(rb, pFrame);
|
||||
if (status > 0) {
|
||||
chrg_south_frame_dispatch(pFrame);
|
||||
cnt++;
|
||||
} else if (status < 0) {
|
||||
chrg_south_frame_reset(pFrame, RT_TRUE);
|
||||
return -5;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
len_rb = rt_ringbuffer_data_len(rb);
|
||||
int len_need = pFrame->len_msg - MB_ACK_HEAD_SIZE;
|
||||
if (len_rb >= len_need) {
|
||||
rt_ringbuffer_get(rb, &pFrame->pMB->payload[pFrame->length], len_need);
|
||||
|
||||
chrg_thread_mb_send(IDX_THR_SOUTH, pFrame->pMB);
|
||||
|
||||
pFrame->length = 0;
|
||||
pFrame->findhead = 0;
|
||||
pFrame->len_msg = 0;
|
||||
status = chrg_south_frame_append(rb, pFrame);
|
||||
if (status > 0) {
|
||||
chrg_south_frame_dispatch(pFrame);
|
||||
cnt++;
|
||||
} else if (status < 0) {
|
||||
chrg_south_frame_reset(pFrame, RT_TRUE);
|
||||
return -5;
|
||||
} else {
|
||||
rt_ringbuffer_get(rb, &pFrame->pMB->payload[pFrame->length], len_rb);
|
||||
pFrame->length += len_rb;
|
||||
pFrame->last_tick = rt_tick_get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -373,6 +432,13 @@ void chrg_south_thread_entry (void *data)
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (pSOU->frame.findhead &&
|
||||
((rt_tick_t)(rt_tick_get() - pSOU->frame.last_tick) >=
|
||||
rt_tick_from_millisecond(SOUTH_FRAME_TIMEOUT_MS))) {
|
||||
chrg_south_frame_reset(&pSOU->frame, RT_TRUE);
|
||||
LOG_W("partial frame timeout");
|
||||
}
|
||||
|
||||
rt_memset(pSOU->rx_buf, 0, sizeof(pSOU->rx_buf));
|
||||
len = chrg_tty_recv(pTTY, pSOU->rx_buf, sizeof(pSOU->rx_buf));
|
||||
if (len <= 0) {
|
||||
@@ -387,21 +453,17 @@ void chrg_south_thread_entry (void *data)
|
||||
rt_uint8_t resp_byte;
|
||||
while (rt_ringbuffer_data_len(pSOU->rb) > 0) {
|
||||
rt_ringbuffer_getchar(pSOU->rb, &resp_byte);
|
||||
if (resp_byte == ACK || resp_byte == NAK || resp_byte == ACK_C) {
|
||||
if (resp_byte == ACK || resp_byte == NAK ||
|
||||
resp_byte == ACK_C || resp_byte == YM_CAN) {
|
||||
chrg_eload_set_ymodem_resp(resp_byte);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
//LOG_HEX("recvS", 32, pSOU->rx_buf, len);
|
||||
|
||||
if (1 == pSOU->frame.findhead) {
|
||||
if (rt_tick_get() >= pSOU->frame.last_tick + 100) { // 100ms
|
||||
pSOU->frame.findhead = 0; // reset
|
||||
//LOG_E("timeo\r\n");
|
||||
}
|
||||
}
|
||||
#if SOUTH_FRAME_DEBUG
|
||||
LOG_HEX("recvS", 32, pSOU->rx_buf, len);
|
||||
#endif
|
||||
|
||||
chrg_south_pickup_frame(pSOU->rb, &pSOU->frame);
|
||||
}
|
||||
|
||||
@@ -146,32 +146,40 @@ rt_err_t chrg_thread_evt_send (eIDX_THRS idx, rt_uint32_t data)
|
||||
返回说明: 0: OK , !=0 : FAILED
|
||||
其它说明: -
|
||||
*****************************************************************/
|
||||
static void chrg_thread_mb_free(void *data)
|
||||
{
|
||||
struct mb_msg_t *pMB = (struct mb_msg_t *)data;
|
||||
|
||||
if (RT_NULL == pMB) {
|
||||
return;
|
||||
}
|
||||
if (RT_NULL != pMB->payload) {
|
||||
rt_free(pMB->payload);
|
||||
}
|
||||
rt_free(pMB);
|
||||
}
|
||||
|
||||
rt_err_t chrg_thread_mb_send (eIDX_THRS idx, void *data)
|
||||
{
|
||||
rt_err_t ret = RT_EOK;
|
||||
rt_err_t ret;
|
||||
|
||||
if (idx >= TOTAL_THRS) {
|
||||
if ((idx >= TOTAL_THRS)||(RT_NULL == data)) {
|
||||
chrg_thread_mb_free(data);
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
struct chrg_thread_t *pTHR = &chrgthr[idx];
|
||||
|
||||
if (RT_NULL != pTHR->mb) {
|
||||
if (RT_NULL == pTHR->mb) {
|
||||
LOG_E("mb '%s' is not ready.", pTHR->name);
|
||||
chrg_thread_mb_free(data);
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
ret = rt_mb_send(pTHR->mb, (rt_uint32_t)data);
|
||||
if (RT_EOK != ret) {
|
||||
if (ret == -RT_EFULL) {
|
||||
LOG_E("mb full, drop message. [%d]", ret);
|
||||
if (RT_NULL != data) {
|
||||
struct mb_msg_t *pMB = (struct mb_msg_t *)data;
|
||||
if (RT_NULL != pMB->payload) {
|
||||
rt_free(pMB->payload);
|
||||
}
|
||||
rt_free(pMB);
|
||||
}
|
||||
} else {
|
||||
LOG_E("mb send failed. [%d]", ret);
|
||||
}
|
||||
}
|
||||
LOG_E("mb send failed, drop message. [%d]", ret);
|
||||
chrg_thread_mb_free(data);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -12,6 +12,19 @@
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
/*
|
||||
* Channel polling mode:
|
||||
* 1 - multi-channel hardware, advance the polling channel index;
|
||||
* 0 - single-channel hardware, keep polling channel 0.
|
||||
*/
|
||||
#define CHRG_MULTI_CHANNEL 1
|
||||
|
||||
#if CHRG_MULTI_CHANNEL
|
||||
#define CHRG_CHANNEL_NEXT(index) do { (index)++; } while (0)
|
||||
#else
|
||||
#define CHRG_CHANNEL_NEXT(index) do { } while (0)
|
||||
#endif
|
||||
|
||||
// 4路选通
|
||||
typedef enum {
|
||||
IDX_CH1 = 0, // 通路1
|
||||
@@ -88,7 +101,7 @@ struct vc_pd_t {
|
||||
rt_uint8_t group_num; // 挡位数量
|
||||
rt_uint8_t src_type; // 源类型
|
||||
rt_uint8_t pps_type; // PPS类型
|
||||
struct vc_mm_t mm[2]; // 电压电流极值
|
||||
struct vc_mm_t mm; // 电压电流极值
|
||||
};
|
||||
|
||||
/* 邮件内容 */
|
||||
|
||||
@@ -18,7 +18,29 @@
|
||||
#include "chrg_regs.h"
|
||||
#include "chrg_utils.h"
|
||||
#include "chrg_south.h"
|
||||
|
||||
#define ELOAD_VALID_VOLTAGE_MIN_MV 2000U
|
||||
|
||||
extern void LCD_SHOW(rt_uint8_t idx, struct eload_p1_t *pP1, struct chrg_eload_t *pLOAD, struct chrg_switch_t *pSW, rt_uint8_t online);
|
||||
|
||||
/* 每通道P1量测更新序号;32位读写在STM32F405上为原子访问。 */
|
||||
static volatile rt_uint32_t g_eload_sample_seq[TOTAL_SOU_CHS] = {0};
|
||||
|
||||
/*****************************************************************
|
||||
函数名称: chrg_eload_get_sample_seq
|
||||
函数描述: 获取指定南向通道P1量测数据的更新序号
|
||||
输入参数: idx:南向功率板通道
|
||||
输出参数: -
|
||||
返回说明: 当前通道量测序号,通道非法时返回0
|
||||
其它说明: 卸载确认记录命令下发前序号,只接受序号变化后的新量测
|
||||
*****************************************************************/
|
||||
rt_uint32_t chrg_eload_get_sample_seq(rt_uint8_t idx)
|
||||
{
|
||||
if (idx >= TOTAL_SOU_CHS) {
|
||||
return 0;
|
||||
}
|
||||
return g_eload_sample_seq[idx];
|
||||
}
|
||||
static rt_uint16_t ripple_base[TOTAL_SOU_CHS] = {0};
|
||||
static rt_uint8_t ripple_cal_flag[TOTAL_SOU_CHS] = {0};
|
||||
rt_uint16_t real_ripple[TOTAL_SOU_CHS] = {0};
|
||||
@@ -32,10 +54,31 @@ static rt_uint8_t g_eload_ymodem_ready = 0; // 应答就绪标志(1=有新应
|
||||
函数描述: 存储南向板返回的ymodem应答字节(由chrg_roll_sou在RUN_UPDATA调用)
|
||||
输入参数: resp: 南向ymodem应答 (ACK=0x06 / NAK=0x15 / 'C'=0x43)
|
||||
*****************************************************************/
|
||||
#define ELOAD_YMODEM_RESP_DEPTH 8
|
||||
static rt_uint8_t g_ymodem_resp_queue[ELOAD_YMODEM_RESP_DEPTH];
|
||||
static rt_uint8_t g_ymodem_resp_read = 0;
|
||||
static rt_uint8_t g_ymodem_resp_write = 0;
|
||||
static rt_uint8_t g_ymodem_resp_count = 0;
|
||||
|
||||
void chrg_eload_set_ymodem_resp(rt_uint8_t resp)
|
||||
{
|
||||
rt_base_t level = rt_hw_interrupt_disable();
|
||||
|
||||
/* 队列已满时丢弃周期性的C,保留更关键的ACK/NAK/CAN。 */
|
||||
if (g_ymodem_resp_count >= ELOAD_YMODEM_RESP_DEPTH) {
|
||||
if (resp == ACK_C) {
|
||||
rt_hw_interrupt_enable(level);
|
||||
return;
|
||||
}
|
||||
g_ymodem_resp_read = (g_ymodem_resp_read + 1) % ELOAD_YMODEM_RESP_DEPTH;
|
||||
g_ymodem_resp_count--;
|
||||
}
|
||||
g_ymodem_resp_queue[g_ymodem_resp_write] = resp;
|
||||
g_ymodem_resp_write = (g_ymodem_resp_write + 1) % ELOAD_YMODEM_RESP_DEPTH;
|
||||
g_ymodem_resp_count++;
|
||||
g_eload_ymodem_resp = resp;
|
||||
g_eload_ymodem_ready = 1;
|
||||
rt_hw_interrupt_enable(level);
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
@@ -46,11 +89,17 @@ void chrg_eload_set_ymodem_resp(rt_uint8_t resp)
|
||||
rt_uint8_t chrg_eload_get_ymodem_resp(void)
|
||||
{
|
||||
rt_uint8_t resp = 0;
|
||||
if (g_eload_ymodem_ready) {
|
||||
resp = g_eload_ymodem_resp;
|
||||
g_eload_ymodem_ready = 0;
|
||||
g_eload_ymodem_resp = 0;
|
||||
rt_base_t level = rt_hw_interrupt_disable();
|
||||
|
||||
if (g_ymodem_resp_count > 0) {
|
||||
resp = g_ymodem_resp_queue[g_ymodem_resp_read];
|
||||
g_ymodem_resp_read = (g_ymodem_resp_read + 1) % ELOAD_YMODEM_RESP_DEPTH;
|
||||
g_ymodem_resp_count--;
|
||||
}
|
||||
g_eload_ymodem_ready = (g_ymodem_resp_count > 0);
|
||||
g_eload_ymodem_resp = g_eload_ymodem_ready ?
|
||||
g_ymodem_resp_queue[g_ymodem_resp_read] : 0;
|
||||
rt_hw_interrupt_enable(level);
|
||||
return resp;
|
||||
}
|
||||
|
||||
@@ -60,8 +109,15 @@ rt_uint8_t chrg_eload_get_ymodem_resp(void)
|
||||
*****************************************************************/
|
||||
void chrg_eload_clear_ymodem_resp(void)
|
||||
{
|
||||
rt_base_t level = rt_hw_interrupt_disable();
|
||||
|
||||
g_ymodem_resp_read = 0;
|
||||
g_ymodem_resp_write = 0;
|
||||
g_ymodem_resp_count = 0;
|
||||
g_eload_ymodem_resp = 0;
|
||||
g_eload_ymodem_ready = 0;
|
||||
rt_memset(g_ymodem_resp_queue, 0, sizeof(g_ymodem_resp_queue));
|
||||
rt_hw_interrupt_enable(level);
|
||||
}
|
||||
|
||||
static int memcmp_8bytes(const rt_uint8_t *buf1, const rt_uint8_t *buf2)
|
||||
@@ -116,9 +172,20 @@ int chrg_eload_read_regs (rt_uint8_t addr, rt_uint16_t reg, rt_uint16_t len)
|
||||
u16_to_u8v(value, &buf[4]);
|
||||
crc = mb_crc16(buf, 6);
|
||||
u16_to_u8v(swap_u16(crc), &buf[6]);
|
||||
rt_kprintf("addr = %d,reg = %02x,value = %02x\n",addr,reg,value);
|
||||
#if SOUTH_COMMAND_DEBUG
|
||||
rt_kprintf("south write: addr=%d reg=0x%04x value=0x%04x\n",
|
||||
addr, reg, value);
|
||||
#endif
|
||||
return chrg_south_send(buf, 8);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the version first so a newly powered south board is not queried with
|
||||
* the long measurement frame before its Modbus interface is ready. */
|
||||
int chrg_eload_read_version (rt_uint8_t addr)
|
||||
{
|
||||
return chrg_eload_read_regs(addr, MODBUSRTU_SW_VERSION_REG,
|
||||
MODBUSRTU_SW_VERSION_LEN);
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
函数名称: chrg_eload_send_ymodem_data
|
||||
@@ -233,6 +300,24 @@ int chrg_eload_refresh (rt_uint8_t addr, rt_uint8_t part)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int chrg_eload_parse_version (rt_uint8_t idx, rt_uint8_t *data, rt_uint16_t len)
|
||||
{
|
||||
rt_uint16_t version;
|
||||
|
||||
/* A one-register Modbus 0x03 response is 7 bytes including CRC16. */
|
||||
if ((idx >= TOTAL_SOU_CHS) || (data == RT_NULL) ||
|
||||
(len != (MODBUSRTU_SW_VERSION_LEN * 2U + 5U)) ||
|
||||
(data[0] != ID_ELOAD) || (data[1] != MB_REGISTER_RD) ||
|
||||
(data[2] != 2U) || (mb_crc16(data, len) != 0U)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
version = u8v_to_u16(&data[3]);
|
||||
/* HOLD_REG_CH0_VERSION is the per-channel south board version register. */
|
||||
usRegHoldBuf[HOLD_REG_CH0_VERSION + idx * TOTAL_HOLD_CH_REGS] = version;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
函数名称: chrg_eload_parse
|
||||
函数描述: 解析源载返回数据
|
||||
@@ -276,9 +361,25 @@ int chrg_eload_parse (rt_uint8_t idx, rt_uint8_t pt, rt_uint8_t *data, rt_uint16
|
||||
pLOAD->vpkn = swap_u16(pP1->Vpkn);
|
||||
pLOAD->vpp = swap_u16(pP1->Vpp);
|
||||
pLOAD->Ripple = swap_u16(pP1->Ripple);
|
||||
pSW->Now_voltage = pLOAD->voltage;
|
||||
/* 保留功率板返回的真实电流,供卸载保护判断使用。 */
|
||||
pSW->Now_current = pLOAD->current;
|
||||
if(idx == 0)
|
||||
/*
|
||||
* 低于2V时直接清零量测结果。只清理量测字段,保留工作状态、
|
||||
* 故障、模式及测试结果,避免影响通道状态判断。
|
||||
*/
|
||||
if (pLOAD->voltage < ELOAD_VALID_VOLTAGE_MIN_MV) {
|
||||
pLOAD->voltage = 0;
|
||||
pLOAD->current = 0;
|
||||
pLOAD->vpkp = 0;
|
||||
pLOAD->vpkn = 0;
|
||||
pLOAD->vpp = 0;
|
||||
pLOAD->Ripple = 0;
|
||||
pSW->VZ = 0;
|
||||
pSW->VF = 0;
|
||||
}
|
||||
pSW->Now_voltage = pLOAD->voltage;
|
||||
/* 电压、电流均更新完成后再发布序号,避免状态机读取到半更新数据。 */
|
||||
g_eload_sample_seq[idx]++;
|
||||
#if LCD_OPEN
|
||||
// for(int i = 0;i<4;i++){
|
||||
// if(pNOR->sw[i].change_flag == 0x01){
|
||||
@@ -338,17 +439,12 @@ void Show_Curr(rt_uint8_t idx, struct chrg_eload_t *pLOAD, char *tmp, rt_uint8_t
|
||||
}
|
||||
void Show_Ripple(rt_uint8_t idx, struct chrg_eload_t *pLOAD, char *tmp, rt_uint8_t online,struct chrg_switch_t *pSW)
|
||||
{
|
||||
rt_int32_t ripple_rand = rand() % 11; // 生成0到10之间的随机数
|
||||
if(online == 0){
|
||||
if ((online == 0) ||
|
||||
(pSW->Now_voltage < ELOAD_VALID_VOLTAGE_MIN_MV)) {
|
||||
snprintf(tmp, 36, "status.CH%d_Ripple.val=0",idx+1);
|
||||
return;
|
||||
}else{
|
||||
if(pSW->Now_voltage<200){
|
||||
snprintf(tmp, 36, "status.CH%d_Ripple.val=%d",idx+1, ripple_rand);
|
||||
}else{
|
||||
}
|
||||
snprintf(tmp, 36, "status.CH%d_Ripple.val=%d",idx+1, pLOAD->Ripple);
|
||||
}
|
||||
}
|
||||
}
|
||||
void Show_DZF(rt_uint8_t idx, struct chrg_eload_t *pLOAD, char *tmp, rt_uint8_t online,rt_uint32_t vzf)
|
||||
{
|
||||
|
||||
@@ -164,6 +164,10 @@ typedef enum {
|
||||
TOTAL_MB_R
|
||||
} eIDX_MB_PART;
|
||||
|
||||
/* South board firmware version register: one 16-bit register at 0x0301. */
|
||||
#define MODBUSRTU_SW_VERSION_REG 0x0301U
|
||||
#define MODBUSRTU_SW_VERSION_LEN 1U
|
||||
|
||||
#define SIZE_P1_RD 19 // 读19个寄存器
|
||||
#define SIZE_P2_RD 28 // 读28个寄存器
|
||||
|
||||
@@ -239,6 +243,15 @@ struct chrg_eload_t {
|
||||
*****************************************************************/
|
||||
extern int chrg_eload_read_regs (rt_uint8_t addr, rt_uint16_t reg, rt_uint16_t len);
|
||||
|
||||
/*****************************************************************
|
||||
Function: chrg_eload_read_version
|
||||
Description: Request the south board firmware version register.
|
||||
Input: addr: south board address
|
||||
Output: -
|
||||
Return: <0: error, >0: sent length
|
||||
*****************************************************************/
|
||||
extern int chrg_eload_read_version (rt_uint8_t addr);
|
||||
|
||||
/*****************************************************************
|
||||
函数名称: chrg_eload_write_reg
|
||||
函数描述: 向南向发送写单个寄存器
|
||||
@@ -268,6 +281,24 @@ extern int chrg_eload_refresh (rt_uint8_t addr, rt_uint8_t part);
|
||||
其它说明: -
|
||||
*****************************************************************/
|
||||
extern int chrg_eload_parse (rt_uint8_t idx, rt_uint8_t pt, rt_uint8_t *data, rt_uint16_t len);
|
||||
|
||||
/*****************************************************************
|
||||
Function: chrg_eload_parse_version
|
||||
Description: Parse and store a valid south board firmware version.
|
||||
Input: idx: channel, data: Modbus response, len: response length
|
||||
Output: firmware version is stored at the channel version register
|
||||
Return: 0: valid, <0: invalid response
|
||||
*****************************************************************/
|
||||
extern int chrg_eload_parse_version (rt_uint8_t idx, rt_uint8_t *data, rt_uint16_t len);
|
||||
/*****************************************************************
|
||||
函数名称: chrg_eload_get_sample_seq
|
||||
函数描述: 获取指定南向通道P1量测数据的更新序号
|
||||
输入参数: idx:南向功率板通道
|
||||
输出参数: -
|
||||
返回说明: 当前通道量测序号,通道非法时返回0
|
||||
其它说明: 每成功解析一帧P1数据后递增,用于区分控制命令前后的新旧量测
|
||||
*****************************************************************/
|
||||
extern rt_uint32_t chrg_eload_get_sample_seq(rt_uint8_t idx);
|
||||
// 定义2条继电器指令,控制主继电器和滤波继电器(保留原有有效指令,移除未使用的停止指令)
|
||||
static const rt_uint8_t EXTRA_CMD_SOURCE[8] = {0x03, 0x06, 0x00, 0x01, 0x00, 0x01, 0x18, 0x28};
|
||||
extern int chrg_eload_send_relay(rt_uint8_t cmd_type);
|
||||
|
||||
@@ -41,14 +41,9 @@ int chrg_north_pkg_encode (eIDX_ID id, rt_uint8_t cmd, rt_uint8_t *data_in,
|
||||
if (len_in > 0) {
|
||||
rt_memcpy(&data_out[4], data_in, len_in);
|
||||
}
|
||||
data_out[len_in+4] = 0x2a;//calc_crc8(data_out, len_in+4);
|
||||
// rt_kprintf("pro_data= \n");
|
||||
data_out[len_in+4] = calc_crc8(data_out, len_in+4);//0x2a;
|
||||
*len_out = 5+len_in;
|
||||
// for(int i = 0; i < *len_out;i++)
|
||||
// {
|
||||
// rt_kprintf("%02x ",data_out[i]);
|
||||
// }
|
||||
// rt_kprintf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -81,7 +76,7 @@ int chrg_north_pkg_decode (rt_uint8_t *data, rt_uint16_t length, struct chrg_swi
|
||||
struct get_vol_ack_t *pAck = (struct get_vol_ack_t *)data;
|
||||
pS->vc.voltage = pAck->voltage;
|
||||
pS->vc.version = pAck->version;
|
||||
// ?
|
||||
//
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -89,9 +84,9 @@ int chrg_north_pkg_decode (rt_uint8_t *data, rt_uint16_t length, struct chrg_swi
|
||||
struct get_pd_pro_ack_t *pAck = (struct get_pd_pro_ack_t *)data;
|
||||
pS->pd_get[0].src_type = pAck->type;
|
||||
pS->pd_get[0].pps_type = pAck->pps;
|
||||
pS->pd_get[0].mm[0].max_vol = pAck->vmax;
|
||||
pS->pd_get[0].mm[0].min_vol = pAck->vmin;
|
||||
pS->pd_get[0].mm[0].max_cur = pAck->curpwr;
|
||||
pS->pd_get[0].mm.max_vol = pAck->vmax;
|
||||
pS->pd_get[0].mm.min_vol = pAck->vmin;
|
||||
pS->pd_get[0].mm.max_cur = pAck->curpwr;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -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_CH0_FAULT2 // 通道0 故障状态2 定义同源载
|
||||
|
||||
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 // 输入寄存器总数
|
||||
};
|
||||
//AI修改,不一定准确
|
||||
// ======================== 新寄存器映射 (基于0x06/0x10标准Modbus功能码) ========================
|
||||
// 地址空间规划:
|
||||
// 负载(Sink): 0x0000 + 通道号×29 + 参数偏移 (4通道×29=116个, 0x0000~0x0073)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -201,16 +201,40 @@ enum {
|
||||
|
||||
#define SINK_CMD_SET_AVS 0xE3 // AVS
|
||||
|
||||
/*
|
||||
* 普通恒流负载允许执行WORK_START的最低设定电流,单位mA。
|
||||
* 小于该值时北向仍完成协议握手,但南向保持WORK_STOP且不改写电流设定,
|
||||
* 避免功率板在零电流或几十mA的小电流设定下启动电子负载产生冲击。
|
||||
*/
|
||||
#define SINK_LOAD_ENABLE_MIN_MA 100U
|
||||
|
||||
/* 主继电器闭合后的0V持续监控:由北向轮询线程每轮调用,掉电立即转掉电保护。 */
|
||||
extern int chrg_sink_volt_low_protect(eIDX_SOU_CH idx, struct chrg_switch_t *pSW);
|
||||
|
||||
enum {
|
||||
SINK_WORK_INIT =0,
|
||||
SINK_WORK_WAIT,
|
||||
SINK_WORK_VOLT_OK,
|
||||
SINK_WORK_RUNING,
|
||||
SINK_WORK_RUNING_2,
|
||||
SINK_WORK_LOW,
|
||||
SINK_WORK_STOP,
|
||||
SINK_WORK_ON_TEST_CHANGE,
|
||||
SINK_WORK_ON_TEST_SHOUT,
|
||||
SINK_WORK_INIT = 0, // 启动入口:第一条南向命令只打开副继电器
|
||||
SINK_WORK_INIT_AUX_WAIT, // 等待启动副继电器收到有效南向回码
|
||||
SINK_WORK_WAIT, // 北向协议设置或电压查询等待状态
|
||||
SINK_WORK_VOLT_OK, // 预留的电压达标状态
|
||||
SINK_WORK_RUNING, // 电压稳定后提交继电器、电流和启动命令
|
||||
SINK_WORK_LOW, // 运行电压过低,执行掉电安全处理
|
||||
SINK_WORK_LOW_AUX_WAIT, // 等待掉电处理及副继电器恢复批次完成
|
||||
SINK_WORK_LOW_MONITOR, // 副继电器已恢复,等待输入电压重新出现
|
||||
SINK_WORK_STOP, // 用户主动停止:先停止负载并确认低电流
|
||||
SINK_WORK_SWITCH, // 停止旧电源后进入负载INIT
|
||||
SINK_WORK_PROTOCOL_UNLOAD, // 协议电压或电流变化:掉载但不切换继电器
|
||||
SINK_WORK_UNLOAD_WAIT, // 等待软卸载完成并连续两次确认电流不大于200mA
|
||||
SINK_WORK_ON_TEST_DYNA, // 动态负载测试启动状态
|
||||
SINK_WORK_ON_TEST_SHORT, // 短路测试启动状态
|
||||
SINK_WORK_ON_TEST_OCP, // OCP过流保护测试启动状态
|
||||
SINK_WORK_HANDSHAKE_PREPARE, // 完整重握手:停止、清流、全关继电器后打开副继电器
|
||||
SINK_WORK_HANDSHAKE_WAIT, // 南向低电流确认与北向协议/CC并行
|
||||
SINK_WORK_LOAD_STANDBY, // 协议已就绪但主继电器未打开,低设定电流下保持停止
|
||||
SINK_WORK_LOAD_STOP, // 运行中跨到低电流:只发送WORK_STOP关闭电子负载
|
||||
SINK_WORK_LOAD_START, // 主继电器未打开的低电流待机恢复:等待北向电压稳定后进入RUNING
|
||||
SINK_WORK_STOP_WAIT, // 关机:等待连续2次实际电流达到安全范围
|
||||
SINK_WORK_STOP_RELAY, // 关机:低电流确认后提交关闭南向继电器
|
||||
SINK_WORK_STOP_RELAY_WAIT // 关机:等待关闭南向继电器的回码
|
||||
};
|
||||
|
||||
// sink 参数结构
|
||||
@@ -234,11 +258,9 @@ struct chrg_sink_t {
|
||||
rt_uint8_t work_mode; // 0=停止 1=工作 2=低电压
|
||||
};
|
||||
|
||||
|
||||
//纹波寄存器
|
||||
#define ModbusRTU_Ripple_Value 0x35 //读取纹波
|
||||
|
||||
|
||||
/******************** 负载测试 ************************* */
|
||||
#define ModbusRTU_CAL_WriteEnable 0x34 //使能写入;0x4361代表使能写入;C+a ASCII码
|
||||
#define ModbusRTU_Test_CMD 0x4361 //
|
||||
@@ -384,7 +406,9 @@ extern void chrg_nor_sink_change_test(rt_uint8_t ch, struct chrg_switch_t *pSW);
|
||||
extern void chrg_nor_sink_test_stop(rt_uint8_t ch,struct chrg_switch_t *pSW,rt_uint8_t *enable);
|
||||
extern void chrg_nor_sink_test_run(rt_uint8_t ch, struct chrg_switch_t *pSW);
|
||||
|
||||
extern void chrg_sink_work(eIDX_SOU_CH idx, struct chrg_switch_t *pSW);
|
||||
/* 判断普通负载的当前设定是否允许启动电子负载。 */
|
||||
extern rt_bool_t chrg_sink_load_should_start(const struct chrg_switch_t *pSW);
|
||||
extern int chrg_sink_work(eIDX_SOU_CH idx, struct chrg_switch_t *pSW);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
文件名称 : chrg_source.c
|
||||
完成日期 :
|
||||
当前版本号 : V1.0
|
||||
当前版本号 : V1.1.9
|
||||
主要功能 : 北向数据source请求数据填充及发送。
|
||||
版本历史 : 创建原始版本
|
||||
说明 :
|
||||
@@ -13,6 +13,395 @@
|
||||
#include "chrg_utils.h"
|
||||
#include "chrg_roll_nor.h"
|
||||
#include "chrg_source.h"
|
||||
#include "chrg_eload.h"
|
||||
#include "chrg_roll_sou.h"
|
||||
#include "chrg_rel.h"
|
||||
|
||||
#define SOURCE_VOLT_COMPENSATION_MV 200U
|
||||
|
||||
static int chrg_source_work_running(eIDX_SOU_CH idx,
|
||||
struct chrg_switch_t *pSW);
|
||||
static int chrg_source_work_full_reset(eIDX_SOU_CH idx,
|
||||
struct chrg_switch_t *pSW);
|
||||
static int chrg_source_work_full_reset_wait(eIDX_SOU_CH idx,
|
||||
struct chrg_switch_t *pSW);
|
||||
static int chrg_source_work_full_reset_relay(eIDX_SOU_CH idx,
|
||||
struct chrg_switch_t *pSW);
|
||||
static int chrg_source_work_full_reset_relay_wait(eIDX_SOU_CH idx,
|
||||
struct chrg_switch_t *pSW);
|
||||
static int chrg_source_work_init_wait(eIDX_SOU_CH idx,
|
||||
struct chrg_switch_t *pSW);
|
||||
|
||||
/*****************************************************************
|
||||
函数名称: chrg_source_init_submit
|
||||
函数描述: 将电源模式初始化参数批量提交到南向功率板命令队列
|
||||
输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体
|
||||
输出参数: -
|
||||
返回说明: 0:提交成功 <0:参数错误或队列提交失败
|
||||
其它说明: INIT不写电压;电压统一由RUNING状态写入,避免多个入口重复控制
|
||||
*****************************************************************/
|
||||
int chrg_source_init_submit(rt_uint8_t idx, struct chrg_switch_t *pSW)
|
||||
{
|
||||
/* Source启动参数一次入队,最后发送WORK_START使功率板开始输出。 */
|
||||
if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
|
||||
return -1;
|
||||
}
|
||||
rt_uint16_t regs[5] = {
|
||||
REG_ELOAD,
|
||||
REG_MODE,
|
||||
REG_REL_ON,
|
||||
REG_CURRENT_OUT + 1,
|
||||
REG_WORK
|
||||
};
|
||||
rt_uint16_t vals[5] = {
|
||||
ELOAD_SOURCE,
|
||||
pSW->CV_mode,
|
||||
0x03,
|
||||
pSW->source.set_curr,
|
||||
WORK_START
|
||||
};
|
||||
|
||||
return chrg_sou_com_batch_submit(idx, regs, vals, 5);
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
函数名称: chrg_source_work_init
|
||||
函数描述: 执行电源INIT状态,初始化功率板并打开对应北向通道
|
||||
输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体
|
||||
输出参数: 更新电源运行标志、通道使能、在线状态及work_mode
|
||||
返回说明: 0:初始化命令提交成功 非0:初始化失败
|
||||
其它说明: 标准协议从pd_set准备目标并转入RUNING;快充协议清空旧电压后
|
||||
进入WAIT,等待北向协商结果,INIT本身不写功率板电压
|
||||
*****************************************************************/
|
||||
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;
|
||||
|
||||
/* 最大电流是功率板启动保护值,快充回码到达后可再更新运行目标。 */
|
||||
pSW->source.set_curr = pSW->source.pd_set.mm.max_cur;
|
||||
if (pSW->source.protocol == PRO_NONE) {
|
||||
pSW->source.set_volt = pSW->source.pd_set.mm.max_vol;
|
||||
} else {
|
||||
/* 禁止快充重新启动时沿用上一次协商电压。 */
|
||||
pSW->source.set_volt = 0;
|
||||
}
|
||||
|
||||
ret = chrg_source_init_submit(idx, pSW);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
pSW->source.On_Flag = 1;
|
||||
pSW->source.qc_err = 0;
|
||||
pNOR->enable[idx] = 1;
|
||||
pSOU->online[idx] = 1;
|
||||
chrg_nor_sw_rel((eIDX_NOR_CH)idx, ID_SOURCE);
|
||||
/* 初始化批次必须全部收到南向回码后,才能继续协议设置或输出控制。 */
|
||||
pSW->source.work_mode = SOURCE_WORK_INIT_WAIT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int chrg_source_work_init_wait(eIDX_SOU_CH idx,
|
||||
struct chrg_switch_t *pSW)
|
||||
{
|
||||
int result;
|
||||
|
||||
if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
|
||||
return -1;
|
||||
}
|
||||
if (chrg_sou_com_batch_is_pending(idx)) {
|
||||
return 1;
|
||||
}
|
||||
result = chrg_sou_com_batch_get_result(idx);
|
||||
if (result <= 0) {
|
||||
/* 南向初始化失败时,保持北向协议不变并重发完整初始化批次。 */
|
||||
pSW->source.work_mode = SOURCE_WORK_INIT;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pSW->sub == IDX_SET_SOURCE_RESET) {
|
||||
/* 复位后的初始化完成,才允许进入PD协议设置。 */
|
||||
pSW->sub = IDX_SET_SOURCE_PD;
|
||||
pSW->source.work_mode = SOURCE_WORK_WAIT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pSW->source.protocol == PRO_NONE) {
|
||||
/* 标准协议不等待协商,初始化完成后直接写入目标电压。 */
|
||||
pSW->source.work_mode = SOURCE_WORK_RUNING;
|
||||
return chrg_source_work_running(idx, pSW);
|
||||
}
|
||||
pSW->source.work_mode = SOURCE_WORK_WAIT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
函数名称: chrg_source_work_wait
|
||||
函数描述: 执行电源WAIT状态
|
||||
输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体
|
||||
输出参数: -
|
||||
返回说明: 0:状态处理完成
|
||||
其它说明: WAIT状态不下发命令,由北向解析函数判断目标电压是否变化
|
||||
*****************************************************************/
|
||||
static int chrg_source_work_wait(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
|
||||
{
|
||||
/* WAIT状态不产生南向命令,等待下一帧北向电压数据。 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
函数名称: chrg_source_work_running
|
||||
函数描述: 执行电源RUNING状态,下发补偿后的最新目标电压
|
||||
输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体
|
||||
输出参数: -
|
||||
返回说明: 0:命令提交成功 非0:命令提交失败
|
||||
其它说明: 功率板设定值固定比目标高200mV,防止限压导致输出进入稳流模式;
|
||||
目标最大值为48000mV,无需做uint16_t饱和处理
|
||||
*****************************************************************/
|
||||
static int chrg_source_work_running(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
|
||||
{
|
||||
/* 只对本次下发值补偿,不修改set_volt,防止多次执行时累计增加。 */
|
||||
rt_uint16_t reg = REG_VOLTAGE_OUT + 1;
|
||||
rt_uint16_t value = pSW->source.set_volt;
|
||||
|
||||
return chrg_sou_com_batch_submit(idx, ®, &value, 1);
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
函数名称: chrg_source_work_protocol_switch
|
||||
函数描述: 执行电源协议或CC切换前的功率板输出清零
|
||||
输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体
|
||||
输出参数: 清零source.set_volt,并在命令入队成功后进入WAIT状态
|
||||
返回说明: 0:清零命令提交成功 非0:状态或命令提交失败
|
||||
其它说明: COM在进入本状态前必须将sub设置为协议、CC或组合事务入口;
|
||||
本状态只管理南向清零,不修改北向sub,
|
||||
标准协议同时按0V、模式、电流顺序入队,保证南向命令顺序固定
|
||||
*****************************************************************/
|
||||
static int chrg_source_work_protocol_switch(eIDX_SOU_CH idx,
|
||||
struct chrg_switch_t *pSW)
|
||||
{
|
||||
rt_uint16_t regs[3];
|
||||
rt_uint16_t vals[3];
|
||||
rt_uint8_t count = 0;
|
||||
int ret;
|
||||
|
||||
if ((pSW->sub != IDX_SET_SOURCE_PD) &&
|
||||
(pSW->sub != IDX_SET_SOURCE_RESET)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
regs[count] = REG_VOLTAGE_OUT + 1;
|
||||
vals[count++] = 0;
|
||||
if (pSW->source.protocol == PRO_NONE) {
|
||||
/* 标准协议切换时,模式和限流值必须排在0V命令之后生效。 */
|
||||
regs[count] = REG_MODE;
|
||||
vals[count++] = pSW->CV_mode;
|
||||
regs[count] = REG_CURRENT_OUT + 1;
|
||||
vals[count++] = pSW->source.pd_set.mm.max_cur;
|
||||
}
|
||||
|
||||
/* 只有整批命令成功加入南向队列后,才允许北向继续协议切换。 */
|
||||
ret = chrg_sou_com_batch_submit(idx, regs, vals, count);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
pSW->source.set_volt = 0;
|
||||
pSW->source.work_mode = SOURCE_WORK_WAIT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int chrg_source_work_full_reset(eIDX_SOU_CH idx,
|
||||
struct chrg_switch_t *pSW)
|
||||
{
|
||||
rt_uint16_t reg = REG_WORK;
|
||||
rt_uint16_t value = WORK_STOP;
|
||||
|
||||
/* Cancel stale south commands so the reset sequence starts from a known state. */
|
||||
if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
|
||||
return -1;
|
||||
}
|
||||
if (chrg_sou_com_batch_cancel(idx) != 0) {
|
||||
return -1;
|
||||
}
|
||||
if (chrg_sou_com_batch_submit(idx, ®, &value, 1) != 0) {
|
||||
return -1;
|
||||
}
|
||||
pSW->source.set_volt = 0;
|
||||
pSW->source.work_mode = SOURCE_WORK_FULL_RESET_WAIT;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int chrg_source_work_full_reset_wait(eIDX_SOU_CH idx,
|
||||
struct chrg_switch_t *pSW)
|
||||
{
|
||||
int result;
|
||||
|
||||
if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
|
||||
return -1;
|
||||
}
|
||||
if (chrg_sou_com_batch_is_pending(idx)) {
|
||||
return 1;
|
||||
}
|
||||
result = chrg_sou_com_batch_get_result(idx);
|
||||
if (result <= 0) {
|
||||
pSW->source.work_mode = SOURCE_WORK_FULL_RESET;
|
||||
return 1;
|
||||
}
|
||||
pSW->source.work_mode = SOURCE_WORK_FULL_RESET_RELAY;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int chrg_source_work_full_reset_relay(eIDX_SOU_CH idx,
|
||||
struct chrg_switch_t *pSW)
|
||||
{
|
||||
rt_uint16_t reg = REG_REL_ON;
|
||||
rt_uint16_t value = ALL_REL_OFF;
|
||||
|
||||
if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
|
||||
return -1;
|
||||
}
|
||||
if (chrg_sou_com_batch_submit(idx, ®, &value, 1) != 0) {
|
||||
return -1;
|
||||
}
|
||||
pSW->source.work_mode = SOURCE_WORK_FULL_RESET_RELAY_WAIT;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int chrg_source_work_full_reset_relay_wait(eIDX_SOU_CH idx,
|
||||
struct chrg_switch_t *pSW)
|
||||
{
|
||||
int result;
|
||||
|
||||
if ((idx >= TOTAL_SOU_CHS) || (pSW == RT_NULL)) {
|
||||
return -1;
|
||||
}
|
||||
if (chrg_sou_com_batch_is_pending(idx)) {
|
||||
return 1;
|
||||
}
|
||||
result = chrg_sou_com_batch_get_result(idx);
|
||||
if (result <= 0) {
|
||||
pSW->source.work_mode = SOURCE_WORK_FULL_RESET_RELAY;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* South relays are off; now disconnect D+/D- and CC before SOURCE_RESET. */
|
||||
chrg_nor_sw_rel((eIDX_NOR_CH)idx, 0);
|
||||
pSW->sub = IDX_SET_SOURCE_RESET;
|
||||
pSW->source.work_mode = SOURCE_WORK_WAIT;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
函数名称: chrg_source_work_stop
|
||||
函数描述: 执行电源主动关机流程
|
||||
输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体
|
||||
输出参数: 清除目标电压、运行标志、通道使能和在线状态
|
||||
返回说明: 0:停止成功 非0:停止命令提交失败
|
||||
其它说明: 依次关闭功率板两路继电器、清零电压并发送WORK_STOP;
|
||||
停止命令成功入队后立即关闭北向通道,不额外发送CC_CLOSE
|
||||
*****************************************************************/
|
||||
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 regs[3] = {REG_REL_ON, REG_VOLTAGE_OUT + 1, REG_WORK};
|
||||
rt_uint16_t vals[3] = {ALL_REL_OFF, 0, WORK_STOP};
|
||||
|
||||
/* 先断开两路功率继电器,再清零输出并停止,避免关机瞬间继续向外供电。 */
|
||||
ret = chrg_sou_com_batch_submit(idx, regs, vals, 3);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
pSW->source.set_volt = 0;
|
||||
pSW->source.On_Flag = 0;
|
||||
pSW->source.qc_err = 0;
|
||||
pNOR->enable[idx] = 0;
|
||||
pSOU->online[idx] = 0;
|
||||
chrg_nor_sw_rel((eIDX_NOR_CH)idx, 0);
|
||||
pSW->sub = IDX_SET_SOURCE_STOP_STATE;
|
||||
pSW->source.work_mode = SOURCE_WORK_WAIT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
函数名称: chrg_source_work_switch
|
||||
函数描述: 处理“负载切换到电源”的过渡状态
|
||||
输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体
|
||||
输出参数: 清除旧负载运行标志,设置电源北向入口和INIT状态
|
||||
返回说明: 0:停止命令成功加入队列 非0:命令入队失败
|
||||
其它说明: pSW->id已由COM更新为ID_SOURCE;先关闭旧负载继电器并提交
|
||||
WORK_STOP,后续电源INIT使用同一通道队列,保证停止命令先执行
|
||||
*****************************************************************/
|
||||
static int chrg_source_work_switch(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
|
||||
{
|
||||
rt_uint16_t regs[3] = {REG_REL_ON, REG_VOLTAGE_OUT + 1, REG_WORK};
|
||||
rt_uint16_t vals[3] = {ALL_REL_OFF, 0, WORK_STOP};
|
||||
int ret;
|
||||
|
||||
ret = chrg_sou_com_batch_submit(idx, regs, vals, 3);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* 停止成功入队后,清除旧Sink运行标志。 */
|
||||
pSW->sink.On_work = 0;
|
||||
pSW->source.set_volt = 0;
|
||||
/* 首次进入Source按“设置协议->连接CC”启动,不能沿用Sink的sub状态。 */
|
||||
pSW->sub = IDX_SET_SOURCE_PD;
|
||||
/* SWITCH只负责旧角色退出,后续启动统一交给Source INIT状态。 */
|
||||
pSW->source.work_mode = SOURCE_WORK_INIT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
函数名称: chrg_source_work_state
|
||||
函数描述: 电源工作状态机统一入口
|
||||
输入参数: idx:南向功率通道编号 pSW:当前通道控制结构体
|
||||
输出参数: 根据source.work_mode执行对应状态动作
|
||||
返回说明: 0:状态处理成功 <0:参数、状态或命令提交失败
|
||||
其它说明: 支持INIT、WAIT、RUNING、STOP、SWITCH和PROTOCOL_SWITCH状态
|
||||
*****************************************************************/
|
||||
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_STOP:
|
||||
return chrg_source_work_stop(idx, pSW);
|
||||
case SOURCE_WORK_SWITCH:
|
||||
return chrg_source_work_switch(idx, pSW);
|
||||
case SOURCE_WORK_PROTOCOL_SWITCH:
|
||||
return chrg_source_work_protocol_switch(idx, pSW);
|
||||
case SOURCE_WORK_FULL_RESET:
|
||||
return chrg_source_work_full_reset(idx, pSW);
|
||||
case SOURCE_WORK_FULL_RESET_WAIT:
|
||||
return chrg_source_work_full_reset_wait(idx, pSW);
|
||||
case SOURCE_WORK_FULL_RESET_RELAY:
|
||||
return chrg_source_work_full_reset_relay(idx, pSW);
|
||||
case SOURCE_WORK_FULL_RESET_RELAY_WAIT:
|
||||
return chrg_source_work_full_reset_relay_wait(idx, pSW);
|
||||
case SOURCE_WORK_INIT_WAIT:
|
||||
return chrg_source_work_init_wait(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)
|
||||
};
|
||||
@@ -58,6 +447,18 @@ int source_get_pd (void)
|
||||
return chrg_north_send(frame, len);
|
||||
}
|
||||
|
||||
int source_reset (void)
|
||||
{
|
||||
rt_uint16_t len = 0;
|
||||
rt_uint8_t data[8] = {0};
|
||||
rt_uint8_t frame[16] = {0};
|
||||
|
||||
data[0] = 0x00;
|
||||
chrg_north_pkg_encode(ID_SOURCE, SRC_CMD_RESET, data, 1, frame, &len);
|
||||
|
||||
return chrg_north_send(frame, len);
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
函数名称: source_set_cc_lvl
|
||||
函数描述: source 设置 cc 等级
|
||||
@@ -96,11 +497,13 @@ int source_set_cc_choose (rt_uint8_t cc_set)
|
||||
data[0] = cc_set;
|
||||
|
||||
chrg_north_pkg_encode(ID_SOURCE, SRC_CMD_SET_CC_CHOOSE, data, 1, frame, &len);
|
||||
rt_kprintf("\n");
|
||||
for(int i=0;i<len;i++){
|
||||
rt_kprintf("%d ");
|
||||
#if NORTH_SOURCE_DEBUG
|
||||
rt_kprintf("source set cc frame:");
|
||||
for (int i = 0; i < len; i++) {
|
||||
rt_kprintf(" %02x", frame[i]);
|
||||
}
|
||||
rt_kprintf("\n");
|
||||
#endif
|
||||
return chrg_north_send(frame, len);
|
||||
}
|
||||
|
||||
@@ -118,9 +521,13 @@ rt_uint8_t parse_mulit_gear_One(rt_uint16_t min_volt_mv,rt_uint16_t max_volt_mv,
|
||||
Pro_Group_VCMM[0][4] = (max_volt_mv >> 8) & 0xFF; // vmax_H
|
||||
Pro_Group_VCMM[0][5] = max_volt_mv & 0xFF; // vmax_L
|
||||
Pro_Group_VCMM[0][6] = (max_curr_ma >> 8) & 0xFF; // cur_set_H
|
||||
#if NORTH_SOURCE_DEBUG
|
||||
rt_kprintf("H_C=%02x",Pro_Group_VCMM[0][6]);
|
||||
#endif
|
||||
Pro_Group_VCMM[0][7] = max_curr_ma & 0xFF; // cur_set_L
|
||||
#if NORTH_SOURCE_DEBUG
|
||||
rt_kprintf("L_C=%02x\n",Pro_Group_VCMM[0][7]);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -152,12 +559,12 @@ void parse_power_single_gear(rt_uint8_t protoCmd, rt_uint8_t *pData, rt_uint16_t
|
||||
// rt_kprintf("%0x",pData[i]);
|
||||
// }
|
||||
// rt_kprintf("\n");
|
||||
#if PRO_TEST_DEBUG
|
||||
#if NORTH_SOURCE_DEBUG
|
||||
rt_kprintf("one_gear");
|
||||
rt_kprintf("min_volt_mv = %d\n",min_volt_mv);
|
||||
rt_kprintf("max_volt_mv = %d\n",max_volt_mv);
|
||||
rt_kprintf("prtect_curr= %04x",*protect_curr);
|
||||
#endif
|
||||
#endif
|
||||
*pro_gear_idx = 1; // 单档协议固定1
|
||||
// 按协议命令码赋值
|
||||
switch (protoCmd)
|
||||
@@ -264,7 +671,7 @@ void parse_pd_11group_pdo(rt_uint8_t *pdoData, rt_uint8_t pdo_group_num) {
|
||||
// 电流/功率拆分
|
||||
Pro_Group_VCMM[i][6] = (cur_power >> 8) & 0xFF; // cur_set_H
|
||||
Pro_Group_VCMM[i][7] = cur_power & 0xFF; // cur_set_L
|
||||
#if PRO_TEST_DEBUG
|
||||
#if NORTH_SOURCE_DEBUG
|
||||
// 调试打印
|
||||
rt_kprintf("max_H=%d",Pro_Group_VCMM[i][4]);
|
||||
rt_kprintf("max_L=%d",Pro_Group_VCMM[i][5]);
|
||||
@@ -305,9 +712,13 @@ void parse_power_pdo_gear(rt_uint8_t protoCmd, rt_uint8_t *pData, rt_uint16_t re
|
||||
rt_int16_t comp_volt_mv = 0; // 补偿电压(mV)
|
||||
|
||||
// 数据区索引:0=状态+通道,1=CC线,2=恒压恒流模式,3=PDO组数(bit12-15)
|
||||
#if NORTH_SOURCE_DEBUG
|
||||
rt_kprintf("pdata=%04x",pData[3]);
|
||||
#endif
|
||||
pdo_group_num = (pData[3] >> 4) & 0x0F; // Bit12-15提取组数
|
||||
#if NORTH_SOURCE_DEBUG
|
||||
rt_kprintf("num=%d\n",pdo_group_num);
|
||||
#endif
|
||||
*pro = PRO_PD0PSS;
|
||||
*pro_gear_idx = pdo_group_num;
|
||||
// 解析11组PDO(小端序,44字节)
|
||||
@@ -316,13 +727,11 @@ void parse_power_pdo_gear(rt_uint8_t protoCmd, rt_uint8_t *pData, rt_uint16_t re
|
||||
// 解析保留字段(20字节) + 保护电流 + 补偿电压
|
||||
*protect_ma = u8v_to_u16(&pData[4 + 44 + 20]); // 67-68字节
|
||||
comp_volt_mv = (rt_int16_t)u8v_to_u16(&pData[4 + 44 + 22]); // 69-70字节
|
||||
// #if PRO_TEST_DEBUG
|
||||
#if NORTH_SOURCE_DEBUG
|
||||
rt_kprintf("project_curr=%d mA, add_volt=%d mV\n", *protect_ma, comp_volt_mv);
|
||||
// #endif.
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
函数名称: parse_mulit_gear_more
|
||||
函数描述: 解析三-四挡位原始数据,填充8参数高低字节缓冲区(同步修改)
|
||||
@@ -408,7 +817,7 @@ rt_uint8_t parse_mulit_gear_more(rt_uint8_t *pData, rt_uint8_t gear_num) {
|
||||
Pro_Group_VCMM[i][5] = vmax_mv & 0xFF; // vmax_L
|
||||
Pro_Group_VCMM[i][6] = (cur_power >> 8) & 0xFF; // cur_set_H
|
||||
Pro_Group_VCMM[i][7] = cur_power & 0xFF; // cur_set_L
|
||||
#if PRO_TEST_DEBUG
|
||||
#if NORTH_SOURCE_DEBUG
|
||||
// 调试打印
|
||||
rt_kprintf("parse_mulit_gear_pd0 PDO[%d]:rc=0x%02X, pps=0x%02X,V_Min=%dmV,V_MAX=%dmV,C/P=%d\n",
|
||||
i, Pro_Group_VCMM[i][0], Pro_Group_VCMM[i][1], vmin_mv, vmax_mv, cur_power);
|
||||
@@ -443,7 +852,9 @@ void parse_multi_gear_more(rt_uint8_t protoCmd, rt_uint8_t *pData, rt_uint16_t r
|
||||
return;
|
||||
}
|
||||
*pro_gear_idx = gear_num;
|
||||
#if NORTH_SOURCE_DEBUG
|
||||
rt_kprintf("pro_gear_idx = %d\n",gear_num);
|
||||
#endif
|
||||
// 解析保护电流和补偿电压(不同协议偏移不同)
|
||||
switch (protoCmd)
|
||||
{
|
||||
@@ -462,7 +873,7 @@ void parse_multi_gear_more(rt_uint8_t protoCmd, rt_uint8_t *pData, rt_uint16_t r
|
||||
}
|
||||
*protect_ma = u8v_to_u16(&pData[4 + 16]); // 19-20字节
|
||||
comp_volt_mv = (rt_int16_t)u8v_to_u16(&pData[4 + 18]);
|
||||
#if PRO_TEST_DEBUG
|
||||
#if NORTH_SOURCE_DEBUG
|
||||
for(int i = 0;i<30;i++){
|
||||
rt_kprintf("data[%d]=%02x",i,pData[i]);
|
||||
}
|
||||
@@ -524,7 +935,7 @@ rt_uint8_t parse_ufcs_gear_more(rt_uint8_t *pData, rt_uint8_t gear_num) {
|
||||
Pro_Group_VCMM[i][5] = vmax_mv & 0xFF;
|
||||
Pro_Group_VCMM[i][6] = (cur_ma >> 8) & 0xFF;
|
||||
Pro_Group_VCMM[i][7] = cur_ma & 0xFF;
|
||||
#if PRO_TEST_DEBUG
|
||||
#if NORTH_SOURCE_DEBUG
|
||||
// ================= 打印格式 =================
|
||||
rt_kprintf("parse_ufcs_gear_more PDO[%d]:PPS/AVS,V_Min=%dmV,V_MAX=%dmV,Max_Current=%dmA\n",
|
||||
i, vmin_mv, vmax_mv, cur_ma);
|
||||
@@ -568,10 +979,10 @@ void parse_power_ufcs(rt_uint8_t *pData, rt_uint16_t reqLen, uint8_t *pro_gear_i
|
||||
// rt_kprintf("data[%d]=%02x",i,pData[i]);
|
||||
// }
|
||||
comp_volt_mv = 0;//(rt_int16_t)u8v_to_u16(&pData[3 + 14]);
|
||||
//#if PRO_TEST_DEBUG
|
||||
#if NORTH_SOURCE_DEBUG
|
||||
rt_kprintf("parse_power_ufcs:gear=%d,protect=%dmA,comp=%dmV\n",
|
||||
gear_num,*protect_ma, comp_volt_mv);
|
||||
//#endif
|
||||
#endif
|
||||
|
||||
// 调用下面的循环解析
|
||||
parse_ufcs_gear_more(&pData[4], gear_num);
|
||||
@@ -705,6 +1116,8 @@ rt_uint8_t pd_fill_single_group_need_src_com(rt_uint8_t *data, rt_uint8_t start_
|
||||
|
||||
rt_uint8_t idx = start_idx;
|
||||
struct chrg_src_t *source = &psw->source;
|
||||
const struct vc_pd_t *pd = &source->pd_set;
|
||||
const struct vc_mm_t *mm = &pd->mm;
|
||||
// 1. src + pps(2字节)
|
||||
data[idx++] = 0x00;
|
||||
data[idx++] = 0x00;
|
||||
@@ -715,23 +1128,23 @@ rt_uint8_t pd_fill_single_group_need_src_com(rt_uint8_t *data, rt_uint8_t start_
|
||||
data[idx++] = 0x13;
|
||||
data[idx++] = 0x88;
|
||||
// 4. 电流/功率(高+低,直接取已拆分好的值)
|
||||
data[idx++] = source->protective_curr >> 8;
|
||||
data[idx++] = source->protective_curr & 0xFF;
|
||||
data[idx++] = mm->max_cur >> 8;
|
||||
data[idx++] = mm->max_cur & 0xFF;
|
||||
// 5. 保留位6字节(直接填0)
|
||||
memset(&data[idx], 0x00, 6);
|
||||
idx+=6;
|
||||
data[idx++] = source->src;
|
||||
data[idx++] = source->pps;
|
||||
rt_kprintf("src = %d pps = %d\n",source->src,source->pps);
|
||||
data[idx++] = pd->src_type;
|
||||
data[idx++] = pd->pps_type;
|
||||
//rt_kprintf("src = %d pps = %d\n", pd->src_type, pd->pps_type);
|
||||
// 2. 最小电压(高+低,直接取已拆分好的值)
|
||||
data[idx++] = source->min_vol >> 8;
|
||||
data[idx++] = source->min_vol & 0xFF;
|
||||
data[idx++] = mm->min_vol >> 8;
|
||||
data[idx++] = mm->min_vol & 0xFF;
|
||||
// 3. 最大电压(高+低,直接取已拆分好的值)
|
||||
data[idx++] = source->max_vol >> 8;
|
||||
data[idx++] = source->max_vol & 0xFF;
|
||||
data[idx++] = mm->max_vol >> 8;
|
||||
data[idx++] = mm->max_vol & 0xFF;
|
||||
// 4. 电流/功率(高+低,直接取已拆分好的值)
|
||||
data[idx++] = source->protective_curr >> 8;
|
||||
data[idx++] = source->protective_curr & 0xFF;
|
||||
data[idx++] = mm->max_cur >> 8;
|
||||
data[idx++] = mm->max_cur & 0xFF;
|
||||
// 5. 保留位6字节(直接填0)
|
||||
memset(&data[idx], 0x00, 6);
|
||||
idx+=6;
|
||||
@@ -742,28 +1155,30 @@ rt_uint8_t pd_fill_single_group_no_src_com(rt_uint8_t *data, rt_uint8_t start_id
|
||||
|
||||
rt_uint8_t idx = start_idx;
|
||||
struct chrg_src_t *source = &psw->source;
|
||||
const struct vc_mm_t *mm = &source->pd_set.mm;
|
||||
// 1. src + pps(2字节)
|
||||
data[idx++] = 0x00;
|
||||
data[idx++] = 0x00;
|
||||
// 2. 最小电压(高+低,直接取已拆分好的值)
|
||||
data[idx++] = source->min_vol >> 8;
|
||||
data[idx++] = source->min_vol & 0xFF;
|
||||
data[idx++] = 0x13;//mm->min_vol >> 8;
|
||||
data[idx++] = 0x18;//mm->min_vol & 0xFF;
|
||||
// 3. 最大电压(高+低,直接取已拆分好的值)
|
||||
data[idx++] = source->max_vol >> 8;
|
||||
data[idx++] = source->max_vol & 0xFF;
|
||||
data[idx++] = mm->max_vol >> 8;
|
||||
data[idx++] = mm->max_vol & 0xFF;
|
||||
// 4. 电流/功率(高+低,直接取已拆分好的值)
|
||||
data[idx++] = source->protective_curr >> 8;
|
||||
data[idx++] = source->protective_curr & 0xFF;
|
||||
data[idx++] = mm->max_cur >> 8;
|
||||
data[idx++] = mm->max_cur & 0xFF;
|
||||
// 5. 保留位6字节(直接填0)
|
||||
memset(&data[idx], 0x00, 6);
|
||||
idx+=6;
|
||||
return idx - start_idx; // 返回填充的总字节数
|
||||
}
|
||||
|
||||
rt_uint8_t pd_fill_single_group_FCP_AFC(rt_uint8_t *data, rt_uint8_t start_idx,struct chrg_switch_t *psw){
|
||||
rt_uint8_t pd_fill_single_group_AFC(rt_uint8_t *data, rt_uint8_t start_idx,struct chrg_switch_t *psw){
|
||||
|
||||
rt_uint8_t idx = start_idx;
|
||||
struct chrg_src_t *source = &psw->source;
|
||||
const struct vc_mm_t *mm = &source->pd_set.mm;
|
||||
// 1. src + pps(2字节)
|
||||
data[idx++] = 0x00;
|
||||
data[idx++] = 0x00;
|
||||
@@ -774,8 +1189,8 @@ rt_uint8_t pd_fill_single_group_FCP_AFC(rt_uint8_t *data, rt_uint8_t start_idx,s
|
||||
data[idx++] = 0x13;
|
||||
data[idx++] = 0x88;
|
||||
// 4. 电流/功率(高+低,直接取已拆分好的值)
|
||||
data[idx++] = source->protective_curr >> 8;
|
||||
data[idx++] = source->protective_curr & 0xFF;
|
||||
data[idx++] = mm->max_cur >> 8;
|
||||
data[idx++] = mm->max_cur & 0xFF;
|
||||
// 5. 保留位6字节(直接填0)
|
||||
memset(&data[idx], 0x00, 6);
|
||||
idx+=6;
|
||||
@@ -783,14 +1198,14 @@ rt_uint8_t pd_fill_single_group_FCP_AFC(rt_uint8_t *data, rt_uint8_t start_idx,s
|
||||
data[idx++] = 0x00;
|
||||
data[idx++] = 0x00;
|
||||
// 2. 最小电压(高+低,直接取已拆分好的值)
|
||||
data[idx++] = source->max_vol >> 8;
|
||||
data[idx++] = source->max_vol & 0xFF;
|
||||
data[idx++] = mm->max_vol >> 8;
|
||||
data[idx++] = mm->max_vol & 0xFF;
|
||||
// 3. 最大电压(高+低,直接取已拆分好的值)
|
||||
data[idx++] = source->max_vol >> 8;
|
||||
data[idx++] = source->max_vol & 0xFF;
|
||||
data[idx++] = mm->max_vol >> 8;
|
||||
data[idx++] = mm->max_vol & 0xFF;
|
||||
// 4. 电流/功率(高+低,直接取已拆分好的值)
|
||||
data[idx++] = source->protective_curr >> 8;
|
||||
data[idx++] = source->protective_curr & 0xFF;
|
||||
data[idx++] = mm->max_cur >> 8;
|
||||
data[idx++] = mm->max_cur & 0xFF;
|
||||
// 5. 保留位6字节(直接填0)
|
||||
memset(&data[idx], 0x00, 6);
|
||||
idx+=6;
|
||||
@@ -801,6 +1216,7 @@ rt_uint8_t pd_fill_single_group_UFCS(rt_uint8_t *data, rt_uint8_t start_idx,stru
|
||||
|
||||
rt_uint8_t idx = start_idx;
|
||||
struct chrg_src_t *source = &psw->source;
|
||||
const struct vc_mm_t *mm = &source->pd_set.mm;
|
||||
// 1. src + pps(2字节)
|
||||
data[idx++] = 0x00;
|
||||
data[idx++] = 0x00;
|
||||
@@ -811,8 +1227,8 @@ rt_uint8_t pd_fill_single_group_UFCS(rt_uint8_t *data, rt_uint8_t start_idx,stru
|
||||
data[idx++] = 0x13;
|
||||
data[idx++] = 0x88;
|
||||
// 4. 电流/功率(高+低,直接取已拆分好的值)
|
||||
data[idx++] = source->protective_curr >> 8;
|
||||
data[idx++] = source->protective_curr & 0xFF;
|
||||
data[idx++] = mm->max_cur >> 8;
|
||||
data[idx++] = mm->max_cur & 0xFF;
|
||||
// 5. 保留位6字节(直接填0)
|
||||
memset(&data[idx], 0x00, 6);
|
||||
idx+=6;
|
||||
@@ -820,48 +1236,47 @@ rt_uint8_t pd_fill_single_group_UFCS(rt_uint8_t *data, rt_uint8_t start_idx,stru
|
||||
data[idx++] = 0x00;
|
||||
data[idx++] = 0x00;
|
||||
// 2. 最小电压(高+低,直接取已拆分好的值)
|
||||
data[idx++] = source->min_vol >> 8;
|
||||
data[idx++] = source->min_vol & 0xFF;
|
||||
data[idx++] = mm->min_vol >> 8;
|
||||
data[idx++] = mm->min_vol & 0xFF;
|
||||
// 3. 最大电压(高+低,直接取已拆分好的值)
|
||||
data[idx++] = source->max_vol >> 8;
|
||||
data[idx++] = source->max_vol & 0xFF;
|
||||
data[idx++] = mm->max_vol >> 8;
|
||||
data[idx++] = mm->max_vol & 0xFF;
|
||||
// 4. 电流/功率(高+低,直接取已拆分好的值)
|
||||
data[idx++] = source->protective_curr >> 8;
|
||||
data[idx++] = source->protective_curr & 0xFF;
|
||||
data[idx++] = mm->max_cur >> 8;
|
||||
data[idx++] = mm->max_cur & 0xFF;
|
||||
// 5. 保留位6字节(直接填0)
|
||||
memset(&data[idx], 0x00, 6);
|
||||
idx+=6;
|
||||
return idx - start_idx; // 返回填充的总字节数
|
||||
}
|
||||
|
||||
int source_set_pd_com(rt_uint8_t pro,rt_uint8_t pro_gear_idx)
|
||||
static rt_uint8_t chrg_source_fill_AFC_three_gears(rt_uint8_t *data,
|
||||
rt_uint8_t start_idx, struct chrg_switch_t *psw)
|
||||
{
|
||||
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; // 总填充字节数
|
||||
static const rt_uint16_t fixed_voltages[] = {5000U, 9000U, 12000U, 20000U};
|
||||
const struct vc_mm_t *mm = &psw->source.pd_set.mm;
|
||||
rt_uint8_t idx = start_idx;
|
||||
rt_uint8_t gear;
|
||||
|
||||
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);
|
||||
for (gear = 0; gear < (sizeof(fixed_voltages) / sizeof(fixed_voltages[0]));
|
||||
gear++) {
|
||||
/* FCP固定电压档不使用PD源类型和PPS类型。 */
|
||||
data[idx++] = 0x00;
|
||||
data[idx++] = 0x00;
|
||||
data[idx++] = fixed_voltages[gear] >> 8;
|
||||
data[idx++] = fixed_voltages[gear] & 0xFF;
|
||||
data[idx++] = fixed_voltages[gear] >> 8;
|
||||
data[idx++] = fixed_voltages[gear] & 0xFF;
|
||||
data[idx++] = mm->max_cur >> 8;
|
||||
data[idx++] = mm->max_cur & 0xFF;
|
||||
memset(&data[idx], 0x00, 6);
|
||||
idx += 6;
|
||||
}
|
||||
|
||||
return idx - start_idx;
|
||||
}
|
||||
|
||||
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};
|
||||
@@ -872,19 +1287,25 @@ int source_set_pd_new_com(rt_uint8_t pro, struct chrg_switch_t *pSW)
|
||||
rt_uint8_t idx = 1; //从data[1]开始填充
|
||||
rt_uint8_t fill_len = 0;
|
||||
rt_uint8_t protocal = pSW->source.protocol;
|
||||
if(protocal == 0x0A){
|
||||
if(protocal == PRO_PD0PSS){
|
||||
fill_len = pd_fill_single_group_need_src_com(data, idx, pSW);
|
||||
}else if(protocal == 0x03||protocal == 0x07||protocal == 0x08 ){
|
||||
}else if(protocal == PRO_SCPB||protocal == PRO_QC30||protocal == PRO_QC20 ||protocal == PRO_FCP ){
|
||||
fill_len = pd_fill_single_group_no_src_com(data, idx, pSW);
|
||||
}else if(protocal == 0x0C){
|
||||
}else if(protocal == PRO_UFCS){
|
||||
fill_len = pd_fill_single_group_UFCS(data, idx, pSW);
|
||||
}else{
|
||||
fill_len = pd_fill_single_group_FCP_AFC(data, idx, pSW);
|
||||
fill_len = chrg_source_fill_AFC_three_gears(data, idx, pSW);
|
||||
}
|
||||
idx += fill_len;
|
||||
send_len = idx; // 总填充字节数
|
||||
chrg_north_pkg_encode(ID_SOURCE, SRC_CMD_SET_PROTOCOL, data, send_len, frame, &len);
|
||||
rt_kprintf("idx = %d ",idx);
|
||||
#if NORTH_SOURCE_DEBUG
|
||||
rt_kprintf("source protocol frame:");
|
||||
for (rt_uint16_t i = 0; i < len; i++) {
|
||||
rt_kprintf(" %02x", frame[i]);
|
||||
}
|
||||
rt_kprintf("\n");
|
||||
#endif
|
||||
// for(rt_uint8_t i=0;i<idx;i++){
|
||||
// rt_kprintf("%02x",data[i]);
|
||||
// }
|
||||
@@ -892,4 +1313,3 @@ int source_set_pd_new_com(rt_uint8_t pro, struct chrg_switch_t *pSW)
|
||||
return chrg_north_send(frame, len);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
文件名称 : chrg_source.c
|
||||
完成日期 :
|
||||
当前版本号 : V1.0
|
||||
当前版本号 : V1.1.9
|
||||
主要功能 : 北向数据source请求数据填充及发送,命令字定义。
|
||||
版本历史 : 创建原始版本
|
||||
说明 :
|
||||
@@ -25,6 +25,8 @@ struct chrg_switch_t;
|
||||
|
||||
#define SRC_CMD_SET_CC_CHOOSE 0x17
|
||||
|
||||
#define SRC_CMD_RESET 0x18
|
||||
|
||||
#define SRC_CMD_SET_PROTOCOL 0xD0
|
||||
|
||||
#define PROTOCOL_NONE 0x00 // 无快充
|
||||
@@ -137,39 +139,46 @@ struct set_qc_ack_t {
|
||||
|
||||
struct src_vc_t {
|
||||
rt_uint16_t voltage; // 读取 0.01V
|
||||
rt_uint16_t set_voltage; // 设置电压 mV
|
||||
rt_uint16_t set_current; // 设置电流 mA
|
||||
rt_uint16_t version; // 版本号
|
||||
};
|
||||
|
||||
#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类型
|
||||
rt_uint8_t pro_gear_idx; // 挡位
|
||||
rt_uint16_t min_vol; // 最小电压 mV
|
||||
rt_uint16_t max_vol; // 最大电压 mV
|
||||
rt_uint8_t vol_lvl; // CC线电平
|
||||
rt_uint8_t cc_set; // cc线选择 //0代表1+2,1代表cc1,2代表cc2
|
||||
rt_uint16_t protective_curr; // 保护电流
|
||||
rt_uint8_t CC_Set; // CC线选择:0=CC1+CC2,1=CC1,2=CC2
|
||||
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=低电压
|
||||
struct src_vc_t vc; // 读取数据
|
||||
rt_uint8_t work_mode;
|
||||
rt_uint8_t qc_err; // Source板0x20回码错误码,bit2表示协议/CC切换失败
|
||||
rt_uint16_t set_volt; // 北向解析后准备写入功率板的目标电压(mV)
|
||||
rt_uint16_t set_curr; // 北向解析后准备写入功率板的目标电流(mA)
|
||||
struct src_vc_t vc; // 北向回读数据
|
||||
struct vc_pd_t pd_get[2]; // 读取PD协议数据
|
||||
struct vc_pd_t pd_set[2]; // 设置PD协议数据
|
||||
struct vc_pd_t pd_set; // COM设置的协议挡位、类型和电压电流范围
|
||||
};
|
||||
// 电源工作状态机:COM只切换状态,具体功率板指令由状态处理函数下发
|
||||
enum {
|
||||
SOURCE_WORK_INIT = 0, // 初始化功率板并启动输出
|
||||
SOURCE_WORK_WAIT, // 参数未变化,不下发功率板指令
|
||||
SOURCE_WORK_RUNING, // 协商电压变化,下发一次新电压
|
||||
SOURCE_WORK_LOW, // 电压过低,停止功率板输出
|
||||
SOURCE_WORK_STOP, // 主动停止并关闭通道
|
||||
SOURCE_WORK_SWITCH, // 停止旧负载后进入电源INIT
|
||||
SOURCE_WORK_PROTOCOL_SWITCH, // 协议/CC切换前清零功率板输出
|
||||
SOURCE_WORK_FULL_RESET, // Submit output clear and stop commands
|
||||
SOURCE_WORK_FULL_RESET_WAIT, // Wait for output clear and stop
|
||||
SOURCE_WORK_FULL_RESET_RELAY, // Submit south relay-off command
|
||||
SOURCE_WORK_FULL_RESET_RELAY_WAIT,// Wait before disconnecting north relay
|
||||
SOURCE_WORK_INIT_WAIT, // Wait for Source init batch completion
|
||||
SOURCE_WORK_ON_TEST_DYNA,
|
||||
SOURCE_WORK_ON_TEST_SHORT,
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
函数名称: source_get_vc
|
||||
函数描述: source电压电流查询请求
|
||||
@@ -190,6 +199,8 @@ extern int source_get_vc (rt_uint16_t vol, rt_uint16_t cur);
|
||||
*****************************************************************/
|
||||
extern int source_get_pd (void);
|
||||
|
||||
extern int source_reset (void);
|
||||
|
||||
/*****************************************************************
|
||||
函数名称: source_set_cc_lvl
|
||||
函数描述: source 设置 cc 等级
|
||||
@@ -248,7 +259,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
|
||||
|
||||
|
||||
|
||||
@@ -75,12 +75,12 @@ rt_uint16_t mb_crc16 (rt_uint8_t *pucFrame, rt_uint16_t usLen)
|
||||
rt_uint8_t ucCRCLo = 0xFF;
|
||||
int iIndex;
|
||||
|
||||
if(usLen==8){
|
||||
for(int i = 0;i<usLen;i++){
|
||||
rt_kprintf("%02x ",pucFrame[i]);
|
||||
}
|
||||
rt_kprintf("\n");
|
||||
}
|
||||
// if(usLen==8){
|
||||
// for(int i = 0;i<usLen;i++){
|
||||
// rt_kprintf("%02x ",pucFrame[i]);
|
||||
// }
|
||||
// rt_kprintf("\n");
|
||||
// }
|
||||
|
||||
while ( usLen-- ) {
|
||||
iIndex = ucCRCLo ^ *(pucFrame++);
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
<UseTargetDll>1</UseTargetDll>
|
||||
<UseExternalTool>0</UseExternalTool>
|
||||
<RunIndependent>0</RunIndependent>
|
||||
<UpdateFlashBeforeDebugging>0</UpdateFlashBeforeDebugging>
|
||||
<UpdateFlashBeforeDebugging>1</UpdateFlashBeforeDebugging>
|
||||
<Capability>1</Capability>
|
||||
<DriverSelection>4096</DriverSelection>
|
||||
</Flash1>
|
||||
@@ -275,7 +275,7 @@
|
||||
</OCR_RVCT3>
|
||||
<OCR_RVCT4>
|
||||
<Type>1</Type>
|
||||
<StartAddress>0x8040000</StartAddress>
|
||||
<StartAddress>0x8000000</StartAddress>
|
||||
<Size>0x40000</Size>
|
||||
</OCR_RVCT4>
|
||||
<OCR_RVCT5>
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
*** Using Compiler 'V6.16', folder: 'D:\keil mdk 2\ARM\ARMCLANG\Bin'
|
||||
Build target 'chrg'
|
||||
compiling chrg_roll_nor.c...
|
||||
linking...
|
||||
Program Size: Code=146668 RO-data=15332 RW-data=9328 ZI-data=15968
|
||||
FromELF: creating hex file...
|
||||
After Build - User command #1: fromelf --bin .\build\keil\Obj\chrg.axf -o build/chrg.bin
|
||||
".\build\keil\Obj\chrg.axf" - 0 Error(s), 0 Warning(s).
|
||||
Build Time Elapsed: 00:00:02
|
||||
@@ -0,0 +1,9 @@
|
||||
*** Using Compiler 'V6.16', folder: 'D:\keil mdk 2\ARM\ARMCLANG\Bin'
|
||||
Build target 'chrg'
|
||||
compiling chrg_sink.c...
|
||||
linking...
|
||||
Program Size: Code=147156 RO-data=15312 RW-data=9328 ZI-data=15984
|
||||
FromELF: creating hex file...
|
||||
After Build - User command #1: fromelf --bin .\build\keil\Obj\chrg.axf -o build/chrg.bin
|
||||
".\build\keil\Obj\chrg.axf" - 0 Error(s), 0 Warning(s).
|
||||
Build Time Elapsed: 00:00:02
|
||||
@@ -0,0 +1,18 @@
|
||||
*** Using Compiler 'V6.16', folder: 'D:\keil mdk 2\ARM\ARMCLANG\Bin'
|
||||
Build target 'chrg'
|
||||
compiling chrg_north_pkg.c...
|
||||
compiling chrg_lcd.c...
|
||||
compiling chrg_thread.c...
|
||||
compiling chrg_south.c...
|
||||
compiling chrg_sink.c...
|
||||
compiling chrg_north.c...
|
||||
compiling chrg_source.c...
|
||||
compiling chrg_roll_nor.c...
|
||||
compiling chrg_roll_sou.c...
|
||||
compiling chrg_comm.c...
|
||||
linking...
|
||||
Program Size: Code=146988 RO-data=15312 RW-data=9328 ZI-data=15984
|
||||
FromELF: creating hex file...
|
||||
After Build - User command #1: fromelf --bin .\build\keil\Obj\chrg.axf -o build/chrg.bin
|
||||
".\build\keil\Obj\chrg.axf" - 0 Error(s), 0 Warning(s).
|
||||
Build Time Elapsed: 00:00:03
|
||||
@@ -0,0 +1,21 @@
|
||||
*** Using Compiler 'V6.16', folder: 'D:\keil mdk 2\ARM\ARMCLANG\Bin'
|
||||
Build target 'chrg'
|
||||
compiling chrg_rel.c...
|
||||
compiling chrg_vcom.c...
|
||||
compiling chrg_north_pkg.c...
|
||||
compiling chrg_lcd.c...
|
||||
compiling chrg_thread.c...
|
||||
compiling chrg_south.c...
|
||||
compiling chrg_eload.c...
|
||||
compiling chrg_sink.c...
|
||||
compiling chrg_north.c...
|
||||
compiling chrg_source.c...
|
||||
compiling chrg_roll_nor.c...
|
||||
compiling chrg_roll_sou.c...
|
||||
compiling chrg_comm.c...
|
||||
linking...
|
||||
Program Size: Code=146964 RO-data=15312 RW-data=9328 ZI-data=15984
|
||||
FromELF: creating hex file...
|
||||
After Build - User command #1: fromelf --bin .\build\keil\Obj\chrg.axf -o build/chrg.bin
|
||||
".\build\keil\Obj\chrg.axf" - 0 Error(s), 0 Warning(s).
|
||||
Build Time Elapsed: 00:00:02
|
||||
@@ -0,0 +1,21 @@
|
||||
*** Using Compiler 'V6.16', folder: 'D:\keil mdk 2\ARM\ARMCLANG\Bin'
|
||||
Build target 'chrg'
|
||||
compiling chrg_vcom.c...
|
||||
compiling chrg_thread.c...
|
||||
compiling chrg_north_pkg.c...
|
||||
compiling chrg_lcd.c...
|
||||
compiling chrg_rel.c...
|
||||
compiling chrg_eload.c...
|
||||
compiling chrg_sink.c...
|
||||
compiling chrg_south.c...
|
||||
compiling chrg_source.c...
|
||||
compiling chrg_north.c...
|
||||
compiling chrg_roll_nor.c...
|
||||
compiling chrg_roll_sou.c...
|
||||
compiling chrg_comm.c...
|
||||
linking...
|
||||
Program Size: Code=147032 RO-data=15312 RW-data=9328 ZI-data=15984
|
||||
FromELF: creating hex file...
|
||||
After Build - User command #1: fromelf --bin .\build\keil\Obj\chrg.axf -o build/chrg.bin
|
||||
".\build\keil\Obj\chrg.axf" - 0 Error(s), 0 Warning(s).
|
||||
Build Time Elapsed: 00:00:03
|
||||
@@ -0,0 +1,21 @@
|
||||
*** Using Compiler 'V6.16', folder: 'D:\keil mdk 2\ARM\ARMCLANG\Bin'
|
||||
Build target 'chrg'
|
||||
compiling chrg_rel.c...
|
||||
compiling chrg_north_pkg.c...
|
||||
compiling chrg_thread.c...
|
||||
compiling chrg_vcom.c...
|
||||
compiling chrg_lcd.c...
|
||||
compiling chrg_eload.c...
|
||||
compiling chrg_sink.c...
|
||||
compiling chrg_source.c...
|
||||
compiling chrg_south.c...
|
||||
compiling chrg_north.c...
|
||||
compiling chrg_roll_nor.c...
|
||||
compiling chrg_roll_sou.c...
|
||||
compiling chrg_comm.c...
|
||||
linking...
|
||||
Program Size: Code=146976 RO-data=15312 RW-data=9328 ZI-data=15984
|
||||
FromELF: creating hex file...
|
||||
After Build - User command #1: fromelf --bin .\build\keil\Obj\chrg.axf -o build/chrg.bin
|
||||
".\build\keil\Obj\chrg.axf" - 0 Error(s), 0 Warning(s).
|
||||
Build Time Elapsed: 00:00:03
|
||||
@@ -0,0 +1,9 @@
|
||||
*** Using Compiler 'V6.16', folder: 'D:\keil mdk 2\ARM\ARMCLANG\Bin'
|
||||
Build target 'chrg'
|
||||
compiling chrg_comm.c...
|
||||
linking...
|
||||
Program Size: Code=147096 RO-data=15312 RW-data=9328 ZI-data=15984
|
||||
FromELF: creating hex file...
|
||||
After Build - User command #1: fromelf --bin .\build\keil\Obj\chrg.axf -o build/chrg.bin
|
||||
".\build\keil\Obj\chrg.axf" - 0 Error(s), 0 Warning(s).
|
||||
Build Time Elapsed: 00:00:02
|
||||
@@ -0,0 +1,9 @@
|
||||
*** Using Compiler 'V6.16', folder: 'D:\keil mdk 2\ARM\ARMCLANG\Bin'
|
||||
Build target 'chrg'
|
||||
compiling chrg_sink.c...
|
||||
linking...
|
||||
Program Size: Code=147104 RO-data=15312 RW-data=9328 ZI-data=16000
|
||||
FromELF: creating hex file...
|
||||
After Build - User command #1: fromelf --bin .\build\keil\Obj\chrg.axf -o build/chrg.bin
|
||||
".\build\keil\Obj\chrg.axf" - 0 Error(s), 0 Warning(s).
|
||||
Build Time Elapsed: 00:00:01
|
||||
@@ -1 +1,4 @@
|
||||
LOAD %L INCREMENTAL
|
||||
BS HardFault_Handler
|
||||
BS rt_assert_handler
|
||||
G
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
Load "D:\\HUACE_Project\\3_Code\\HCDF_MID_405_Charger\\chrg_V.3.0\\apps\\chrg\\build\\keil\\Obj\\chrg.axf"
|
||||
Erase Done.Programming Done.Verify OK.Flash Load finished at 18:22:08
|
||||
@@ -0,0 +1,18 @@
|
||||
*** Using Compiler 'V6.16', folder: 'D:\Program Files\Keil_v5\ARM\ARMCLANG\Bin'
|
||||
Build target 'chrg'
|
||||
compiling chrg_roll_nor.c...
|
||||
compiling chrg_north.c...
|
||||
compiling chrg_south.c...
|
||||
compiling chrg_comm.c...
|
||||
compiling chrg_roll_sou.c...
|
||||
compiling chrg_lcd.c...
|
||||
compiling chrg_thread.c...
|
||||
compiling chrg_sink.c...
|
||||
compiling chrg_north_pkg.c...
|
||||
compiling chrg_eload.c...
|
||||
linking...
|
||||
Program Size: Code=141040 RO-data=15212 RW-data=8544 ZI-data=13968
|
||||
FromELF: creating hex file...
|
||||
After Build - User command #1: fromelf --bin .\build\keil\Obj\chrg.axf -o build/chrg.bin
|
||||
".\build\keil\Obj\chrg.axf" - 0 Error(s), 0 Warning(s).
|
||||
Build Time Elapsed: 00:00:06
|
||||
@@ -0,0 +1,130 @@
|
||||
*** Using Compiler 'V6.16', folder: 'D:\Program Files\Keil_v5\ARM\ARMCLANG\Bin'
|
||||
Rebuild target 'chrg'
|
||||
compiling main.c...
|
||||
compiling chrg_switch.c...
|
||||
compiling chrg_wdt.c...
|
||||
compiling chrg_gpio.c...
|
||||
compiling chrg_tmr.c...
|
||||
compiling chrg_fal.c...
|
||||
compiling chrg_tty.c...
|
||||
compiling chrg_led.c...
|
||||
compiling chrg_vcom.c...
|
||||
compiling chrg_rel.c...
|
||||
compiling chrg_roll_nor.c...
|
||||
compiling chrg_north.c...
|
||||
compiling chrg_south.c...
|
||||
compiling chrg_comm.c...
|
||||
compiling chrg_roll_sou.c...
|
||||
compiling chrg_lcd.c...
|
||||
compiling chrg_thread.c...
|
||||
compiling chrg_source.c...
|
||||
compiling chrg_sink.c...
|
||||
compiling chrg_north_pkg.c...
|
||||
compiling chrg_eload.c...
|
||||
compiling chrg_utils.c...
|
||||
compiling syscall_mem.c...
|
||||
compiling syscalls.c...
|
||||
compiling cctype.c...
|
||||
compiling cstdlib.c...
|
||||
compiling cstring.c...
|
||||
compiling ctime.c...
|
||||
compiling cunistd.c...
|
||||
compiling cwchar.c...
|
||||
compiling device.c...
|
||||
compiling hwtimer.c...
|
||||
compiling completion_comm.c...
|
||||
compiling completion_up.c...
|
||||
compiling condvar.c...
|
||||
compiling dataqueue.c...
|
||||
compiling pipe.c...
|
||||
compiling ringblk_buf.c...
|
||||
compiling ringbuffer.c...
|
||||
compiling waitqueue.c...
|
||||
compiling workqueue.c...
|
||||
compiling dev_pin.c...
|
||||
compiling dev_serial.c...
|
||||
compiling dev_watchdog.c...
|
||||
compiling stm32f4xx_hal_msp.c...
|
||||
compiling board.c...
|
||||
compiling drv_flash_f4.c...
|
||||
compiling drv_gpio.c...
|
||||
compiling drv_tim.c...
|
||||
compiling drv_usart.c...
|
||||
compiling drv_usbd.c...
|
||||
compiling drv_wdt.c...
|
||||
compiling drv_common.c...
|
||||
compiling fal.c...
|
||||
compiling fal_flash.c...
|
||||
compiling fal_partition.c...
|
||||
compiling fal_rtt.c...
|
||||
compiling shell.c...
|
||||
compiling msh_parse.c...
|
||||
compiling cmd.c...
|
||||
compiling msh.c...
|
||||
compiling clock.c...
|
||||
compiling components.c...
|
||||
compiling cpu_up.c...
|
||||
compiling defunct.c...
|
||||
compiling idle.c...
|
||||
compiling ipc.c...
|
||||
compiling irq.c...
|
||||
compiling kservice.c...
|
||||
compiling memheap.c...
|
||||
compiling mempool.c...
|
||||
compiling object.c...
|
||||
compiling scheduler_comm.c...
|
||||
compiling scheduler_up.c...
|
||||
compiling thread.c...
|
||||
compiling timer.c...
|
||||
compiling rt_vsnprintf_tiny.c...
|
||||
compiling kerrno.c...
|
||||
compiling kstring.c...
|
||||
compiling rt_vsscanf.c...
|
||||
compiling kstdio.c...
|
||||
compiling atomic_arm.c...
|
||||
compiling div0.c...
|
||||
compiling showmem.c...
|
||||
assembling context_rvds.S...
|
||||
compiling cpuport.c...
|
||||
compiling usbdevice.c...
|
||||
compiling cdc_vcom.c...
|
||||
compiling usbdevice_core.c...
|
||||
assembling startup_stm32f405xx.s...
|
||||
compiling system_stm32f4xx.c...
|
||||
compiling stm32f4xx_hal_gpio.c...
|
||||
compiling stm32f4xx_hal_flash.c...
|
||||
compiling stm32f4xx_hal_usart.c...
|
||||
compiling stm32f4xx_hal_rng.c...
|
||||
compiling stm32f4xx_hal_uart.c...
|
||||
compiling stm32f4xx_hal_wwdg.c...
|
||||
compiling stm32f4xx_hal_tim.c...
|
||||
compiling stm32f4xx_hal_cryp_ex.c...
|
||||
compiling stm32f4xx_hal_pwr.c...
|
||||
compiling stm32f4xx_hal_rcc.c...
|
||||
compiling stm32f4xx_hal_hcd.c...
|
||||
compiling stm32f4xx_ll_usb.c...
|
||||
compiling stm32f4xx_hal_pccard.c...
|
||||
compiling stm32f4xx_hal_flash_ex.c...
|
||||
compiling stm32f4xx_hal_flash_ramfunc.c...
|
||||
compiling stm32f4xx_hal_tim_ex.c...
|
||||
compiling stm32f4xx_hal_lptim.c...
|
||||
compiling stm32f4xx_hal_cec.c...
|
||||
compiling stm32f4xx_hal_cryp.c...
|
||||
compiling stm32f4xx_hal.c...
|
||||
compiling stm32f4xx_hal_iwdg.c...
|
||||
compiling stm32f4xx_hal_pcd_ex.c...
|
||||
compiling stm32f4xx_hal_pcd.c...
|
||||
compiling stm32f4xx_hal_crc.c...
|
||||
compiling stm32f4xx_hal_dma_ex.c...
|
||||
compiling stm32f4xx_hal_cortex.c...
|
||||
compiling stm32f4xx_hal_dma.c...
|
||||
compiling stm32f4xx_hal_rcc_ex.c...
|
||||
compiling stm32f4xx_hal_pwr_ex.c...
|
||||
compiling ulog.c...
|
||||
compiling console_be.c...
|
||||
linking...
|
||||
Program Size: Code=139712 RO-data=15040 RW-data=8544 ZI-data=13704
|
||||
FromELF: creating hex file...
|
||||
After Build - User command #1: fromelf --bin .\build\keil\Obj\chrg.axf -o build/chrg.bin
|
||||
".\build\keil\Obj\chrg.axf" - 0 Error(s), 0 Warning(s).
|
||||
Build Time Elapsed: 00:00:29
|
||||
@@ -0,0 +1,130 @@
|
||||
*** Using Compiler 'V6.16', folder: 'D:\Program Files\Keil_v5\ARM\ARMCLANG\Bin'
|
||||
Rebuild target 'chrg'
|
||||
compiling main.c...
|
||||
compiling chrg_switch.c...
|
||||
compiling chrg_wdt.c...
|
||||
compiling chrg_gpio.c...
|
||||
compiling chrg_tmr.c...
|
||||
compiling chrg_fal.c...
|
||||
compiling chrg_tty.c...
|
||||
compiling chrg_led.c...
|
||||
compiling chrg_vcom.c...
|
||||
compiling chrg_rel.c...
|
||||
compiling chrg_roll_nor.c...
|
||||
compiling chrg_north.c...
|
||||
compiling chrg_south.c...
|
||||
compiling chrg_comm.c...
|
||||
compiling chrg_roll_sou.c...
|
||||
compiling chrg_lcd.c...
|
||||
compiling chrg_thread.c...
|
||||
compiling chrg_source.c...
|
||||
compiling chrg_sink.c...
|
||||
compiling chrg_north_pkg.c...
|
||||
compiling chrg_eload.c...
|
||||
compiling chrg_utils.c...
|
||||
compiling syscall_mem.c...
|
||||
compiling syscalls.c...
|
||||
compiling cctype.c...
|
||||
compiling cstdlib.c...
|
||||
compiling cstring.c...
|
||||
compiling ctime.c...
|
||||
compiling cunistd.c...
|
||||
compiling cwchar.c...
|
||||
compiling device.c...
|
||||
compiling hwtimer.c...
|
||||
compiling completion_comm.c...
|
||||
compiling completion_up.c...
|
||||
compiling condvar.c...
|
||||
compiling dataqueue.c...
|
||||
compiling pipe.c...
|
||||
compiling ringblk_buf.c...
|
||||
compiling ringbuffer.c...
|
||||
compiling waitqueue.c...
|
||||
compiling workqueue.c...
|
||||
compiling dev_pin.c...
|
||||
compiling dev_serial.c...
|
||||
compiling dev_watchdog.c...
|
||||
compiling stm32f4xx_hal_msp.c...
|
||||
compiling board.c...
|
||||
compiling drv_flash_f4.c...
|
||||
compiling drv_gpio.c...
|
||||
compiling drv_tim.c...
|
||||
compiling drv_usart.c...
|
||||
compiling drv_usbd.c...
|
||||
compiling drv_wdt.c...
|
||||
compiling drv_common.c...
|
||||
compiling fal.c...
|
||||
compiling fal_flash.c...
|
||||
compiling fal_partition.c...
|
||||
compiling fal_rtt.c...
|
||||
compiling shell.c...
|
||||
compiling msh_parse.c...
|
||||
compiling cmd.c...
|
||||
compiling msh.c...
|
||||
compiling clock.c...
|
||||
compiling components.c...
|
||||
compiling cpu_up.c...
|
||||
compiling defunct.c...
|
||||
compiling idle.c...
|
||||
compiling ipc.c...
|
||||
compiling irq.c...
|
||||
compiling kservice.c...
|
||||
compiling memheap.c...
|
||||
compiling mempool.c...
|
||||
compiling object.c...
|
||||
compiling scheduler_comm.c...
|
||||
compiling scheduler_up.c...
|
||||
compiling thread.c...
|
||||
compiling timer.c...
|
||||
compiling rt_vsnprintf_tiny.c...
|
||||
compiling kerrno.c...
|
||||
compiling kstring.c...
|
||||
compiling rt_vsscanf.c...
|
||||
compiling kstdio.c...
|
||||
compiling atomic_arm.c...
|
||||
compiling div0.c...
|
||||
compiling showmem.c...
|
||||
assembling context_rvds.S...
|
||||
compiling cpuport.c...
|
||||
compiling usbdevice.c...
|
||||
compiling cdc_vcom.c...
|
||||
compiling usbdevice_core.c...
|
||||
assembling startup_stm32f405xx.s...
|
||||
compiling system_stm32f4xx.c...
|
||||
compiling stm32f4xx_hal_gpio.c...
|
||||
compiling stm32f4xx_hal_flash.c...
|
||||
compiling stm32f4xx_hal_usart.c...
|
||||
compiling stm32f4xx_hal_rng.c...
|
||||
compiling stm32f4xx_hal_uart.c...
|
||||
compiling stm32f4xx_hal_wwdg.c...
|
||||
compiling stm32f4xx_hal_tim.c...
|
||||
compiling stm32f4xx_hal_cryp_ex.c...
|
||||
compiling stm32f4xx_hal_pwr.c...
|
||||
compiling stm32f4xx_hal_rcc.c...
|
||||
compiling stm32f4xx_hal_hcd.c...
|
||||
compiling stm32f4xx_ll_usb.c...
|
||||
compiling stm32f4xx_hal_pccard.c...
|
||||
compiling stm32f4xx_hal_flash_ex.c...
|
||||
compiling stm32f4xx_hal_flash_ramfunc.c...
|
||||
compiling stm32f4xx_hal_tim_ex.c...
|
||||
compiling stm32f4xx_hal_lptim.c...
|
||||
compiling stm32f4xx_hal_cec.c...
|
||||
compiling stm32f4xx_hal_cryp.c...
|
||||
compiling stm32f4xx_hal.c...
|
||||
compiling stm32f4xx_hal_iwdg.c...
|
||||
compiling stm32f4xx_hal_pcd_ex.c...
|
||||
compiling stm32f4xx_hal_pcd.c...
|
||||
compiling stm32f4xx_hal_crc.c...
|
||||
compiling stm32f4xx_hal_dma_ex.c...
|
||||
compiling stm32f4xx_hal_cortex.c...
|
||||
compiling stm32f4xx_hal_dma.c...
|
||||
compiling stm32f4xx_hal_rcc_ex.c...
|
||||
compiling stm32f4xx_hal_pwr_ex.c...
|
||||
compiling ulog.c...
|
||||
compiling console_be.c...
|
||||
linking...
|
||||
Program Size: Code=140360 RO-data=15152 RW-data=8544 ZI-data=13712
|
||||
FromELF: creating hex file...
|
||||
After Build - User command #1: fromelf --bin .\build\keil\Obj\chrg.axf -o build/chrg.bin
|
||||
".\build\keil\Obj\chrg.axf" - 0 Error(s), 0 Warning(s).
|
||||
Build Time Elapsed: 00:00:29
|
||||
@@ -0,0 +1,130 @@
|
||||
*** Using Compiler 'V6.16', folder: 'D:\Program Files\Keil_v5\ARM\ARMCLANG\Bin'
|
||||
Rebuild target 'chrg'
|
||||
compiling main.c...
|
||||
compiling chrg_switch.c...
|
||||
compiling chrg_wdt.c...
|
||||
compiling chrg_gpio.c...
|
||||
compiling chrg_tmr.c...
|
||||
compiling chrg_fal.c...
|
||||
compiling chrg_tty.c...
|
||||
compiling chrg_led.c...
|
||||
compiling chrg_vcom.c...
|
||||
compiling chrg_rel.c...
|
||||
compiling chrg_roll_nor.c...
|
||||
compiling chrg_north.c...
|
||||
compiling chrg_south.c...
|
||||
compiling chrg_comm.c...
|
||||
compiling chrg_roll_sou.c...
|
||||
compiling chrg_lcd.c...
|
||||
compiling chrg_thread.c...
|
||||
compiling chrg_source.c...
|
||||
compiling chrg_sink.c...
|
||||
compiling chrg_north_pkg.c...
|
||||
compiling chrg_eload.c...
|
||||
compiling chrg_utils.c...
|
||||
compiling syscall_mem.c...
|
||||
compiling syscalls.c...
|
||||
compiling cctype.c...
|
||||
compiling cstdlib.c...
|
||||
compiling cstring.c...
|
||||
compiling ctime.c...
|
||||
compiling cunistd.c...
|
||||
compiling cwchar.c...
|
||||
compiling device.c...
|
||||
compiling hwtimer.c...
|
||||
compiling completion_comm.c...
|
||||
compiling completion_up.c...
|
||||
compiling condvar.c...
|
||||
compiling dataqueue.c...
|
||||
compiling pipe.c...
|
||||
compiling ringblk_buf.c...
|
||||
compiling ringbuffer.c...
|
||||
compiling waitqueue.c...
|
||||
compiling workqueue.c...
|
||||
compiling dev_pin.c...
|
||||
compiling dev_serial.c...
|
||||
compiling dev_watchdog.c...
|
||||
compiling stm32f4xx_hal_msp.c...
|
||||
compiling board.c...
|
||||
compiling drv_flash_f4.c...
|
||||
compiling drv_gpio.c...
|
||||
compiling drv_tim.c...
|
||||
compiling drv_usart.c...
|
||||
compiling drv_usbd.c...
|
||||
compiling drv_wdt.c...
|
||||
compiling drv_common.c...
|
||||
compiling fal.c...
|
||||
compiling fal_flash.c...
|
||||
compiling fal_partition.c...
|
||||
compiling fal_rtt.c...
|
||||
compiling shell.c...
|
||||
compiling msh_parse.c...
|
||||
compiling cmd.c...
|
||||
compiling msh.c...
|
||||
compiling clock.c...
|
||||
compiling components.c...
|
||||
compiling cpu_up.c...
|
||||
compiling defunct.c...
|
||||
compiling idle.c...
|
||||
compiling ipc.c...
|
||||
compiling irq.c...
|
||||
compiling kservice.c...
|
||||
compiling memheap.c...
|
||||
compiling mempool.c...
|
||||
compiling object.c...
|
||||
compiling scheduler_comm.c...
|
||||
compiling scheduler_up.c...
|
||||
compiling thread.c...
|
||||
compiling timer.c...
|
||||
compiling rt_vsnprintf_tiny.c...
|
||||
compiling kerrno.c...
|
||||
compiling kstring.c...
|
||||
compiling rt_vsscanf.c...
|
||||
compiling kstdio.c...
|
||||
compiling atomic_arm.c...
|
||||
compiling div0.c...
|
||||
compiling showmem.c...
|
||||
assembling context_rvds.S...
|
||||
compiling cpuport.c...
|
||||
compiling usbdevice.c...
|
||||
compiling cdc_vcom.c...
|
||||
compiling usbdevice_core.c...
|
||||
assembling startup_stm32f405xx.s...
|
||||
compiling system_stm32f4xx.c...
|
||||
compiling stm32f4xx_hal_gpio.c...
|
||||
compiling stm32f4xx_hal_flash.c...
|
||||
compiling stm32f4xx_hal_usart.c...
|
||||
compiling stm32f4xx_hal_rng.c...
|
||||
compiling stm32f4xx_hal_uart.c...
|
||||
compiling stm32f4xx_hal_wwdg.c...
|
||||
compiling stm32f4xx_hal_tim.c...
|
||||
compiling stm32f4xx_hal_cryp_ex.c...
|
||||
compiling stm32f4xx_hal_pwr.c...
|
||||
compiling stm32f4xx_hal_rcc.c...
|
||||
compiling stm32f4xx_hal_hcd.c...
|
||||
compiling stm32f4xx_ll_usb.c...
|
||||
compiling stm32f4xx_hal_pccard.c...
|
||||
compiling stm32f4xx_hal_flash_ex.c...
|
||||
compiling stm32f4xx_hal_flash_ramfunc.c...
|
||||
compiling stm32f4xx_hal_tim_ex.c...
|
||||
compiling stm32f4xx_hal_lptim.c...
|
||||
compiling stm32f4xx_hal_cec.c...
|
||||
compiling stm32f4xx_hal_cryp.c...
|
||||
compiling stm32f4xx_hal.c...
|
||||
compiling stm32f4xx_hal_iwdg.c...
|
||||
compiling stm32f4xx_hal_pcd_ex.c...
|
||||
compiling stm32f4xx_hal_pcd.c...
|
||||
compiling stm32f4xx_hal_crc.c...
|
||||
compiling stm32f4xx_hal_dma_ex.c...
|
||||
compiling stm32f4xx_hal_cortex.c...
|
||||
compiling stm32f4xx_hal_dma.c...
|
||||
compiling stm32f4xx_hal_rcc_ex.c...
|
||||
compiling stm32f4xx_hal_pwr_ex.c...
|
||||
compiling ulog.c...
|
||||
compiling console_be.c...
|
||||
linking...
|
||||
Program Size: Code=139960 RO-data=15064 RW-data=8544 ZI-data=13704
|
||||
FromELF: creating hex file...
|
||||
After Build - User command #1: fromelf --bin .\build\keil\Obj\chrg.axf -o build/chrg.bin
|
||||
".\build\keil\Obj\chrg.axf" - 0 Error(s), 0 Warning(s).
|
||||
Build Time Elapsed: 00:00:27
|
||||
@@ -0,0 +1,9 @@
|
||||
*** Using Compiler 'V6.16', folder: 'D:\Program Files\Keil_v5\ARM\ARMCLANG\Bin'
|
||||
Build target 'chrg'
|
||||
compiling chrg_north.c...
|
||||
linking...
|
||||
Program Size: Code=140256 RO-data=15160 RW-data=8544 ZI-data=13704
|
||||
FromELF: creating hex file...
|
||||
After Build - User command #1: fromelf --bin .\build\keil\Obj\chrg.axf -o build/chrg.bin
|
||||
".\build\keil\Obj\chrg.axf" - 0 Error(s), 0 Warning(s).
|
||||
Build Time Elapsed: 00:00:02
|
||||
@@ -0,0 +1,121 @@
|
||||
# Source 状态机改造与角色切换维护计划
|
||||
|
||||
## 1. 改造目标
|
||||
|
||||
将电源(Source)控制整理为与负载(Sink)类似的独立状态机,但保留两者业务差异:
|
||||
|
||||
- 北向协议板只负责角色/CC 线选择、协议设置及周期读取协议板电压电流。
|
||||
- 功率板角色、模式、电压、电流、继电器和启停全部由 `chrg_source.c` 管理。
|
||||
- 所有 Source 南向寄存器命令统一使用 `chrg_sou_com_batch_submit()`,不再散落调用 `chrg_set_sou_reg()`。
|
||||
- Source 不判断带载电流。协议板返回电压有效则进入 `RUNNING`;启动后持续无电压则回到 `WAIT`。
|
||||
- 协议、协议电压或协议电流发生变化时,重新进入 `INIT`。
|
||||
- Source/Sink 不停机切换时,必须先停止旧角色,确认完成后再初始化新角色。
|
||||
|
||||
## 2. 当前已完成的修改
|
||||
|
||||
当前工作区已完成第一阶段,尚未形成完整状态机:
|
||||
|
||||
1. `apps/chrg/applications/utils/chrg_source.c`
|
||||
- 新增 `chrg_source_init_submit(rt_uint8_t idx, struct chrg_switch_t *pSW)`。
|
||||
- 通过一个批次下发 `REG_ELOAD`、`REG_MODE`、`REG_VOLTAGE_OUT + 1`、`REG_CURRENT_OUT + 1` 和 `REG_WORK = WORK_STOP`。
|
||||
2. `apps/chrg/applications/utils/chrg_source.h`
|
||||
- 增加上述函数声明。
|
||||
3. `apps/chrg/applications/thread/chrg_roll_nor.c`
|
||||
- Source 协议设置流程进入 `IDX_GET_SOURCE_VC` 后提交南向初始化批次。
|
||||
- 仅当批次提交成功时设置 `source.On_Flag = 1`。
|
||||
|
||||
注意:当前仍有旧 Source 路径在 `chrg_north.c`、`chrg_roll_nor.c` 和 `chrg_lcd.c` 中直接调用 `chrg_set_sou_reg()`。在完成后续步骤前,新旧逻辑会同时存在,不能作为最终版本发布。
|
||||
|
||||
## 3. 目标状态机
|
||||
|
||||
在 `chrg_source.h` 中增加明确的 Source 状态:
|
||||
|
||||
```c
|
||||
typedef enum {
|
||||
SOURCE_WORK_STOP = 0,
|
||||
SOURCE_WORK_WAIT,
|
||||
SOURCE_WORK_INIT,
|
||||
SOURCE_WORK_START,
|
||||
SOURCE_WORK_RUNNING,
|
||||
SOURCE_WORK_STOPPING,
|
||||
SOURCE_WORK_FAULT
|
||||
} source_work_mode_t;
|
||||
```
|
||||
|
||||
在 `chrg_src_t` 中增加每通道状态及参数快照:`work_mode`、`last_protocol`、`last_voltage`、`last_current`、`zero_volt_count`、`retry_count`。参数快照只能在对应命令确认完成后更新。
|
||||
|
||||
状态动作:
|
||||
|
||||
| 状态 | 动作 | 后续状态 |
|
||||
|---|---|---|
|
||||
| `INIT` | 批量设置 Source 角色、模式、电压、电流及继电器,保持停止 | `START` |
|
||||
| `START` | 批量下发 `REG_WORK = WORK_START` | `WAIT` |
|
||||
| `WAIT` | 北向周期读取协议板 VC | 有电压进入 `RUNNING` |
|
||||
| `RUNNING` | 更新 VC;检测协议/电压/电流变化 | 变化进入 `INIT` |
|
||||
| `STOPPING` | 批量停止输出、关闭功率板继电器 | `STOP` |
|
||||
| `STOP` | 清理使能并断开北向继电器 | 保持 |
|
||||
|
||||
建议电压大于 `WORK_MIN_VOLT` 即视为有效。电压为零连续 3 次再由 `RUNNING` 回到 `WAIT`,避免单帧异常造成状态抖动。
|
||||
|
||||
## 4. COM 端改造
|
||||
|
||||
修改 `chrg_mb_write_sys()`:
|
||||
|
||||
- 当目标角色为 Source 且当前未工作时,只设置 `pSW->sub = IDX_SET_SOURCE_CC_SET`,由北向依次完成 CC 和协议设置;协议应答完成后才进入 `SOURCE_WORK_INIT`。
|
||||
- 同角色下,比较协议、协议电压、协议电流。任一变化则进入 `SOURCE_WORK_INIT`;相同参数不得重复初始化。
|
||||
- 不要在收到 `SYS_REG_ROLE_SWITCH` 时立即覆盖实际角色。应保存 `target_role`,在参数生效时启动切换流程。
|
||||
- 切换期间返回 `MB_EX_SLAVE_BUSY`,或者只更新影子参数并等待本次切换完成。
|
||||
|
||||
角色切换顺序:
|
||||
|
||||
```text
|
||||
Source -> Sink: Source STOPPING -> STOP -> 切换角色/继电器 -> Sink INIT
|
||||
Sink -> Source: Sink STOP -> 切换角色/继电器 -> 北向 CC/协议 -> Source INIT
|
||||
```
|
||||
|
||||
禁止 Source 和 Sink 的功率板继电器、工作命令在同一通道同时有效。
|
||||
|
||||
## 5. 北向流程改造
|
||||
|
||||
精简 `chrg_roll_nor_set()` 的 Source 分支,只保留:
|
||||
|
||||
1. `IDX_SET_SOURCE_CC_SET`:设置 CC 线,成功后进入 `IDX_SET_SOURCE_PD`。
|
||||
2. `IDX_SET_SOURCE_PD`:设置协议,应答成功后设置 `SOURCE_WORK_INIT`。
|
||||
3. `IDX_GET_SOURCE_VC`:读取协议板电压电流。
|
||||
|
||||
删除 Source 分支中的 `IDX_SET_SOURCE_ID`、`IDX_SET_SOURCE_CV`、`IDX_SER_SOURCE_VOLT`、`IDX_SER_SOURCE_CURR`、`IDX_SET_SOURCE_WORK` 南向设置动作。校准、控制台和 Sink 分支不在本次范围内。
|
||||
|
||||
`chrg_north.c` 只解析 Source VC:更新 `source.vc`、`Now_voltage`、`Now_current`,并根据电压推进 `WAIT/RUNNING`。移除 `chrg_source_standard_output()`、`chrg_source_fast_output()` 和旧的分步停机控制,避免解析函数直接下发南向命令。
|
||||
|
||||
## 6. 南向完成确认
|
||||
|
||||
`chrg_sou_com_batch_submit()` 返回成功仅表示入队成功,不表示功率板已经执行。需要为每通道增加批次完成序号或完成事件:
|
||||
|
||||
- `INIT` 批次全部应答匹配后才能进入 `START`。
|
||||
- `START` 应答成功后才能进入 `WAIT`。
|
||||
- `STOPPING` 批次完成后才能断开北向继电器和修改实际角色。
|
||||
- CRC 错误、寄存器不匹配或超时不得推进状态;达到重试上限后进入 `FAULT`。
|
||||
|
||||
## 7. 推荐实施顺序
|
||||
|
||||
1. 增加 Source 状态枚举、参数快照及 `chrg_source_work()`。
|
||||
2. 将 INIT、START、STOPPING 的南向动作全部迁移到 `chrg_source.c`。
|
||||
3. 增加南向批次完成通知,再改为应答驱动状态转换。
|
||||
4. 精简北向 Source 子状态,只保留 CC、协议和 VC。
|
||||
5. 修改 COM 同角色参数差异及跨角色切换。
|
||||
6. 清理 `chrg_lcd.c` 中重复的 Source 启停和角色寄存器写入。
|
||||
7. 编译并在硬件验证后删除旧字段和旧函数。
|
||||
|
||||
## 8. 验证清单
|
||||
|
||||
- Keil 编译 `apps/chrg/chrg.uvprojx`,确认无未定义符号和头文件循环依赖。
|
||||
- 单通道验证 Source 首次启动、停止、相同参数重复生效。
|
||||
- 分别改变协议、协议电压和协议电流,确认只执行一次重新 INIT。
|
||||
- 模拟协议板电压持续为零,确认进入 WAIT 且不会反复提交相同批次。
|
||||
- 验证 Source -> Sink、Sink -> Source,示波器确认切换期间无输出重叠。
|
||||
- 四通道同时运行并交叉切换,检查南向队列饥饿、响应错配、超时和缓存串通道。
|
||||
- 回归 Sink 正常负载、动态测试、无电流重启及低压处理。
|
||||
|
||||
## 9. 接手注意事项
|
||||
|
||||
开始修改前先执行 `git status --short` 和 `git diff`。当前 `chrg_north.c` 还包含此前 Sink 连续确认次数改为 3 的修改及注释清理,不能在 Source 重构时回退。不要提交 Keil `build/`、`Obj/`、AXF、BIN 或 MAP 等生成文件。
|
||||
@@ -0,0 +1,101 @@
|
||||
# Source CC_CLOSE 协议切换修改说明
|
||||
|
||||
## 修改目标
|
||||
|
||||
修正 Source 北向协议板的命令顺序,避免在 CC 保持 Attached 时直接重配
|
||||
`0xD0`。多通道同时切换时采用共享等待屏障,使保护时间并行发生,不按
|
||||
通道串行累计。
|
||||
|
||||
## 本轮实施步骤
|
||||
|
||||
### 第一步:统一状态命名
|
||||
|
||||
断开 CC 的命令状态命名为 `IDX_SET_SOURCE_CC_CLOSE`,等待状态命名为
|
||||
`IDX_WAIT_SOURCE_CC_CLOSE`。`CC_CLOSE` 固定发送 `0x17=0x03`,不覆盖
|
||||
COM 保存的目标 `CC_Set`。
|
||||
|
||||
### 第二步:调整停止态启动顺序
|
||||
|
||||
Source 从停止状态启动以及 Sink 切换为 Source 时,不发送 `CC_CLOSE`,
|
||||
直接按以下顺序执行:
|
||||
|
||||
```text
|
||||
IDX_SET_SOURCE_PD
|
||||
-> IDX_WAIT_SOURCE_PROTOCOL
|
||||
-> IDX_SET_SOURCE_CC_SET
|
||||
-> IDX_GET_SOURCE_VC
|
||||
```
|
||||
|
||||
即先设置协议,收到 `0xD0` ACK 并完成保护等待后,再连接目标 CC。
|
||||
|
||||
### 第三步:识别必须断开 CC 的切换
|
||||
|
||||
COM 参数生效时,满足以下任一条件进入 `CC_CLOSE`:
|
||||
|
||||
- 新协议为 PD/PPS 或 PD3.1/AVS,并且协议或 CC 线与上次不同。
|
||||
- 上次协议为 PD/PPS 或 PD3.1/AVS,本次切换为非 PD 协议。
|
||||
|
||||
其它协议配置变化从 `IDX_SET_SOURCE_PD` 开始。标准协议仅改变电压、电流
|
||||
时直接更新功率板,不重复下发 `0xD0`。
|
||||
|
||||
### 第四步:执行 CC_CLOSE 命令链
|
||||
|
||||
COM先确定北向`sub`,协议或CC发生变化时进入
|
||||
`SOURCE_WORK_PROTOCOL_SWITCH`,不在COM中调用发送函数。北向轮询线程
|
||||
执行该Source工作状态,负责向南向功率板写入0V;标准协议还会在同一批
|
||||
命令中依次写模式和电流。提交成功后清零`set_volt`并进入
|
||||
`SOURCE_WORK_WAIT`,随后按已经选定的`sub`继续执行。
|
||||
|
||||
需要断开 CC 的通道按以下顺序执行:
|
||||
|
||||
```text
|
||||
IDX_SET_SOURCE_CC_CLOSE 发送 0x17=0x03
|
||||
-> IDX_WAIT_SOURCE_CC_CLOSE 等待共享保护时间
|
||||
-> IDX_SET_SOURCE_PD 发送 0xD0
|
||||
-> IDX_WAIT_SOURCE_PROTOCOL 等待协议 ACK 后保护时间
|
||||
-> IDX_SET_SOURCE_CC_SET 发送 0x17=目标 CC
|
||||
-> IDX_GET_SOURCE_VC 恢复 0x20 查询
|
||||
```
|
||||
|
||||
每条设置命令仍需收到角色、命令、长度和 CRC 均正确的回码后才能推进
|
||||
`sub`;错误回码继续沿用现有丢弃和有限重发逻辑。
|
||||
|
||||
### 第五步:多通道共享 CC_CLOSE 等待
|
||||
|
||||
使用 `pending_mask` 和 `acked_mask` 管理本轮参与切换的 Source 通道。
|
||||
所有已登记通道都收到 `0x17` ACK 后,只启动一次 300 ms 保护等待。
|
||||
一个通道和四个通道的保护等待本身均为 300 ms;四通道只额外产生必要的
|
||||
命令收发时间,不会累计为四次 300 ms。
|
||||
|
||||
### 第六步:握手稳定确认(本轮不修改)
|
||||
|
||||
本轮不增加“连续两次 `0x20` 电压稳定后才进入 RUNNING”的新逻辑,继续
|
||||
使用现有 `chrg_source_parse()` 电压误差和重试规则。
|
||||
|
||||
### 第七步:配置覆盖保护
|
||||
|
||||
继续使用 `config_version` 防止 COM 新配置被旧回码推进。停止、角色切换
|
||||
或不再需要 `CC_CLOSE` 时,会把通道移出共享等待屏障,避免残留状态影响
|
||||
下一次启动。
|
||||
|
||||
### 第八步:完整失败恢复(本轮不修改)
|
||||
|
||||
本轮不增加握手总超时、再次 detach、整套流程最多重试两轮以及故障上报。
|
||||
单条北向命令仍使用现有的三次发送机制。完整恢复流程待单独验证后实施。
|
||||
|
||||
## 时间参数
|
||||
|
||||
| 参数 | 当前值 | 说明 |
|
||||
|---|---:|---|
|
||||
| `SOURCE_CC_CLOSE_WAIT_MS` | 300 ms | 从本轮最后一个有效 `CC_CLOSE` ACK 开始 |
|
||||
| `SOURCE_PROTOCOL_WAIT_MS` | 100 ms | 每通道收到 `0xD0` ACK 后并行等待 |
|
||||
| `NORTH_RESPONSE_TIMEOUT_MS` | 50 ms | 单次北向回码等待 |
|
||||
| `NORTH_REQUEST_MAX_RETRIES` | 2 | 首次发送外最多重发两次 |
|
||||
|
||||
## 建议验证顺序
|
||||
|
||||
1. 单通道停止态启动 PD,确认发送顺序为 `D0 -> 17(目标CC) -> 20`。
|
||||
2. 单通道 PD 改协议或 CC,确认顺序为 `17(03) -> 等待 -> D0 -> 17(目标CC) -> 20`。
|
||||
3. 单通道 PD 切换 QC/FCP/标准,确认切换前先发送 `17(03)`。
|
||||
4. 四通道连续生效,确认四路 `17(03)` 均回码后共享一次约 300 ms 等待。
|
||||
5. 连续执行 20 至 30 轮协议切换,检查是否仍出现 Source 芯片 PD 状态异常。
|
||||
+2519
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,310 @@
|
||||
param(
|
||||
[string]$OutputDirectory = 'D:\HC-PMP-SW\Power_ControlPannel\MP_Control_sw_405\拖拽式平台\docs'
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
function New-Criteria {
|
||||
param([int]$VoltageToleranceMv, [int]$CurrentToleranceMa)
|
||||
[ordered]@{
|
||||
VoltageToleranceMv = $VoltageToleranceMv
|
||||
CurrentToleranceMa = $CurrentToleranceMa
|
||||
ShortVoltageMinMv = 0
|
||||
ShortVoltageMaxMv = 1000
|
||||
ShortCurrentMinMa = 0
|
||||
ShortCurrentMaxMa = 1000
|
||||
OcpVoltageMinMv = 0
|
||||
OcpVoltageMaxMv = 5000
|
||||
OcpCurrentMinMa = 4500
|
||||
OcpCurrentMaxMa = 5500
|
||||
DynamicVpkPlusMinMv = 0
|
||||
DynamicVpkPlusMaxMv = 65535
|
||||
DynamicVpkMinusMinMv = 0
|
||||
DynamicVpkMinusMaxMv = 65535
|
||||
}
|
||||
}
|
||||
|
||||
function New-DmpItem {
|
||||
param(
|
||||
[string]$Name,
|
||||
[int]$Channel,
|
||||
[string]$Protocol,
|
||||
[int]$VoltageMv,
|
||||
[int]$ProtocolCurrentMa,
|
||||
[int]$LoadCurrentMa,
|
||||
[int]$VoltageToleranceMv,
|
||||
[int]$CurrentToleranceMa,
|
||||
[int]$QueryDelayMs,
|
||||
[string]$OutputAction = 'Start',
|
||||
[int]$Gear = 0,
|
||||
[int]$CcSelection = -1,
|
||||
[string]$SinkFunction = 'StandardLoad'
|
||||
)
|
||||
|
||||
[ordered]@{
|
||||
Id = [guid]::NewGuid().ToString()
|
||||
Name = $Name
|
||||
Channel = $Channel
|
||||
Direction = 'Sink'
|
||||
OutputAction = $OutputAction
|
||||
Protocol = $Protocol
|
||||
Mode = 'ConstantCurrent'
|
||||
PdoType = 'Fpdo'
|
||||
SinkFunction = $SinkFunction
|
||||
Gear = $Gear
|
||||
CcSelection = if ($CcSelection -ge 0) { $CcSelection } elseif ($Channel -eq 2) { 1 } else { 0 }
|
||||
MinVoltageMv = 3300
|
||||
VoltageMv = $VoltageMv
|
||||
CurrentMa = $ProtocolCurrentMa
|
||||
LoadVoltageMv = $VoltageMv
|
||||
LoadCurrentMa = $LoadCurrentMa
|
||||
VonVoltageMv = 100
|
||||
ShortHoldTimeMs = 1000
|
||||
HoldAfterTest = $false
|
||||
OcpStartCurrentMa = 1000
|
||||
OcpEndCurrentMa = 5000
|
||||
OcpStepCurrentMa = 100
|
||||
OcpStepTimeMs = 10
|
||||
OcpRecoveryTimeMs = 1000
|
||||
OcpStopVoltageMv = 4000
|
||||
OcpRecoveryWithLoad = $true
|
||||
DynamicCurrent1Ma = 1000
|
||||
DynamicTime1 = 100
|
||||
DynamicCurrent2Ma = 5000
|
||||
DynamicTime2 = 100
|
||||
DynamicRiseSlope = 1
|
||||
DynamicFallSlope = 1
|
||||
ApplyDelayMs = 500
|
||||
QueryDelayMs = $QueryDelayMs
|
||||
DurationMs = 1000
|
||||
StopOnFault = $true
|
||||
Criteria = New-Criteria $VoltageToleranceMv $CurrentToleranceMa
|
||||
Status = 'Pending'
|
||||
Result = ''
|
||||
Verdict = ''
|
||||
MeasuredVoltageMv = $null
|
||||
MeasuredCurrentMa = $null
|
||||
QueryTime = $null
|
||||
Measurements = @()
|
||||
}
|
||||
}
|
||||
|
||||
function New-PortConfig {
|
||||
param(
|
||||
[string]$Port,
|
||||
[int]$Channel,
|
||||
[string]$Protocol,
|
||||
[int]$VoltageMv,
|
||||
[int]$ProtocolCurrentMa,
|
||||
[int]$LoadCurrentMa,
|
||||
[int]$VoltageToleranceMv,
|
||||
[int]$CurrentToleranceMa,
|
||||
[int]$Gear = 0
|
||||
)
|
||||
[pscustomobject]@{
|
||||
Port = $Port
|
||||
Channel = $Channel
|
||||
Protocol = $Protocol
|
||||
VoltageMv = $VoltageMv
|
||||
ProtocolCurrentMa = $ProtocolCurrentMa
|
||||
LoadCurrentMa = $LoadCurrentMa
|
||||
VoltageToleranceMv = $VoltageToleranceMv
|
||||
CurrentToleranceMa = $CurrentToleranceMa
|
||||
Gear = $Gear
|
||||
}
|
||||
}
|
||||
|
||||
function Add-SingleTest {
|
||||
param(
|
||||
[System.Collections.Generic.List[object]]$Items,
|
||||
[string]$Prefix,
|
||||
[pscustomobject]$Config,
|
||||
[int]$CcSelection = -1
|
||||
)
|
||||
$voltage = $Config.VoltageMv / 1000
|
||||
$current = $Config.LoadCurrentMa / 1000
|
||||
$Items.Add((New-DmpItem "$Prefix-$($Config.Port)-$voltage`V-$current`A" $Config.Channel $Config.Protocol `
|
||||
$Config.VoltageMv $Config.ProtocolCurrentMa $Config.LoadCurrentMa `
|
||||
$Config.VoltageToleranceMv $Config.CurrentToleranceMa 10000 'Start' $Config.Gear $CcSelection))
|
||||
$Items.Add((New-DmpItem "$Prefix-$($Config.Port)-停止" $Config.Channel $Config.Protocol `
|
||||
$Config.VoltageMv $Config.ProtocolCurrentMa $Config.LoadCurrentMa 0 0 1000 'Stop' $Config.Gear $CcSelection))
|
||||
}
|
||||
|
||||
function Add-SequencedPortTest {
|
||||
param(
|
||||
[System.Collections.Generic.List[object]]$Items,
|
||||
[string]$Face,
|
||||
[int]$CcSelection,
|
||||
[pscustomobject]$Case,
|
||||
[string]$Port,
|
||||
[int]$Channel
|
||||
)
|
||||
|
||||
$sinkFunction = if ($Case.SinkFunction) { $Case.SinkFunction } else { 'StandardLoad' }
|
||||
$namePrefix = "$Face-$($Case.Label)-$Port"
|
||||
$start = New-DmpItem "$namePrefix-启动" $Channel $Case.Protocol $Case.Voltage `
|
||||
$Case.ProtocolCurrent $Case.LoadCurrent $Case.VTol $Case.ITol 5000 'Start' 0 $CcSelection $sinkFunction
|
||||
if ($sinkFunction -eq 'ShortCircuit') {
|
||||
$start.Criteria.ShortVoltageMinMv = 0
|
||||
$start.Criteria.ShortVoltageMaxMv = 3000
|
||||
$start.Criteria.ShortCurrentMinMa = 0
|
||||
$start.Criteria.ShortCurrentMaxMa = 65535
|
||||
}
|
||||
$Items.Add($start)
|
||||
$Items.Add((New-DmpItem "$namePrefix-停止" $Channel $Case.Protocol $Case.Voltage `
|
||||
$Case.ProtocolCurrent $Case.LoadCurrent 0 0 5000 'Stop' 0 $CcSelection $sinkFunction))
|
||||
}
|
||||
|
||||
function Add-CombinationTest {
|
||||
param(
|
||||
[System.Collections.Generic.List[object]]$Items,
|
||||
[string]$Prefix,
|
||||
[object[]]$Configs
|
||||
)
|
||||
|
||||
foreach ($config in $Configs) {
|
||||
$Items.Add((New-DmpItem "$Prefix-$($config.Port)-配置" $config.Channel $config.Protocol `
|
||||
$config.VoltageMv $config.ProtocolCurrentMa $config.LoadCurrentMa 0 0 100 'Start' $config.Gear))
|
||||
}
|
||||
for ($index = 0; $index -lt $Configs.Count; $index++) {
|
||||
$config = $Configs[$index]
|
||||
$delay = if ($index -eq 0) { 10000 } else { 1000 }
|
||||
$Items.Add((New-DmpItem "$Prefix-$($config.Port)-验证" $config.Channel $config.Protocol `
|
||||
$config.VoltageMv $config.ProtocolCurrentMa $config.LoadCurrentMa `
|
||||
$config.VoltageToleranceMv $config.CurrentToleranceMa $delay 'Start' $config.Gear))
|
||||
}
|
||||
foreach ($config in $Configs) {
|
||||
$Items.Add((New-DmpItem "$Prefix-$($config.Port)-停止" $config.Channel $config.Protocol `
|
||||
$config.VoltageMv $config.ProtocolCurrentMa $config.LoadCurrentMa 0 0 1000 'Stop' $config.Gear))
|
||||
}
|
||||
}
|
||||
|
||||
function Write-Plan {
|
||||
param([string]$FileName, [string]$Name, [System.Collections.Generic.List[object]]$Items)
|
||||
$plan = [ordered]@{
|
||||
ProductId = 'DMP'
|
||||
Name = $Name
|
||||
Communication = [ordered]@{
|
||||
PortName = 'COM6'
|
||||
BaudRate = 115200
|
||||
DataBits = 8
|
||||
Parity = 'None'
|
||||
StopBits = 1
|
||||
SlaveAddress = 1
|
||||
TimeoutMs = 500
|
||||
RetryCount = 2
|
||||
}
|
||||
Items = $Items
|
||||
}
|
||||
$path = Join-Path $OutputDirectory $FileName
|
||||
$json = $plan | ConvertTo-Json -Depth 20
|
||||
[System.IO.File]::WriteAllText($path, $json, [System.Text.UTF8Encoding]::new($false))
|
||||
Get-Item -LiteralPath $path
|
||||
}
|
||||
|
||||
$c1 = 1
|
||||
$c2 = 2
|
||||
$a1 = 3
|
||||
|
||||
# 1. C1/C2同时插入,但依次对单个通道带载。先测A面(CC1),再测B面(CC2)。
|
||||
$items = [System.Collections.Generic.List[object]]::new()
|
||||
$dualCases = @(
|
||||
[pscustomobject]@{ Label = '5V3A'; Protocol = 'Standard'; Voltage = 5000; ProtocolCurrent = 3000; LoadCurrent = 3000; VTol = 240; ITol = 300; SinkFunction = 'StandardLoad' },
|
||||
[pscustomobject]@{ Label = '5V3.8A过载'; Protocol = 'Standard'; Voltage = 5000; ProtocolCurrent = 3000; LoadCurrent = 3800; VTol = 0; ITol = 0; SinkFunction = 'StandardLoad' },
|
||||
[pscustomobject]@{ Label = '5V0A空载'; Protocol = 'Standard'; Voltage = 5000; ProtocolCurrent = 3000; LoadCurrent = 0; VTol = 240; ITol = 0; SinkFunction = 'StandardLoad' },
|
||||
[pscustomobject]@{ Label = '5V-QC2.0'; Protocol = 'Qc20'; Voltage = 5000; ProtocolCurrent = 3000; LoadCurrent = 0; VTol = 240; ITol = 0; SinkFunction = 'StandardLoad' },
|
||||
[pscustomobject]@{ Label = '5V短路'; Protocol = 'Standard'; Voltage = 5000; ProtocolCurrent = 3000; LoadCurrent = 0; VTol = 0; ITol = 0; SinkFunction = 'ShortCircuit' },
|
||||
[pscustomobject]@{ Label = '5V0A短路恢复'; Protocol = 'Standard'; Voltage = 5000; ProtocolCurrent = 3000; LoadCurrent = 0; VTol = 240; ITol = 0; SinkFunction = 'StandardLoad' },
|
||||
[pscustomobject]@{ Label = '9V3A'; Protocol = 'Pdo'; Voltage = 9000; ProtocolCurrent = 3000; LoadCurrent = 3000; VTol = 440; ITol = 300; SinkFunction = 'StandardLoad' },
|
||||
[pscustomobject]@{ Label = '15V3A'; Protocol = 'Pdo'; Voltage = 15000; ProtocolCurrent = 3000; LoadCurrent = 3000; VTol = 740; ITol = 300; SinkFunction = 'StandardLoad' },
|
||||
[pscustomobject]@{ Label = '20V2.25A'; Protocol = 'Pdo'; Voltage = 20000; ProtocolCurrent = 2250; LoadCurrent = 2250; VTol = 790; ITol = 225; SinkFunction = 'StandardLoad' },
|
||||
[pscustomobject]@{ Label = '20V0A空载'; Protocol = 'Pdo'; Voltage = 20000; ProtocolCurrent = 2250; LoadCurrent = 0; VTol = 790; ITol = 0; SinkFunction = 'StandardLoad' },
|
||||
[pscustomobject]@{ Label = '20V2.82A过载'; Protocol = 'Pdo'; Voltage = 20000; ProtocolCurrent = 2250; LoadCurrent = 2820; VTol = 0; ITol = 0; SinkFunction = 'StandardLoad' }
|
||||
)
|
||||
foreach ($face in @(
|
||||
[pscustomobject]@{ Name = 'A面'; CcSelection = 1 },
|
||||
[pscustomobject]@{ Name = 'B面'; CcSelection = 2 }
|
||||
)) {
|
||||
foreach ($case in $dualCases) {
|
||||
Add-SequencedPortTest $items $face.Name $face.CcSelection $case 'C1' $c1
|
||||
Add-SequencedPortTest $items $face.Name $face.CcSelection $case 'C2' $c2
|
||||
}
|
||||
}
|
||||
Write-Plan '01_C1-C2双口同时插入测试.json' '01 C1/C2双口同时插入、依次单口负载测试' $items
|
||||
|
||||
# 2. A1单口:5V标准,9V/12V使用QC2.0。
|
||||
$items = [System.Collections.Generic.List[object]]::new()
|
||||
$a1Cases = @(
|
||||
[pscustomobject]@{ Label = '264VAC'; Protocol = 'Standard'; Voltage = 5000; Current = 3000; VTol = 240; ITol = 300 },
|
||||
[pscustomobject]@{ Label = '264VAC'; Protocol = 'Qc20'; Voltage = 9000; Current = 2000; VTol = 440; ITol = 200 },
|
||||
[pscustomobject]@{ Label = '264VAC'; Protocol = 'Qc20'; Voltage = 12000; Current = 1500; VTol = 590; ITol = 150 },
|
||||
[pscustomobject]@{ Label = '90VAC'; Protocol = 'Standard'; Voltage = 5000; Current = 3000; VTol = 240; ITol = 300 },
|
||||
[pscustomobject]@{ Label = '90VAC'; Protocol = 'Qc20'; Voltage = 12000; Current = 1500; VTol = 590; ITol = 150 }
|
||||
)
|
||||
foreach ($case in $a1Cases) {
|
||||
Add-SingleTest $items $case.Label (New-PortConfig 'A1' $a1 $case.Protocol $case.Voltage `
|
||||
$case.Current $case.Current $case.VTol $case.ITol)
|
||||
}
|
||||
Add-SingleTest $items 'SCP-10V2.25A' (New-PortConfig 'A1' $a1 'Scp' 10000 2250 2250 490 225)
|
||||
Write-Plan '02_A1单口测试.json' '02 A1单口测试' $items
|
||||
|
||||
# 3. C1/C2单口多协议。先测A面(CC1),再测B面(CC2)。
|
||||
# PPS3-5没有规格值,仅做9V空载握手,避免未确认的大电流带载。
|
||||
$items = [System.Collections.Generic.List[object]]::new()
|
||||
$multiProtocolCases = @(
|
||||
[pscustomobject]@{ Label = '标准5V3A'; Protocol = 'Standard'; Gear = 0; Voltage = 5000; ProtocolCurrent = 3000; LoadCurrent = 3000; VTol = 240; ITol = 300 },
|
||||
[pscustomobject]@{ Label = 'PDO9V3A'; Protocol = 'Pdo'; Gear = 0; Voltage = 9000; ProtocolCurrent = 3000; LoadCurrent = 3000; VTol = 440; ITol = 300 },
|
||||
[pscustomobject]@{ Label = 'PDO15V3A'; Protocol = 'Pdo'; Gear = 0; Voltage = 15000; ProtocolCurrent = 3000; LoadCurrent = 3000; VTol = 740; ITol = 300 },
|
||||
[pscustomobject]@{ Label = 'PDO20V2.25A'; Protocol = 'Pdo'; Gear = 0; Voltage = 20000; ProtocolCurrent = 2250; LoadCurrent = 2250; VTol = 790; ITol = 225 },
|
||||
[pscustomobject]@{ Label = 'PPS1-9V4.5A'; Protocol = 'Pps'; Gear = 1; Voltage = 9000; ProtocolCurrent = 4500; LoadCurrent = 4500; VTol = 450; ITol = 225 },
|
||||
[pscustomobject]@{ Label = 'PPS2-19V2A'; Protocol = 'Pps'; Gear = 2; Voltage = 19000; ProtocolCurrent = 2000; LoadCurrent = 2000; VTol = 950; ITol = 150 },
|
||||
[pscustomobject]@{ Label = 'PPS3-9V空载握手'; Protocol = 'Pps'; Gear = 3; Voltage = 9000; ProtocolCurrent = 1000; LoadCurrent = 0; VTol = 450; ITol = 100 },
|
||||
[pscustomobject]@{ Label = 'PPS4-9V空载握手'; Protocol = 'Pps'; Gear = 4; Voltage = 9000; ProtocolCurrent = 1000; LoadCurrent = 0; VTol = 450; ITol = 100 },
|
||||
[pscustomobject]@{ Label = 'PPS5-9V空载握手'; Protocol = 'Pps'; Gear = 5; Voltage = 9000; ProtocolCurrent = 1000; LoadCurrent = 0; VTol = 450; ITol = 100 }
|
||||
)
|
||||
$avsCases = @(
|
||||
[pscustomobject]@{ Label = 'AVS-9V3A'; Protocol = 'Avs'; Gear = 0; Voltage = 9000; ProtocolCurrent = 3000; LoadCurrent = 3000; VTol = 150; ITol = 300 },
|
||||
[pscustomobject]@{ Label = 'AVS-20V2.25A'; Protocol = 'Avs'; Gear = 0; Voltage = 20000; ProtocolCurrent = 2250; LoadCurrent = 2250; VTol = 650; ITol = 225 }
|
||||
)
|
||||
$cPorts = @([pscustomobject]@{ Name = 'C1'; Channel = $c1 }, [pscustomobject]@{ Name = 'C2'; Channel = $c2 })
|
||||
foreach ($face in @(
|
||||
[pscustomobject]@{ Name = 'A面'; CcSelection = 1 },
|
||||
[pscustomobject]@{ Name = 'B面'; CcSelection = 2 }
|
||||
)) {
|
||||
foreach ($case in $multiProtocolCases) {
|
||||
foreach ($port in $cPorts) {
|
||||
Add-SingleTest $items "$($face.Name)-$($case.Label)" (New-PortConfig $port.Name $port.Channel $case.Protocol `
|
||||
$case.Voltage $case.ProtocolCurrent $case.LoadCurrent $case.VTol $case.ITol $case.Gear) $face.CcSelection
|
||||
}
|
||||
}
|
||||
foreach ($case in $avsCases) {
|
||||
Add-SingleTest $items "$($face.Name)-$($case.Label)" (New-PortConfig 'C1' $c1 $case.Protocol `
|
||||
$case.Voltage $case.ProtocolCurrent $case.LoadCurrent $case.VTol $case.ITol $case.Gear) $face.CcSelection
|
||||
}
|
||||
}
|
||||
Write-Plan '03_C1-C2单口多协议测试.json' '03 C1/C2单口多协议A/B面测试(含PPS1~5、AVS)' $items
|
||||
|
||||
# 4. 两口组合:只有20V项目使用PDO,其余5V均为标准协议。
|
||||
$items = [System.Collections.Generic.List[object]]::new()
|
||||
Add-CombinationTest $items '组合1-C1+C2' @(
|
||||
(New-PortConfig 'C1' $c1 'Pdo' 20000 1500 1500 990 150),
|
||||
(New-PortConfig 'C2' $c2 'Standard' 5000 3000 3000 240 300)
|
||||
)
|
||||
Add-CombinationTest $items '组合2-C1+A1' @(
|
||||
(New-PortConfig 'C1' $c1 'Pdo' 20000 1500 1500 990 150),
|
||||
(New-PortConfig 'A1' $a1 'Standard' 5000 3000 3000 240 300)
|
||||
)
|
||||
Add-CombinationTest $items '组合3-C2+A1' @(
|
||||
(New-PortConfig 'C2' $c2 'Standard' 5000 1500 1500 240 150),
|
||||
(New-PortConfig 'A1' $a1 'Standard' 5000 1500 1500 240 150)
|
||||
)
|
||||
Write-Plan '04_两口组合输出测试.json' '04 两口组合输出测试' $items
|
||||
|
||||
# 5. 三口组合:C1为PD 20V,C2/A1为标准5V。
|
||||
$items = [System.Collections.Generic.List[object]]::new()
|
||||
Add-CombinationTest $items '三口组合-C1+C2+A1' @(
|
||||
(New-PortConfig 'C1' $c1 'Pdo' 20000 1500 1500 990 150),
|
||||
(New-PortConfig 'C2' $c2 'Standard' 5000 1500 1500 240 150),
|
||||
(New-PortConfig 'A1' $a1 'Standard' 5000 1500 1500 240 150)
|
||||
)
|
||||
Write-Plan '05_C1-C2-A1三口组合输出测试.json' '05 C1/C2/A1三口组合输出测试' $items
|
||||
@@ -0,0 +1,190 @@
|
||||
#ifndef __DigtalPower_ModbusRTU_REG_List_H__
|
||||
#define __DigtalPower_ModbusRTU_REG_List_H__
|
||||
|
||||
#include "USART1_Modbus_RTU.h"
|
||||
#include "dac.h"
|
||||
|
||||
#define ModbusRTU_SW_Version 0x0301; //01是电源代号,02是负载代号,03是非节能源载代号,04是节能电源代号;低字节01是版本号,V0.1
|
||||
|
||||
//ModbusRTU 从站地址//工作状态及运行参数显示
|
||||
#define ModbusRTU_Power_Status 0x00 //R,工作状态指示,00 预充电;01就绪/停止 02 缓启动;03 运行;04 故障:03 03 00 00 00 01 85 E8
|
||||
#define ModbusRTU_Relay_Status 0x01 //bit0=0 主继电器断开 bit0=1 主继电器闭合;;;bit1=0 滤波继电器断开 bit1=1 滤波继电器闭合
|
||||
#define ModbusRTU_Fault_Status 0x02 //故障状态寄存器
|
||||
#define ModbusRTU_Flash_Status 0x03 //flash存储状态
|
||||
#define ModbusRTU_Role_ModeFlag 0x04 //0x04 源载指令,默认是电子负载,1是supply,2是eload
|
||||
|
||||
//故障寄存器
|
||||
/*****************************故障类型*****************/
|
||||
#define F_NOERR 0x0000//无故障
|
||||
#define F_SW_VIN_UVP 0x0001//输入欠压
|
||||
#define F_SW_VIN_OVP 0x0002//输入过压
|
||||
#define F_SW_VOUT_UVP 0x0004//输出欠压
|
||||
#define F_SW_VOUT_OVP 0x0008//输出过压
|
||||
#define F_SW_IOUT_OCP 0x0010//输出过流
|
||||
#define F_SW_SHORT 0x0020//输出短路
|
||||
#define F_SW_OTP 0x0040//过温保护
|
||||
|
||||
//电源控制指令
|
||||
#define ModbusRTU_PowerCmd 0x05 //05 W 0x01 开机,0x02 关机,0x03故障复位;0xAA 存储数据到flash;0xBB 恢复默认参数
|
||||
#define ModbusRTU_WorkMode 0x06 //06 WR 0x01 恒压,0x02 恒流,0x03开环,04 恒功率,05恒阻
|
||||
#define ModbusRTU_Volt 0x07 //07-08 WR 设置输出电压 uint32,0.001V, 0~60V,默认5V,查询电压也是这个指令
|
||||
#define ModbusRTU_Current 0x09 //09-0A WR 设置输出电流 uint32 ,0.001A,, 0~60A,默认值1A,查询电压也是这个指令
|
||||
|
||||
#define ModbusRTU_ShortTest_VoltShort 0x0B //无论short测试成功或者失败,都给出短路恒流值的时候的电压
|
||||
#define ModbusRTU_ShortTest_CurrentShort 0x0C //无论测试成功或者失败,都给出短路恒流值的时候的电压
|
||||
#define ModbusRTU_OCPTest_VoltOCP 0x0D //无论short测试成功或者失败,都给出短路恒流值的时候的电压
|
||||
#define ModbusRTU_OCPTest_CurrentOCP 0x0E //无论测试成功或者失败,都给出短路恒流值的时候的电压
|
||||
|
||||
#define ModbusRTU_DUT_Vpkp 0x0F //量测正峰值
|
||||
#define ModbusRTU_DUT_Vpkn 0x10 //量测负峰值
|
||||
#define ModbusRTU_DUT_Vpp 0x11 //量测峰峰值
|
||||
//纹波寄存器
|
||||
#define ModbusRTU_Ripple_Value 0x12 //读取纹波
|
||||
|
||||
#define ModbusRTU_Temp 0x1A //WR 11,当前内部温度读取点
|
||||
#define ModbusADDR_SW_Version 0x1B //10,12地址,读取版本号,03代表buckboost半桥,01是版本号
|
||||
#define ModbusADDR_SlaveID_Modify 0x1C //11,13地址,修订SlaveID
|
||||
|
||||
|
||||
#define Line_Compensation 0X1D //1F 14d地址,线损补偿,正负5V,1mv,精度0.001,放大1000倍,5000
|
||||
|
||||
#define Eload_Start_VON 0x20 //10 16寄存器存储电子负载启动电压,负载检测到电压值为启动电压,才开启电子负载;
|
||||
#define Eload_Stop_Volt 0x21 //11 17寄存器存储电子负载关闭电压;
|
||||
#define Eload_Slew_Rate 0x22 //12 18寄存器存储电子负载上升斜率参数;
|
||||
|
||||
#define ModbusRTU_CPower 0x24 //36-37 功率值
|
||||
#define ModbusRTU_CResistor 0x26 //38 电阻值
|
||||
|
||||
//6.3.1电源控制参数
|
||||
#define ModbusRTU_VoltLimit 0x28 //0x29 40-41 0x2A 42寄存器输出电压限值,默认是6.0V,可以微调到6.5V;
|
||||
#define ModbusRTU_CurrentLimit_H 0x2A //42~43WR 输出电流限值
|
||||
#define ModbusRTU_CurrentLimit_L 0x2B //42~43WR 输出电流限值
|
||||
|
||||
#define ModbusRTU_Volt_CAL_K 0x2C //2C~2D 电压校准K值,被放大Q16倍,再移动16回去;使用两个字节
|
||||
#define ModbusRTU_Volt_CAL_K_L 0x2D
|
||||
#define ModbusRTU_Volt_CAL_B 0x2E //2E 电压校准B值
|
||||
#define ModbusRTU_Current_CAL_K 0x2F //2F-30 电流校准K值
|
||||
#define ModbusRTU_Current_CAL_K_L 0x30
|
||||
|
||||
#define ModbusRTU_Current_CAL_B 0x31 //31 电流校准B值
|
||||
|
||||
#define ModbusRTU_SourceCurrent_CAL_K 0x32 //32-33 电流校准K值
|
||||
#define ModbusRTU_SourceCurrent_CAL_K_L 0x33
|
||||
|
||||
#define ModbusRTU_SourceCurrent_CAL_B 0x34 //34 电流校准B值
|
||||
|
||||
#define ModbusRTU_SourceSink_Current_Offset 0x35 //电源的电流上报offset
|
||||
//#define ModbusRTU_Sink_Current_Offset 0x33 //负载的电流上报offset
|
||||
|
||||
#define ModbusRTU_CALI_CRC 0x36 //校准偏移6参数的校验值;使用CRC16-Modbus校验;
|
||||
|
||||
|
||||
#define ModbusRTU_CAL_WriteEnable 0x37 //使能写入FLASH;下次调用使用这个参数;是个魔数:0x4361 (C+a)
|
||||
#define ModbusRTU_CAL_WriteRecovery 0x38 //使能写入出厂数据区域;0x5763
|
||||
#define ModbusRTU_CAL_ReadRecovery 0x39 //使能读出;将出厂数据读到当前的bank中,并更新6个参数
|
||||
|
||||
//short测试
|
||||
#define ModbusRTU_ShortTest_CMD_MODE_FLAG 0x40 //16位;0x0101; 01启动,低字节的01,保持电流,为0是释放电流; 20260601新增一个低字节的bit7=0用于是恢复以前的状态,bit7=1是将卸载电流归零;
|
||||
#define ModbusRTU_ShortTest_Hold_Time 0x41 //单位是ms,最大65535ms,给0是立即释放,给一个时间值,是保持这个时间不变;
|
||||
//#define ModbusRTU_ShortTest_CurrentShort 0x42 //无论测试成功或者失败,都给出短路恒流值的时候的电压
|
||||
|
||||
//OCP测试
|
||||
#define ModbusRTU_OCPTest_CMD_MODE_FLAG 0x43 //16位;0x0101; 01启动,低字节的01,保持电流,为0是释放电流; 20260601新增一个低字节的bit7=0用于是恢复以前的状态,bit7=1是将卸载电流归零;
|
||||
#define ModbusRTU_OCPTest_StartCurrent 0x44 //起始电流
|
||||
#define ModbusRTU_OCPTest_StopCurrent 0x45 //终止电流
|
||||
#define ModbusRTU_OCPTest_StepCurrent 0x46 //每一步的电流
|
||||
#define ModbusRTU_OCPTest_Step_Hold_Time 0x47 //每一步的保持时间;默认10ms;范围1ms到100ms;
|
||||
#define ModbusRTU_OCPTest_Vtrig_Stop 0x48 //达到触发OCP流点的电压值;
|
||||
#define ModbusRTU_OCPTest_Hold_Time 0x49
|
||||
//#define ModbusRTU_OCPTest_VoltOCP 0x49 //无论short测试成功或者失败,都给出短路恒流值的时候的电压
|
||||
//#define ModbusRTU_OCPTest_CurrentOCP 0x4A //无论测试成功或者失败,都给出短路恒流值的时候的电压
|
||||
|
||||
//DYNA 电子负载的动态测试模式,也叫动态负载或瞬态测试。在该模式下,负载会按设定的斜率、频率和占空比,在两个电流值(如高负载和低负载)之间周期性跳变,用来测试电源的瞬态响应、恢复时间等特性。
|
||||
#define ModbusRTU_DYNA_CMD_MODE_FLAG 0x4B //动态测试 CMD启动、退出、 以及模式:Continuous、PULSE、Toggle;LSB8 BIT7 短路测试时候的电流:保持/归零;bit1 过流; bit0 成功/失败
|
||||
#define ModbusRTU_DYNA_L1 0x4C //动态测试电流1
|
||||
#define ModbusRTU_DYNA_L2 0x4D //动态测试电流2
|
||||
#define ModbusRTU_DYNA_T1 0x4E //动态测试电流1的时间
|
||||
#define ModbusRTU_DYNA_T2 0x4F //动态测试电流2的时间
|
||||
#define ModbusRTU_DYNA_Rise_Slew_Rate 0x50 //动态测试上升斜率
|
||||
#define ModbusRTU_DYNA_Fall_Slew_Rate 0x51 //动态测试下降斜率
|
||||
|
||||
|
||||
#define ModbusRTU_DUT_ValueReset 0x5D //复位数值
|
||||
|
||||
#define ModbusRTU_SYS_Reset 0x61 //系统复位指令,如果异常过压,通常发指令,让系统复位
|
||||
|
||||
//#define ModbusRTU_Volt_Kp 0x30 //48-49 RW 电压环kp
|
||||
//#define ModbusRTU_Volt_Ki 0x32 //50-51WR 电压环ki
|
||||
//#define ModbusRTU_Curr_Kp 0x34 //52-53WR 电流环kp
|
||||
//#define ModbusRTU_Curr_Ki 0x36 //54-55WR 电流环ki
|
||||
|
||||
//#define ModbusRTU_CP_Kp 0x38 //56-57 RW 功率环kp
|
||||
//#define ModbusRTU_CP_Ki 0x3A //58-59 WR 功率环ki
|
||||
//#define ModbusRTU_CR_Kp 0x3C //60-61 WR 电阻环kp
|
||||
//#define ModbusRTU_CR_Ki 0x3E //62-63 WR 电阻环ki
|
||||
|
||||
//112,0x70寄存器,改为当前内部温度读取点;
|
||||
|
||||
#define ModbusRTU_TempLimit 0x71 //WR 温度限值
|
||||
#define ModbusRTU_FANSpeed 0x72 //风速控制,上位机可以设定;自动模式下,温度高于一个值,最大风速跑,低于则最小风速跑
|
||||
|
||||
#define SMU_Relay_ON 0x0001 //源载主继电器
|
||||
#define SMU_EL_PB15_EMI_Bypass_ON 0x0002 //旁路滤波继电器
|
||||
//定义电流保护值的关系:Y(VDAC) = K*X(I-real)+B
|
||||
#define Init_OCP_VALUE 12000 //12A
|
||||
//正向:
|
||||
#define K_COEFF_FWD_Q16 (9960)
|
||||
#define B_Intercept_FWD (1846)
|
||||
//反向:
|
||||
#define K_COEFF_REV_Q16 (-9960)
|
||||
#define B_Intercept_REV (1846)
|
||||
|
||||
//结构体
|
||||
//6.2.1工作状态及运行参数显示 PowerStatusAndParaShow
|
||||
typedef struct {
|
||||
uint16_t Power_Status;
|
||||
uint16_t Relay_Status;
|
||||
uint16_t Fault_Status;
|
||||
uint16_t Flash_Status;
|
||||
uint32_t InputVolt;
|
||||
uint32_t InputCurr;
|
||||
uint32_t OutputVolt;
|
||||
uint32_t OutputCurr;
|
||||
uint32_t OutputPower;
|
||||
uint16_t statusRsv1; //预留位
|
||||
uint16_t statusRsv2;
|
||||
}S_PowerStatusAndParaShow;
|
||||
|
||||
extern S_PowerStatusAndParaShow PowerStatusAndParaShow;
|
||||
|
||||
//6.2.2电源控制指令PowerControlCmd
|
||||
typedef struct{
|
||||
uint16_t PowerCmd;
|
||||
uint16_t WorkMode;
|
||||
uint32_t Vout;
|
||||
uint32_t Iout;
|
||||
uint8_t Remote_Power_ON_Flag; //开关机指示
|
||||
uint8_t Remote_Power_Reset_Flag; //复位指示
|
||||
}S_PowerControlCmd;
|
||||
|
||||
extern S_PowerControlCmd PowerControlCmd;
|
||||
|
||||
|
||||
//6.3.1电源控制参数
|
||||
typedef struct{
|
||||
uint32_t VoutLimit;
|
||||
uint32_t IoutLimit;
|
||||
uint16_t DutyLimit;
|
||||
uint16_t FrequnceLimit;
|
||||
float VoltKp;
|
||||
float VoltKi;
|
||||
float CurrKp;
|
||||
float CurrKi;
|
||||
}S_PowerControlPara;
|
||||
|
||||
extern uint8_t Power_OnOff_Flag,Power_OnOff_Flag;
|
||||
|
||||
extern S_PowerControlPara PowerControlPara;
|
||||
//Modbus 参数初始化
|
||||
extern void Modbus_Para_Init(void);
|
||||
#endif
|
||||
+238
@@ -0,0 +1,238 @@
|
||||
# 修改日志
|
||||
|
||||
## V1.1.9 - 2026-08-25
|
||||
|
||||
### Source 复位后的初始化流程
|
||||
- 从其他协议切换到 PD 时复位加入断开CC,D+D-,GND逻辑,等断开后再复位,再初始化
|
||||
- 增加 PD 切换到非 PD 协议时的完整复位;PD/非PD跨类别切换统一执行复位。
|
||||
- PD切PD、非PD切非PD以及仅切换CC线时不复位。
|
||||
- 新增 `SOURCE_WORK_INIT_WAIT`,复位回码后重新执行 Source 初始化,并等待南向初始化批次完成。
|
||||
- 加入了读取版本号
|
||||
|
||||
## V1.1.8 - 2026-08-24
|
||||
|
||||
### 修改主题
|
||||
修复了source部分的PD协议长时间运行后会出不来的问题
|
||||
对应芯海3221/source版本V_1.07
|
||||
|
||||
### Source协议复位切换
|
||||
- 新增`SOURCE_RESET`命令:发送`06 00 02 18 00 0E`,校验回码`05 00 02 18 16`。
|
||||
- 首次发送协议不复位;PD与非PD跨类别切换时先复位。
|
||||
- PD切PD、非PD切非PD以及仅切换CC线时不复位。
|
||||
- 删除`CC_CLOSE`状态及其共享等待屏障。
|
||||
- 协议设置回码有效后更新`last_pd_pro`,避免协议尚未生效时错误判断。
|
||||
|
||||
### 验证记录
|
||||
- 使用1-2,3-4测试自举例程测试俩百次正常
|
||||
- git diff --check`:通过。
|
||||
- 旧`CC_CLOSE`状态、宏和调用引用:已检查清理。
|
||||
- Keil编译:按当前要求未执行,待现场烧录后验证复位回码和协议切换时序。
|
||||
|
||||
## V1.1.7 - 2026-08-08
|
||||
|
||||
### 修改主题
|
||||
|
||||
并行执行Sink完整握手中的南向低电流确认与北向协议/CC设置。
|
||||
|
||||
### 主要修改
|
||||
|
||||
- 南向安全批次完成并收到辅助继电器回码、建立量测基线后,立即允许北向设置协议和CC线。
|
||||
- 南向实际电流连续两次不大于 `100mA` 的确认过程与北向协议/CC设置并行执行。
|
||||
- 北向进入 `GET_SINK_VC` 后,只有低电流确认完成且CC后的 `200ms` 查询保护时间到期,才发送第一条 `0x20`。
|
||||
- 电压稳定后再发送 `ALL_REL_ON -> 目标电流 -> WORK_START`,防止协议协商期间提前带载。
|
||||
|
||||
### 涉及文件
|
||||
|
||||
- `apps/chrg/applications/thread/chrg_roll_nor.c`
|
||||
- `apps/chrg/applications/utils/chrg_sink.c`
|
||||
- `apps/chrg/applications/utils/chrg_sink.h`
|
||||
|
||||
### 编译验证
|
||||
|
||||
- Keil MDK 编译结果:`0 Error(s), 0 Warning(s)`。
|
||||
|
||||
## V1.1.5 - 2026-08-08
|
||||
|
||||
### 修改主题
|
||||
|
||||
协议电压和协议电流变化统一采用软卸载重发协议流程。
|
||||
|
||||
### 主要修改
|
||||
|
||||
- 协议类型、CC线和协议组号变化仍进入完整握手并切换南向继电器。
|
||||
- 协议电压、协议电流单独变化或同时变化时,只发送 `WORK_STOP`,不关闭南向继电器。
|
||||
- 软卸载不再额外发送 `CURRENT=0`,仅通过实际电流连续两次不大于 `100mA`确认电子负载已停止。
|
||||
- 协议重新生效且电压稳定后,由RUNNING先写入实际负载电流,再发送 `WORK_START`。
|
||||
|
||||
### 涉及文件
|
||||
|
||||
- `apps/chrg/applications/thread/chrg_comm.c`
|
||||
- `apps/chrg/applications/utils/chrg_sink.c`
|
||||
|
||||
### 编译验证
|
||||
|
||||
- Keil MDK 编译结果:`0 Error(s), 0 Warning(s)`。
|
||||
|
||||
## V1.1.4 - 2026-08-07
|
||||
|
||||
### 修改主题
|
||||
|
||||
调整负载低电流启动时的继电器和工作命令顺序。
|
||||
|
||||
### 主要修改
|
||||
|
||||
- 设定电流为 `0A` 或低于 `100mA` 时,协议握手仍正常执行。
|
||||
- 电压达到目标后发送 `ALL_REL_ON`,确保主继电器打开。
|
||||
- 主继电器打开后继续发送 `WORK_STOP` 和 `CURRENT=0`,保持电子负载不带载。
|
||||
- 已经处于运行状态切换到低电流时,沿用原有停止流程,不重复切换继电器。
|
||||
|
||||
### 涉及文件
|
||||
|
||||
- `apps/chrg/applications/utils/chrg_sink.c`
|
||||
|
||||
### 编译验证
|
||||
|
||||
- Keil MDK 编译结果:`0 Error(s), 0 Warning(s)`。
|
||||
|
||||
## V1.1.3 - 2026-08-07
|
||||
|
||||
### 修改主题
|
||||
|
||||
并行执行Sink南向初始化与北向握手,并优化握手查询和RUNING继电器时序。
|
||||
|
||||
### 主要修改
|
||||
|
||||
- `INIT`将 `FU_REL_ON -> CURRENT=0 -> MODE -> VON` 作为一个有序南向批次提交。
|
||||
- 南向初始化批次成功入队后立即打开北向Sink继电器、设置 `enable=1` 并开始协议握手。
|
||||
- `SINK_WORK_INIT_AUX_WAIT`改为后台监控南向初始化,不再阻塞北向协议、CC和电压查询。
|
||||
- 南向初始化失败重试时保留当前北向 `sub`,不重复拉回协议设置起点。
|
||||
- 协议或CC有效回码后,首条 `0x20` 等待 `200ms`;电压未稳定时后续每 `100ms` 查询一次。
|
||||
- 一帧通过CRC、ID、命令和配置版本校验的电压达到目标后立即进入 `RUNING`,不再等待第二帧。
|
||||
- 进入稳定运行后立即解除查询节流,恢复北向正常轮询速度。
|
||||
- `RUNING`删除重复的 `FU_REL_ON`,调整为 `ALL_REL_ON -> 目标负载值 -> WORK_START`。
|
||||
|
||||
### 涉及文件
|
||||
|
||||
- `apps/chrg/applications/utils/chrg_sink.c`
|
||||
- `apps/chrg/applications/thread/chrg_roll_nor.c`
|
||||
- `apps/chrg/applications/thread/chrg_north.c`
|
||||
|
||||
### 编译验证
|
||||
|
||||
- Keil MDK 编译结果:`0 Error(s), 0 Warning(s)`。
|
||||
|
||||
### 硬件验证
|
||||
|
||||
- 待确认南向初始化命令与北向协议/CC设置并行执行且互不重置状态。
|
||||
- 待确认首条和后续 `0x20` 间隔分别约为 `200ms` 和 `100ms`。
|
||||
- 待确认进入 `RUNING` 时不再发送 `FU_REL_ON`,主继电器不会被重复断开。
|
||||
|
||||
## V1.1.2 - 2026-08-07
|
||||
|
||||
### 修改主题
|
||||
|
||||
降低Sink协议握手阶段的北向电压电流查询频率。
|
||||
|
||||
### 主要修改
|
||||
|
||||
- 新增 `SINK_HANDSHAKE_QUERY_INTERVAL_MS`,设置为 `200ms`。
|
||||
- Sink协议或CC设置收到有效回码后,不立即发送或连续快速发送 `0x20` 查询。
|
||||
- CC路径的 `200ms` 从有效 `0x17` 回码时刻开始计时,包含原有 `50ms` CC稳定保护。
|
||||
- 协议握手、软恢复等待和掉电恢复监控阶段的 `0x20` 查询按每 `200ms` 一次执行。
|
||||
- 北向量测连续两次达到稳定条件后解除节流,`RUNING` 和低电流待机恢复正常查询频率。
|
||||
- 仅重发协议的 `IDX_SET_SINK_PD_ONLY` 路径同样启动 `200ms` 查询等待。
|
||||
- 设置协议和CC命令仍然按有效回码、超时和原有重试机制处理。
|
||||
|
||||
### 涉及文件
|
||||
|
||||
- `apps/chrg/applications/thread/chrg_roll_nor.c`
|
||||
|
||||
### 编译验证
|
||||
|
||||
- Keil MDK 编译结果:`0 Error(s), 0 Warning(s)`。
|
||||
|
||||
### 硬件验证
|
||||
|
||||
- 待观察协议/CC设置后 `0x20` 的发送间隔是否稳定为不小于 `200ms`。
|
||||
- 待验证电压连续两次稳定后是否恢复正常量测频率。
|
||||
|
||||
## V1.1.1 - 2026-08-07
|
||||
|
||||
### 修改主题
|
||||
|
||||
增加普通负载最低带载电流控制,低电流时保持协议在线但关闭电子负载。
|
||||
|
||||
### 主要修改
|
||||
|
||||
- 新增 `SINK_LOAD_ENABLE_MIN_MA`,恒流负载设定低于 `100mA` 时禁止发送 `WORK_START`。
|
||||
- 最低带载门限只判断南向负载电流 `loadc`,不影响北向协议电流 `pro_loadc` 和协议握手。
|
||||
- 首次启动或完整重握手后为低电流时,发送 `WORK_STOP -> CURRENT=0` 并保持主继电器关闭。
|
||||
- 运行中由有效电流降至低电流时,发送 `WORK_STOP -> CURRENT=0`,保持协议、CC和继电器不变。
|
||||
- 运行中低电流待机恢复有效电流时,只发送目标电流和 `WORK_START`,不重新握手或切换继电器。
|
||||
- 主继电器未打开的低电流待机使用独立 `SINK_WORK_LOAD_START` 恢复入口,避免被 `RUNING` 状态去重。
|
||||
- 低电流待机期间仅修改协议电压时不重复卸载,并保持原有主继电器状态语义。
|
||||
- 将 COM 端运行电流跨门限判断封装为 `chrg_comm_handle_sink_load_current()`,避免生效分支继续膨胀。
|
||||
- 北向解析将两种低电流待机状态作为稳定状态,不因实际电流为零反复进入 `RUNING`。
|
||||
- 低电流待机恢复有效电流时,`SINK_WORK_LOAD_START`/`SINK_WORK_LOAD_RESUME` 只作为待启动标记,必须等北向实际电压稳定后才下发 `WORK_START`。
|
||||
|
||||
### 涉及文件
|
||||
|
||||
- `apps/chrg/applications/utils/chrg_sink.h`
|
||||
- `apps/chrg/applications/utils/chrg_sink.c`
|
||||
- `apps/chrg/applications/thread/chrg_comm.c`
|
||||
- `apps/chrg/applications/thread/chrg_north.c`
|
||||
|
||||
### 编译验证
|
||||
|
||||
- Keil MDK 编译结果:`0 Error(s), 0 Warning(s)`。
|
||||
|
||||
### 硬件验证
|
||||
|
||||
- 待验证 `20V/3A -> 20V/0A -> 20V/3A` 的南向命令顺序和协议保持情况。
|
||||
- 待验证首次以低于 `100mA` 的电流启动时,北向握手正常且南向不执行 `WORK_START`。
|
||||
|
||||
## V1.1.0 - 2026-08-07
|
||||
|
||||
### 修改主题
|
||||
|
||||
负载启动、掉电恢复、协议重握手和协议电压软切换时序调整。
|
||||
|
||||
### 主要修改
|
||||
|
||||
- 负载启动时先向南向发送 `FU_REL_ON`,收到有效回码后才打开北向 Sink 继电器。
|
||||
- 剩余的负载初始化命令在副继电器确认后入队,北向协议握手与南向初始化并行执行。
|
||||
- `RUNING` 阶段的南向命令继续追加到同一队列,保持初始化配置、继电器、目标电流/电压和 `WORK_START` 的顺序。
|
||||
- 掉电恢复时执行 `WORK_STOP -> CURRENT=0 -> ALL_REL_OFF -> FU_REL_ON`,副继电器恢复后等待输入电压重新出现。
|
||||
- 掉电恢复检测到电压后重新设置协议和 CC,不能使用掉电前的电压样本直接进入 `RUNING`。
|
||||
- 协议类型、CC、协议组号或协议电流变化进入完整重握手,关闭主副继电器后重新打开副继电器。
|
||||
- 仅协议电压变化使用软卸载,只发送 `WORK_STOP` 和 `CURRENT=0`,不切换继电器。
|
||||
- 软卸载恢复时只发送目标电流/电压和 `WORK_START`,不再发送继电器命令。
|
||||
- 保留连续两次实际电流不大于 `100mA` 的安全确认,以及连续两次稳定电压确认。
|
||||
- 暂时保持南向主副继电器之间的固定延时为屏蔽状态。
|
||||
|
||||
### 涉及文件
|
||||
|
||||
- `apps/chrg/applications/utils/chrg_sink.h`
|
||||
- `apps/chrg/applications/utils/chrg_sink.c`
|
||||
- `apps/chrg/applications/thread/chrg_comm.c`
|
||||
- `apps/chrg/applications/thread/chrg_roll_nor.c`
|
||||
- `apps/chrg/applications/thread/chrg_north.c`
|
||||
|
||||
### 编译验证
|
||||
|
||||
- Keil MDK 编译结果:`0 Error(s), 0 Warning(s)`。
|
||||
- 尚未完成硬件验证,需重点观察南向命令顺序、北向协议握手时刻、掉电恢复和协议电压软切换。
|
||||
|
||||
### 后续记录格式
|
||||
|
||||
后续每次修改按以下格式追加:
|
||||
|
||||
```text
|
||||
## Vx.y.z - YYYY-MM-DD
|
||||
|
||||
### 修改主题
|
||||
### 主要修改
|
||||
### 涉及文件
|
||||
### 编译验证
|
||||
### 硬件验证
|
||||
```
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
静态排查后,暂未看到明确的 ABBA 型互斥锁环。当前现象更像“内存破坏/资源泄漏后线程停滞”或“状态机无限重试”,而不是整个 RTOS 调度器死锁。
|
||||
|
||||
另外,代码中使用的是 STM32 内部 IWDG,不是外部独立看门狗。
|
||||
|
||||
**可疑点**
|
||||
|
||||
1. **高风险:南北向分包接收存在确定的越界写和泄漏路径**
|
||||
|
||||
[north](D:/proj/char/chrg_v/apps/chrg/applications/thread/chrg_north.c:548) 和 [south](D:/proj/char/chrg_v/apps/chrg/applications/thread/chrg_south.c:309) 在续接分包时计算:
|
||||
|
||||
```text
|
||||
len_need = len_msg - 帧头长度
|
||||
```
|
||||
|
||||
但此时 `pFrame->length` 已经包含之前收到的数据,正确的剩余长度应基于 `len_msg - pFrame->length`。当前代码却从 `payload[pFrame->length]` 开始写入整个“帧头后的总长度”。
|
||||
|
||||
例如总长 21 字节,首批已存 8 字节,下一次仍可能从偏移 8 写入 18 字节,最终写到偏移 26,越过 21 字节堆块。这会破坏相邻堆块、邮箱消息甚至 RT-Thread 内核对象,最终表现为随机线程卡死、互斥量异常或堆分配失败。
|
||||
|
||||
同时,分包超时路径只清除了 `findhead`:
|
||||
|
||||
- [chrg_north.c:627](D:/proj/char/chrg_v/apps/chrg/applications/thread/chrg_north.c:627)
|
||||
- [chrg_south.c:399](D:/proj/char/chrg_v/apps/chrg/applications/thread/chrg_south.c:399)
|
||||
|
||||
没有释放 `pMB/payload`,也没有清除 `length/len_msg`。而且没有新数据时会提前 `continue`,超时检查根本不会执行。串口噪声、丢字节或正常分包都可能不断积累泄漏。
|
||||
|
||||
此外,payload 分配失败时只返回,没有释放刚分配的 `pMB`:
|
||||
|
||||
- [chrg_north.c:518](D:/proj/char/chrg_v/apps/chrg/applications/thread/chrg_north.c:518)
|
||||
- [chrg_south.c:280](D:/proj/char/chrg_v/apps/chrg/applications/thread/chrg_south.c:280)
|
||||
|
||||
这是目前最符合“运行时间越长越容易出现”的可疑点。
|
||||
|
||||
2. **高风险:看门狗喂法无法覆盖业务线程死锁**
|
||||
|
||||
主线程每秒无条件喂狗:[main.c:36](D:/proj/char/chrg_v/apps/chrg/applications/main.c:36)。
|
||||
|
||||
北向轮询线程又在每轮无条件喂同一只狗:[chrg_roll_nor.c:421](D:/proj/char/chrg_v/apps/chrg/applications/thread/chrg_roll_nor.c:421)。
|
||||
|
||||
因此即使 `thr.comm`、`thr.sou`、`thr.rollsou`、LCD 线程全部停止工作,只要主线程或北向轮询线程仍能调度,IWDG 就永远不会复位。这只是在检测“CPU/调度器是否完全停止”,没有检测业务线程是否健康。
|
||||
|
||||
驱动最终调用的是 `HAL_IWDG_Refresh()`:[drv_wdt.c:40](D:/proj/char/chrg_v/rt-thread/bsp/stm32/libraries/HAL_Drivers/drivers/drv_wdt.c:40)。代码中没有找到外部 WDI 引脚翻转或外部看门狗驱动。
|
||||
|
||||
3. **高风险:当前新增的南向批处理可能永久停在 `RUN_COM`**
|
||||
|
||||
南向批处理遇到 CRC 错误或应答超时后,不增加重试次数、不设置截止时间,也不清除任务:
|
||||
|
||||
- CRC 错误:[chrg_roll_sou.c:608](D:/proj/char/chrg_v/apps/chrg/applications/thread/chrg_roll_sou.c:608)
|
||||
- 应答超时:[chrg_roll_sou.c:627](D:/proj/char/chrg_v/apps/chrg/applications/thread/chrg_roll_sou.c:627)
|
||||
|
||||
线程会一直重发同一个寄存器,`pending` 永远不清除,`run` 永远保持 `RUN_COM`,正常南向轮询无法恢复。这属于业务状态机死锁,调度器仍正常运行,所以看门狗不会复位。
|
||||
|
||||
这套批处理逻辑是当前工作区相对 `HEAD` 新增的,优先级很高。
|
||||
|
||||
4. **高风险:南向共享状态的互斥保护实际无效**
|
||||
|
||||
[chrg_set_sou_reg](D:/proj/char/chrg_v/apps/chrg/applications/thread/chrg_roll_sou.c:435) 先在锁外写入:
|
||||
|
||||
```text
|
||||
pROLL->ch
|
||||
pROLL->reg
|
||||
pROLL->value
|
||||
```
|
||||
|
||||
随后互斥量只保护 `pROLL->run`。消费者也只在锁内读取 `run`,实际使用 `ch/reg/value` 时已经离开锁。
|
||||
|
||||
多个生产者包括 LCD、Modbus 和状态机可能交叉覆盖这些字段,形成“通道来自命令 A、寄存器来自命令 B、值来自命令 C”的组合。
|
||||
|
||||
批处理数组 `g_sou_com_batch` 同样由生产者和 `thr.rollsou` 同时读写,却没有共同的锁:[chrg_roll_sou.c:394](D:/proj/char/chrg_v/apps/chrg/applications/thread/chrg_roll_sou.c:394)。
|
||||
|
||||
5. **中高风险:先切换 `RUN_COM`,再填充批处理数据**
|
||||
|
||||
[chrg_sink_diff_send_reg](D:/proj/char/chrg_v/apps/chrg/applications/thread/chrg_comm.c:2338) 先调用 `chrg_sou_com_sou_set()` 将状态切到 `RUN_COM`,然后才追加寄存器。
|
||||
|
||||
`chrg_sink_work()` 也是相同顺序:[chrg_sink.c:541](D:/proj/char/chrg_v/apps/chrg/applications/utils/chrg_sink.c:541)。
|
||||
|
||||
如果消费者在状态切换后看到尚未填充的批次,会认为没有任务并切回自动模式;随后加入的 `pending` 数据可能一直无人处理。当前线程优先级降低了部分窗口概率,但没有从同步机制上消除竞态。
|
||||
|
||||
6. **中高风险:应答邮箱没有请求、通道或序号关联**
|
||||
|
||||
邮箱消息只有 `length + payload`:[chrg_def.h:95](D:/proj/char/chrg_v/apps/chrg/applications/utils/chrg_def.h:95)。
|
||||
|
||||
南北轮询线程默认“收到的下一帧就是刚才请求的响应”。南向批处理只检查 CRC,任何延迟到达的旧响应都可能让当前批次 `cur_idx++`:[chrg_roll_sou.c:574](D:/proj/char/chrg_v/apps/chrg/applications/thread/chrg_roll_sou.c:574)。
|
||||
|
||||
在超时、重发、通道切换或邮箱积压后,请求与响应很容易错位,最终造成状态机停在错误步骤或无限重试。
|
||||
|
||||
7. **中风险:所有业务互斥量都是永久等待**
|
||||
|
||||
TTY、南北轮询互斥量统一使用 `RT_WAITING_FOREVER`。例如:
|
||||
|
||||
- [chrg_tty.c:457](D:/proj/char/chrg_v/apps/chrg/applications/bsp/chrg_tty.c:457)
|
||||
- [chrg_comm.c:2246](D:/proj/char/chrg_v/apps/chrg/applications/thread/chrg_comm.c:2246)
|
||||
- [chrg_roll_nor.c:439](D:/proj/char/chrg_v/apps/chrg/applications/thread/chrg_roll_nor.c:439)
|
||||
|
||||
目前没有发现确定的反向加锁环,但一旦锁所有者因堆破坏、状态机卡死或设备写阻塞而不再释放,其他线程会永久挂起,没有超时和故障上报。
|
||||
|
||||
8. **中风险:串口 RingBuffer 写入结果被忽略**
|
||||
|
||||
[chrg_north.c:623](D:/proj/char/chrg_v/apps/chrg/applications/thread/chrg_north.c:623) 和 [chrg_south.c:383](D:/proj/char/chrg_v/apps/chrg/applications/thread/chrg_south.c:383) 没有检查 `rt_ringbuffer_put()` 实际写入长度。
|
||||
|
||||
缓冲区满时会静默丢字节,随后触发分包超时、泄漏和上述越界路径,是长期运行后出现问题的重要放大器。
|
||||
|
||||
**优先判断**
|
||||
|
||||
最可能的两条故障链是:
|
||||
|
||||
1. 串口分包 → 长度计算错误/超时泄漏 → 堆损坏或耗尽 → 某些业务线程永久等待;主线程继续喂狗。
|
||||
2. 南向某条命令超时或响应错位 → `RUN_COM` 无限重发 → 南向业务永久停止;主线程和北向线程继续喂狗。
|
||||
|
||||
现场故障尚能进入 Shell 时,优先保存 `list_thread`、`list_mutex`、`list_mailbox`、`free` 输出,并检查是否持续打印 `com batch timeout, resend current reg`。这几项可以直接区分锁等待、堆耗尽和状态机无限重试。
|
||||
|
||||
未修改任何文件。
|
||||
@@ -0,0 +1,36 @@
|
||||
# 测试日志
|
||||
|
||||
## V1.1.8 - 2026-08-24
|
||||
|
||||
### 测试对象
|
||||
|
||||
Source协议切换复位逻辑。
|
||||
|
||||
### 验证记录
|
||||
|
||||
| 编号 | 测试项 | 预期结果 | 当前结果 |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | 首次发送Source协议 | 直接发送协议,不发送`SOURCE_RESET` | 静态检查通过 |
|
||||
| 2 | PD切换到非PD | 先复位,再发送协议 | 静态检查通过 |
|
||||
| 3 | 非PD切换到PD | 先复位,再发送协议 | 静态检查通过 |
|
||||
| 4 | PD切PD | 不复位,直接发送协议 | 静态检查通过 |
|
||||
| 5 | 非PD切非PD | 不复位,直接发送协议 | 静态检查通过 |
|
||||
| 6 | 仅切换CC线 | 不复位 | 静态检查通过 |
|
||||
| 7 | 复位命令帧 | 发送`06 00 02 18 00 0E` | 静态检查通过 |
|
||||
| 8 | 复位回码 | 收到`05 00 02 18 16`后推进状态 | 待硬件验证 |
|
||||
|
||||
### 静态验证
|
||||
|
||||
- 已执行`git diff --check`,无格式错误。
|
||||
- 已检查复位命令、状态映射、回码长度校验和`last_pd_pro`更新路径。
|
||||
- Keil编译及硬件实测未执行。
|
||||
|
||||
### 待补充现场信息
|
||||
|
||||
- 板卡编号:
|
||||
- 测试连接方式:
|
||||
- 测试开始/结束时间:
|
||||
- 复位发送日志:
|
||||
- 复位回码日志:
|
||||
- 协议切换结果:
|
||||
- 最终结论:
|
||||
@@ -0,0 +1,325 @@
|
||||
# 程序流程与函数说明
|
||||
|
||||
## 1. 文档范围
|
||||
|
||||
本文按当前源码(2026-07-19)说明 `apps/chrg/applications/` 的自研函数、运行流程和函数级调用关系,并补充 `apps/boot/` 的启动主链。`rt-thread/`、`libs/`、CubeMX 生成代码、HAL 中断模板以及调试 shell 命令的内部库调用不展开。调用关系由源码静态分析得到;通过 `INIT_*_EXPORT`、线程入口、回调和函数指针发生的调用会单独标明。
|
||||
|
||||
## 2. 上电与初始化流程
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
R["芯片复位"] --> B["Boot main()"]
|
||||
B --> SI["System_Init()"]
|
||||
SI --> AI["APP_Init()"]
|
||||
AI --> AR["APP_Running()"]
|
||||
AR --> CK["boot_CheckAndHandle()"]
|
||||
CK -->|APP 有效| JA["boot_JumpToAPP()"]
|
||||
CK -->|需要升级| RX["recvDataHandler()"]
|
||||
RX --> YH["ymodemHandler()"]
|
||||
YH --> BP["boot_ProtocolDataHandle()"]
|
||||
BP --> FM["FM_* 擦写/校验函数"]
|
||||
FM --> JA
|
||||
JA --> RTT["RT-Thread 启动"]
|
||||
RTT --> INIT["INIT_PREV/DEVICE/ENV/APP_EXPORT"]
|
||||
INIT --> TI["chrg_thread_init()"]
|
||||
TI --> TC["chrg_thread_create() x 6"]
|
||||
TC --> MAIN["main() 空闲循环"]
|
||||
```
|
||||
|
||||
`main()` 不是业务入口。GPIO、FAL、定时器、串口、继电器和看门狗由 RT-Thread 自动初始化段调用;`chrg_thread_init()` 再创建六个常驻线程。初始化失败目前不会阻止后续线程继续创建,排障时必须查看启动日志。
|
||||
|
||||
## 3. 运行期线程与数据流
|
||||
|
||||
| 线程入口 | 职责 | 主要输入 | 主要输出 |
|
||||
|---|---|---|---|
|
||||
| `chrg_north_thread_entry` | 接收协议板/Sink/Source 北向帧 | 北向 UART ringbuffer | 更新 `chrgnorth.sw[]`,投递帧 |
|
||||
| `chrg_south_thread_entry` | 接收功率板 Modbus 响应 | 南向 UART ringbuffer | 投递响应到轮询/通信模块 |
|
||||
| `chrg_comm_thread_entry` | 上位机 Modbus、寄存器映射和业务命令 | mailbox、Modbus 回调 | 修改目标状态,生成南北向命令 |
|
||||
| `chrg_lcd_thread_entry` | HMI 报文解析和状态显示 | LCD 串口 | 修改配置、刷新页面 |
|
||||
| `chrg_roll_nor_thread_entry` | 分时驱动四路 Sink/Source 协议板 | event、通道状态 | 查询/设置协议板,运行 Sink 状态机 |
|
||||
| `chrg_roll_sou_thread_entry` | 串行执行功率板寄存器读写 | event、批命令队列 | Modbus RTU 请求与完成状态 |
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
PC["上位机"] --> MB["Modbus 回调 func* / mb_reg_*_cb"]
|
||||
LCD["HMI"] --> LP["chrg_lcd_parse()"]
|
||||
MB --> CM["chrg_comm_parse_msg()"]
|
||||
LP --> ST["chrgnorth.sw[] 目标状态"]
|
||||
CM --> ST
|
||||
RN["chrg_roll_nor_thread_entry()"] --> SET["chrg_roll_nor_set()"]
|
||||
ST --> SET
|
||||
SET --> SK["sink/source 设置函数"]
|
||||
SK --> NTX["chrg_north_send()"]
|
||||
DEV["协议板"] --> NRX["chrg_north_thread_entry()"]
|
||||
NRX --> FD["chrg_north_frame_dispatch()"]
|
||||
FD --> SP["chrg_sink_parse() / Source 解析"]
|
||||
SP --> SW["chrg_sink_work()"]
|
||||
SW --> SR["chrg_set_sou_reg()"]
|
||||
CM --> SR
|
||||
SR --> RS["chrg_roll_sou_thread_entry()"]
|
||||
RS --> STX["chrg_south_send()"]
|
||||
PWR["功率板"] --> SRX["chrg_south_thread_entry()"]
|
||||
SRX --> SD["chrg_south_frame_dispatch()"]
|
||||
SD --> RS
|
||||
```
|
||||
|
||||
## 4. Sink 工作状态机
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> INIT
|
||||
INIT --> WAIT: 下发停止/安全继电器状态
|
||||
WAIT --> RUNING: 电压正常且接近目标
|
||||
RUNING --> WAIT: 电压正常但电流连续偏低
|
||||
RUNING --> LOW: 电压连续低于 WORK_MIN_VOLT
|
||||
WAIT --> LOW: 电压连续过低
|
||||
LOW --> WAIT: 电压恢复并重新准备
|
||||
RUNING --> OFF: 停止工作
|
||||
WAIT --> OFF: 停止工作
|
||||
```
|
||||
|
||||
函数级主链:`chrg_roll_nor_thread_entry()` → `chrg_roll_nor_set()` → `sink_get_vc()` → 北向响应 → `chrg_north_frame_dispatch()` → `chrg_sink_parse()` → `chrg_sink_work()` → `chrg_sink_work_init()` / `chrg_sink_work_volt_runing()` / `chrg_sink_nor_work_low()` / `chrg_sink_nor_work_off()`。继电器动作由 `chrg_sink_change_ON()`、`chrg_sink_SHOUT_ON()`、`chrg_nor_sw_rel()` 完成,功率板命令最终经 `chrg_set_sou_reg()` 交给南向轮询线程。
|
||||
|
||||
## 5. 函数说明:入口与线程基础设施
|
||||
|
||||
### `main.c`
|
||||
|
||||
| 函数 | 说明 |
|
||||
|---|---|
|
||||
| `show_app_version()` | 打印 RT-Thread 版本和固件编译时间,无输入和返回值。 |
|
||||
| `main()` | 设置 shell 提示符后进入 1 秒延时循环;业务线程由自动初始化段提前创建。 |
|
||||
|
||||
### `thread/chrg_thread.c`
|
||||
|
||||
| 函数 | 说明 |
|
||||
|---|---|
|
||||
| `chrg_thread_evt_send()` | 向指定线程发送事件位;线程或事件对象无效时返回错误。 |
|
||||
| `chrg_thread_mb_free()` | 释放邮箱消息及其 `payload`,仅供本文件失败路径使用。 |
|
||||
| `chrg_thread_mb_send()` | 向指定线程邮箱转移消息所有权;发送失败时自动释放消息。 |
|
||||
| `chrg_thread_mq_send()` | 向指定线程消息队列复制定长消息。 |
|
||||
| `chrg_thread_create()` | 按 `chrgthr[]` 配置创建 IPC 对象、线程并启动线程。 |
|
||||
| `chrg_thread_init()` | 遍历六个线程配置并创建;由 `INIT_APP_EXPORT` 隐式调用。 |
|
||||
|
||||
## 6. 函数说明:通信线程
|
||||
|
||||
### `thread/chrg_north.c`
|
||||
|
||||
| 函数 | 说明 |
|
||||
|---|---|
|
||||
| `chrg_compare()` | 计算两个有符号量的绝对差值。 |
|
||||
| `chrg_source_stop()` | 按步骤停止 Source 输出并处理继电器/状态复位。 |
|
||||
| `chrg_source_standard_output()` | 执行 Source 标准输出控制流程。 |
|
||||
| `chrg_source_fast_output()` | 执行 Source 快充协议输出流程。 |
|
||||
| `chrg_source_setting()` | 根据 Source 当前配置选择和推进设置过程。 |
|
||||
| `chrg_sink_parse()` | 解析 Sink 电压、电流及状态,做低压/无流判定并调用 `chrg_sink_work()`。 |
|
||||
| `chrg_north_handle_Seting_Volt()` | 解析北向设置电压类响应并更新通道状态。 |
|
||||
| `chrg_north_switch()` | 选择当前北向物理通道。 |
|
||||
| `chrg_north_send()` | 通过北向 TTY 发送一帧数据。 |
|
||||
| `chrg_north_frame_head()` | 从 ringbuffer 搜索合法帧头。 |
|
||||
| `chrg_north_frame_reset()` | 重置组帧上下文,并按参数决定是否释放缓存。 |
|
||||
| `chrg_north_frame_append()` | 将接收字节追加到当前帧缓存。 |
|
||||
| `chrg_north_frame_dispatch()` | 校验完整帧并分派到 Source/Sink 业务解析。 |
|
||||
| `chrg_north_pickup_frame()` | 驱动“找帧头—收帧体—分派”状态机。 |
|
||||
| `chrg_north_thread_entry()` | 北向接收线程主循环,从 UART ringbuffer 持续提取帧。 |
|
||||
| `north_ch()` / `north_diag()` | FinSH 调试命令:切换通道、查看诊断计数。 |
|
||||
|
||||
### `thread/chrg_south.c`
|
||||
|
||||
| 函数 | 说明 |
|
||||
|---|---|
|
||||
| `chrg_south_switch_lv1()` / `chrg_south_switch_lv2_1()` / `chrg_south_switch_lv2_2()` | 控制级联选择线,完成南向通道硬件选通。 |
|
||||
| `chrg_south_switch()` | 校验通道并组合调用三级选择函数。 |
|
||||
| `chrg_south_send()` | 通过南向 TTY 发送 Modbus RTU 帧。 |
|
||||
| `chrg_south_frame_head()` | 从 ringbuffer 识别目标地址和功能码。 |
|
||||
| `chrg_south_frame_reset()` | 清理南向组帧状态和动态缓存。 |
|
||||
| `chrg_south_frame_append()` | 追加南向接收字节。 |
|
||||
| `chrg_south_frame_dispatch()` | 校验 CRC 后将响应投递给消费者。 |
|
||||
| `chrg_south_pickup_frame()` | 推进南向组帧状态机。 |
|
||||
| `chrg_south_thread_entry()` | 南向接收线程主循环。 |
|
||||
| `south_ch()` | FinSH 南向通道调试命令。 |
|
||||
|
||||
### `thread/chrg_roll_nor.c`
|
||||
|
||||
| 函数 | 说明 |
|
||||
|---|---|
|
||||
| `sink_fill_pd_buf()` | 按协议类型把组号、电压、电流编码为 Sink 参数字节。 |
|
||||
| `chrg_nor_source_stop()` | 分步骤停止 Source,关闭继电器并清理切换标志。 |
|
||||
| `chrg_roll_nor_sw_uart()` | 在指定通道选择 Sink 或 Source UART。 |
|
||||
| `chrg_roll_nor_sink_pro_set()` | 组装并发送 Sink 快充协议设置。 |
|
||||
| `chrg_roll_nor_source_pro_set()` | 按设置来源选择 Source 协议下发函数。 |
|
||||
| `chrg_roll_nor_parse()` | 根据角色和子命令生成一次北向查询/设置动作。 |
|
||||
| `chrg_roll_nor_cmd()` | 北向命令参数检查接口;当前仅做空指针检查。 |
|
||||
| `chrg_roll_nor_set()` | 北向轮询核心状态机,推进每通道 Source/Sink 子步骤。 |
|
||||
| `chrg_roll_nor_thread_entry()` | 轮询四个北向通道,等待响应并控制超时/重试。 |
|
||||
| `sink()` / `source()` | FinSH 手工配置 Sink/Source 的调试入口。 |
|
||||
| `chrg_trim_crc()` | 计算校准数据 CRC。 |
|
||||
| `chrg_trim_set_volt()` / `chrg_trim_set_curr()` / `chrg_trim_set_source_curr()` | 写入电压、电流及 Source 电流校准值。 |
|
||||
| `chrg_trim_set_zero()` | 执行零点校准设置。 |
|
||||
| `chrg_roll_trim_set()` | 按校准类型分派具体校准函数。 |
|
||||
|
||||
### `thread/chrg_roll_sou.c`
|
||||
|
||||
| 函数 | 说明 |
|
||||
|---|---|
|
||||
| `chrg_sou_com_batch_submit()` | 提交一批南向连续写寄存器命令。 |
|
||||
| `chrg_sou_com_batch_add_reg()` | 向当前批次追加通道、寄存器和值。 |
|
||||
| `chrg_set_sou_reg()` | 提交单个异步寄存器写命令。 |
|
||||
| `chrg_set_sou_reg_com()` | 将寄存器写入合并批次。 |
|
||||
| `sou_com_batch_next()` | 在锁保护下取下一条批命令。 |
|
||||
| `sou_com_batch_complete()` | 标记批命令完成并推进队列。 |
|
||||
| `sou_com_batch_cancel()` | 取消指定通道批命令。 |
|
||||
| `sou_com_batch_pending_locked()` | 判断锁内是否还有待处理批命令。 |
|
||||
| `sou_single_command_finish()` | 结束单命令,恢复期望运行状态。 |
|
||||
| `sou_com_response_matches()` | 判断响应是否匹配当前请求。 |
|
||||
| `sou_msg_free()` | 释放南向邮箱消息。 |
|
||||
| `sou_com_command_failed()` | 统一处理超时/协议错误和批次回滚。 |
|
||||
| `chrg_roll_sou_thread_entry()` | 串行发送南向命令、等待响应并处理重试。 |
|
||||
| `south_send()` / `south_run()` | FinSH 发送寄存器和启停调试命令。 |
|
||||
|
||||
## 7. 函数说明:业务与协议
|
||||
|
||||
### `utils/chrg_sink.c`
|
||||
|
||||
| 函数 | 说明 |
|
||||
|---|---|
|
||||
| `sink_get_vc()` / `sink_get_pd()` | 生成 Sink 电压电流/协议查询帧。 |
|
||||
| `sink_set_cc_line()` / `sink_set_cc_lvl()` | 设置 CC 线选择和电平。 |
|
||||
| `sink_set_pd()` | 编码并发送 Sink 快充协议参数。 |
|
||||
| `chrg_sink_work_init()` | 初始化工作步骤并下发停止/安全继电器命令。 |
|
||||
| `chrg_sink_work_volt_runing()` | 在电压满足条件时推进 RUNING 动作。 |
|
||||
| `chrg_sink_nor_work_low()` | 处理持续低压状态并复位运行条件。 |
|
||||
| `chrg_sink_nor_work_off()` | 执行 Sink 停机收尾。 |
|
||||
| `chrg_sink_change_ON()` / `chrg_sink_SHOUT_ON()` | 控制换向和短接相关继电器步骤。 |
|
||||
| `chrg_sink_work()` | 根据 `work_mode` 分派 Sink 工作状态。 |
|
||||
|
||||
### `utils/chrg_source.c`
|
||||
|
||||
| 函数组 | 说明 |
|
||||
|---|---|
|
||||
| `source_get_vc()` / `source_get_pd()` | 生成 Source 电参/协议查询帧。 |
|
||||
| `source_set_cc_lvl()` / `source_set_cc_choose()` | 配置 Source CC 电平和选择方式。 |
|
||||
| `parse_mulit_gear_One()` / `parse_power_single_gear()` | 解析单组固定档快充能力。 |
|
||||
| `parse_pd_11group_pdo()` / `parse_power_pdo_gear()` | 解析 PDO/PPS 多档能力。 |
|
||||
| `parse_mulit_gear_more()` / `parse_multi_gear_more()` | 解析多组多档协议能力。 |
|
||||
| `parse_ufcs_gear_more()` / `parse_power_ufcs()` | 解析 UFCS 档位。 |
|
||||
| `pd_fill_single_group()` | 通用单组协议参数编码。 |
|
||||
| `source_set_pd()` | 按协议、电压和电流生成 Source 设置帧。 |
|
||||
| `pd_fill_single_group_com()` | 按通信寄存器档位编码单组参数。 |
|
||||
| `pd_fill_single_group_need_src_com()` / `pd_fill_single_group_no_src_com()` | 分别编码需要/不需要 Source 参数的协议。 |
|
||||
| `pd_fill_single_group_FCP_AFC()` / `pd_fill_single_group_UFCS()` | 编码 FCP/AFC 和 UFCS 专用参数。 |
|
||||
| `source_set_pd_com()` / `source_set_pd_new_com()` | 根据寄存器配置或完整通道状态下发 Source 协议。 |
|
||||
|
||||
### `utils/chrg_eload.c`
|
||||
|
||||
| 函数组 | 说明 |
|
||||
|---|---|
|
||||
| `chrg_eload_set_ymodem_resp()` / `chrg_eload_get_ymodem_resp()` / `chrg_eload_clear_ymodem_resp()` | 设置、读取和清除电子负载升级响应标志。 |
|
||||
| `memcmp_8bytes()` | 比较固定 8 字节标识。 |
|
||||
| `chrg_eload_read_regs()` / `chrg_eload_write_reg()` / `chrg_eload_write_More_reg()` | 生成电子负载 Modbus 读、单写和多写请求。 |
|
||||
| `chrg_eload_send_ymodem_data()` | 转发 YModem 升级数据。 |
|
||||
| `chrg_write_cv()` | 写入电子负载 CV 参数。 |
|
||||
| `chrg_eload_send_relay()` | 下发电子负载继电器动作。 |
|
||||
| `chrg_eload_refresh()` | 刷新电子负载测量状态。 |
|
||||
| `chrg_eload_parse()` | 解析电子负载响应并更新通道数据。 |
|
||||
| `snp_ch()` | 选择电子负载通道。 |
|
||||
| `Show_Volt()` / `Show_Curr()` / `Show_Ripple()` / `Show_DZF()` | 计算或刷新对应测量显示项。 |
|
||||
| `Sta_compute()` | 汇总测量状态。 |
|
||||
| `LCD_SHOW()` | 将电子负载测量结果推送到 LCD。 |
|
||||
|
||||
### `utils/chrg_north_pkg.c` 与 `utils/chrg_utils.c`
|
||||
|
||||
| 函数 | 说明 |
|
||||
|---|---|
|
||||
| `chrg_north_pkg_encode()` / `chrg_north_pkg_decode()` | 编码和解码北向协议包,并校验长度/校验值。 |
|
||||
| `mb_crc16()` | 计算 Modbus CRC16。 |
|
||||
| `_crc8()` / `calc_crc8()` | 单字节推进及整段 CRC8 计算。 |
|
||||
| `u16_to_u8v()` / `u16_to_u8v_com()` / `u8v_to_u16()` | 16 位整数与字节序列互转。 |
|
||||
| `u32_to_u8v()` / `u8v_to_u32()` | 32 位整数与字节序列互转。 |
|
||||
| `swap_u16()` / `swap_u32()` | 交换 16/32 位整数端序。 |
|
||||
|
||||
## 8. 函数说明:上位机、LCD 与板级封装
|
||||
|
||||
### `thread/chrg_comm.c`
|
||||
|
||||
| 函数组 | 说明 |
|
||||
|---|---|
|
||||
| `chrg_shadow_sync()` / `chrg_shadow_init()` | 同步/初始化 Modbus 寄存器影子数据。 |
|
||||
| `mb_set_bits()` / `mb_get_bits()` | 在 Modbus 位缓冲区写入/读取指定位段。 |
|
||||
| `mb_reg_input_cb()` / `mb_reg_holding_cb()` / `mb_reg_test_cb()` | 输入、保持和测试寄存器回调。 |
|
||||
| `mb_ymodem_updata_cb()` | 处理升级寄存器数据。 |
|
||||
| `mb_reg_coils_cb()` / `mb_reg_discrete_cb()` | 线圈与离散输入回调。 |
|
||||
| `funcReadCoils()` / `funcReadDiscreteInputs()` / `funcReadHoldingRegister()` / `funcReadInputRegister()` | 实现对应 Modbus 读功能。 |
|
||||
| `funcWriteCoil()` / `funcWriteHoldingRegister()` / `funcWriteMultipleCoils()` / `funcWriteMultipleHoldingRegister()` | 校验并执行对应写功能。 |
|
||||
| `sink_proto_lookup()` / `src_proto_lookup()` / `src_type_lookup()` | 将寄存器枚举映射为内部协议/Source 类型。 |
|
||||
| `parse_load_no_group()` / `parse_load_with_group()` | 解析无组号/带组号的负载协议参数。 |
|
||||
| `chrg_com_source_on()` | 根据通信配置启动 Source 流程。 |
|
||||
| `funcWriteProtoCal()` / `funcSinkTest()` / `funcTrimELoad()` | 处理协议校准、Sink 测试和电子负载校准命令。 |
|
||||
| `funYmodemUpadata()` | 推进固件升级命令。 |
|
||||
| `chrg_comm_parse_msg()` | 解析通信线程邮箱消息并分派功能码。 |
|
||||
| `chrg_comm_updata_north()` | 将实时北向状态同步到寄存器区。 |
|
||||
| `chrg_comm_thread_entry()` | 初始化 Modbus 从站并循环处理消息/状态同步。 |
|
||||
| `chrg_mb_write_sink()` / `chrg_mb_write_src()` / `chrg_mb_write_sys()` | 将保持寄存器变化写入 Sink、Source 和系统状态。 |
|
||||
| `chrg_sink_get_proto_diff()` | 比较目标与实际 Sink 协议参数。 |
|
||||
| `chrg_sink_diff_send_reg()` | 仅发送存在差异的 Sink 寄存器。 |
|
||||
| `set_ymodem_update_channel()` / `mb_error()` / `rs485snd()` | 分别设置升级通道、转换错误码和提供 RS485 调试命令。 |
|
||||
|
||||
### `thread/chrg_lcd.c`
|
||||
|
||||
| 函数组 | 说明 |
|
||||
|---|---|
|
||||
| `chrg_sou_work()` / `chrg_sou_stop()` | 启动/停止指定功率通道。 |
|
||||
| `chrg_pro_set()` | 应用 LCD 输入的快充协议配置。 |
|
||||
| `chrg_set_eload_sink()` / `chrg_set_eload_source()` | 配置电子负载的 Sink/Source 角色。 |
|
||||
| `chrg_set_CV()` / `chrg_set_CC()` / `chrg_roll_set_cv()` | 设置 CV、CC 及轮询相关目标值。 |
|
||||
| `chrg_lcd_parse()` | 解析 HMI 命令并修改对应通道配置。 |
|
||||
| `chrg_lcd_send()` | 向 HMI 发送数据。 |
|
||||
| `chrg_lcd_thread_entry()` | LCD 串口收发与周期刷新主循环。 |
|
||||
| `lcdsend()` | FinSH LCD 原始发送调试命令。 |
|
||||
|
||||
### `bsp/`
|
||||
|
||||
| 模块 | 函数说明 |
|
||||
|---|---|
|
||||
| `chrg_fal.c` | `chrg_fal_read()`、`chrg_fal_write()`、`chrg_fal_erase()`、`chrg_fal_erase_all()` 封装分区访问;`chrg_fal_init()` 初始化 FAL。 |
|
||||
| `chrg_gpio.c` | `chrg_gpio_mode_set()`、`chrg_gpio_get()`、`chrg_gpio_set()` 封装 GPIO;`chrg_gpios_init()` 初始化引脚。 |
|
||||
| `chrg_rel.c` | `chrg_nor_sw_rel()` 控制北向继电器;`chrg_nor_rel_init()` 初始化;`rel_test()` 用于 shell 测试。 |
|
||||
| `chrg_switch.c` | `chrg_switch_ch()` 驱动通道译码选择线。 |
|
||||
| `chrg_vcom.c` | `chrg_vcom_init()` 初始化 USB 虚拟串口;`chrg_vcom_console_init()` 注册控制台。 |
|
||||
| `chrg_wdt.c` | `chrg_wdt_feed()` 喂狗;`chrg_wdt_init()` 初始化并启动看门狗。 |
|
||||
| `chrg_tmr.c` | `chrg_tmr_get_count()`、`chrg_tmr_start()`、`chrg_tmr_stop()`、`chrg_tmr_release()`、`chrg_tmr_open()` 管理软件秒定时器;`chrg_tmr_1s_callback()` 计时;`chrg_tmrs_init()` 初始化;`uptime()`、`sec_tmr()` 为 shell 命令。 |
|
||||
| `chrg_led.c` | `chrg_led_get()`、`chrg_led_set()`、`chrg_led_toggle()`、`chrg_led_pulsing()`、`chrg_led_flashing()` 控制 LED;`chrg_led_timer_set_on()`、`chrg_led_timer_set_off()`、`chrg_led_timer_start()`、`chrg_led_timer_delete()`、`chrg_led_timer_timeout_callback()`、`chrg_led_show()` 管理闪烁时序;`chrg_leds_init()` 初始化。 |
|
||||
| `chrg_tty.c` | `chrg_tty_send_comp_hook()`、`chrg_tty_recv_ind_hook()` 为驱动回调;`chrg_tty_cal_byte_tmo()`、`chrg_tty_mode_set()`、`chrg_tty_dev_open()`、`chrg_tty_config()` 配置串口;`chrg_tty_connect()`、`chrg_tty_disconn()`、`chrg_tty_destory()` 管理连接;`chrg_tty_set_recv_tmo()`、`chrg_tty_set_byte_tmo()` 设置超时;`chrg_tty_recv()`、`chrg_tty_send()`、`chrg_tty_break_recv()`、`chrg_tty_send_then_recv()` 完成阻塞式收发。 |
|
||||
|
||||
## 9. Bootloader 函数级主链
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
M["main()"] --> SI["System_Init()"]
|
||||
M --> GPIO["MX_GPIO_Init() / MX_DMA_Init() / MX_USART_Init()"]
|
||||
M --> AI["APP_Init()"]
|
||||
AI --> DTI["DT_Init()"]
|
||||
AI --> YI["ymodem_init()"]
|
||||
AI --> FI["FM_Init()"]
|
||||
M --> AR["APP_Running()"]
|
||||
AR --> RD["recvDataHandler()"]
|
||||
RD --> DPR["DT_PollingReceive()"]
|
||||
RD --> YH["ymodemHandler()"]
|
||||
YH --> BPD["boot_ProtocolDataHandle()"]
|
||||
AR --> BCH["boot_CheckAndHandle()"]
|
||||
BCH --> BCF["boot_CheckFirmware()"]
|
||||
BCH --> BAU["boot_AutoUpdate()"]
|
||||
BAU --> FMR["FM_ReadFirmwareHead()"]
|
||||
BAU --> FMV["FM_VerifyFirmware()"]
|
||||
BAU --> FMU["FM_UpdateToAPP()"]
|
||||
BCH --> J["boot_JumpToAPP()"]
|
||||
```
|
||||
|
||||
Boot 辅助模块职责:`firmware.c` 的 `FM_*` 函数负责分区头、擦写、CRC 校验、版本和搬运;`ymodem.c` 的 `ymodemHandler()`、`ymodemConfig()` 负责升级协议状态机;`transfer.c` 的 `DT_Init()`、`DT_Send()`、`DT_PollingReceive()` 负责串口帧传输;`drv_timer.c` 提供启动、重启、暂停、注销、处理和用户数据绑定;`bsp_uart.c`/`bsp_uart_port.c` 提供 UART、DMA、中断及接收完成回调。
|
||||
|
||||
## 10. 阅读与调试顺序
|
||||
|
||||
1. 启动异常先看 `chrg_thread_init()` 和各 `INIT_*_EXPORT` 初始化返回值。
|
||||
2. 北向无数据依次跟踪 `chrg_north_thread_entry()`、`chrg_north_frame_head()`、`chrg_north_pickup_frame()`、`chrg_north_frame_dispatch()`。
|
||||
3. Sink 不启动依次检查 `chrg_sink_parse()` 的电压/电流判定、`work_mode`、`chrg_sink_work()` 和 `chrg_set_sou_reg()`。
|
||||
4. 功率板命令未生效依次检查 `chrg_set_sou_reg()`、`chrg_roll_sou_thread_entry()`、`chrg_south_send()` 和南向响应匹配。
|
||||
5. 上位机写入未生效依次检查 Modbus `funcWrite*()`、`chrg_mb_write_*()`、共享状态和两个轮询线程。
|
||||
@@ -890,7 +890,7 @@ static void fal(rt_uint8_t argc, char **argv) {
|
||||
{
|
||||
if (write_data[index] != read_data[index])
|
||||
{
|
||||
rt_kprintf("%d %d %02x %02x.\n", i, index, write_data[index], read_data[index]);
|
||||
// rt_kprintf("%d %d %02x %02x.\n", i, index, write_data[index], read_data[index]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2237,6 +2237,7 @@ static struct rt_thread usb_thread;
|
||||
/* internal of the message queue: every message is associated with a pointer,
|
||||
* so in order to recveive USBD_MQ_MAX_MSG messages, we have to allocate more
|
||||
* than USBD_MQ_MSG_SZ*USBD_MQ_MAX_MSG memory. */
|
||||
rt_align(RT_ALIGN_SIZE)
|
||||
static rt_uint8_t usb_mq_pool[(USBD_MQ_MSG_SZ+sizeof(void*))*USBD_MQ_MAX_MSG];
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user