feat: 完成项目多模块功能迭代与配置更新

1. 新增sqlite文件、协议文档、调试截图、配置ini等各类辅助文件
2. 更新Keil开发包版本与工程配置,调整编译优化等级
3. 重构继电器控制逻辑、串口收发逻辑与线程优先级
4. 新增Modbus寄存器映射、校准结构体与Ymodem升级相关代码
5. 完善南北向协议解析、快充挡位配置与调试日志
6. 修复注释格式、数组越界与线程邮箱溢出问题
7. 新增屏幕控制、功率板调试与协议格式说明文档
This commit is contained in:
yhf
2026-07-18 15:32:54 +08:00
parent 250864c517
commit c820aad809
54 changed files with 6498 additions and 830 deletions
+9
View File
@@ -102,6 +102,15 @@ static void MX_GPIO_Init (void)
HAL_GPIO_Init(LED0_GPIO_Port, &GPIO_InitStruct);
HAL_GPIO_WritePin(LED0_GPIO_Port, LED0_Pin, GPIO_PIN_SET);
/* Configure the MCO1 pin in alternate function mode */
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
+19 -1
View File
@@ -262,6 +262,11 @@ BSP_UART_ERR BSP_UART_Port_DisableReceive(struct UART_STRUCT *uart)
*/
BSP_UART_ERR BSP_UART_Port_Send(struct UART_STRUCT *uart, const uint8_t *data, uint16_t len, uint16_t timeout)
{
// ================================
// ?? 485 发送模式:置 1 ??
// ================================
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
_UART_Alternate(uart);
if (timeout == 0)
@@ -272,7 +277,20 @@ BSP_UART_ERR BSP_UART_Port_Send(struct UART_STRUCT *uart, const uint8_t *data,
return (BSP_UART_ERR)HAL_UART_Transmit_IT(&uart->handle, (uint8_t *)data, len);
}
else
return (BSP_UART_ERR)HAL_UART_Transmit(&uart->handle, (uint8_t *)data, len, timeout);
{
// 发送
BSP_UART_ERR err = (BSP_UART_ERR)HAL_UART_Transmit(&uart->handle, (uint8_t *)data, len, timeout);
// 等待发送完成
while(__HAL_UART_GET_FLAG(&uart->handle, UART_FLAG_TC) == RESET);
// ================================
// ?? 485 回到接收模式:置 0 ??
// ================================
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
return err;
}
}
+2 -2
View File
@@ -16,7 +16,7 @@
<TargetCommonOption>
<Device>STM32F405RGTx</Device>
<Vendor>STMicroelectronics</Vendor>
<PackID>Keil.STM32F4xx_DFP.3.1.0</PackID>
<PackID>Keil.STM32F4xx_DFP.3.1.1</PackID>
<PackURL>https://www.keil.com/pack/</PackURL>
<Cpu>IRAM(0x20000000,0x00020000) IRAM2(0x10000000,0x00010000) IROM(0x08000000,0x00100000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE</Cpu>
<FlashUtilSpec></FlashUtilSpec>
@@ -138,7 +138,7 @@
</Flash1>
<bUseTDR>1</bUseTDR>
<Flash2>BIN\UL2CM3.DLL</Flash2>
<Flash3></Flash3>
<Flash3>"" ()</Flash3>
<Flash4></Flash4>
<pFcarmOut></pFcarmOut>
<pFcarmGrp></pFcarmGrp>
+9
View File
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<component_viewer schemaVersion="0.1" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:noNamespaceSchemaLocation="Component_Viewer.xsd">
<component name="EventRecorderStub" version="1.0.0"/> <!--name and version of the component-->
<events>
</events>
</component_viewer>
+3 -2
View File
@@ -37,7 +37,7 @@ void chrg_nor_sw_rel (eIDX_NOR_CH ch, eIDX_ID id)
}
if (ID_SOURCE == id) {
rt_pin_write(chrgrel[ch].p2, PIN_LOW);
rt_pin_write(chrgrel[ch].p2, PIN_HIGH);//sw置1
rt_pin_write(chrgrel[ch].p1, PIN_HIGH);
rt_pin_write(chrgrel[ch].p0, PIN_LOW);
} else if (ID_SINK == id) {
@@ -96,7 +96,7 @@ int rel_test (int argc, char **argv)
return -1;
}
rt_uint8_t val = (rt_uint8_t)atoi(argv[3]);
if ((idx > 2)||(idx < 1)) {
if ((idx > 3)||(idx < 0)) {
rt_kprintf("help : %s <get|set> <0|1|2|3> [1, 2]", argv[0]);
return -1;
}
@@ -110,6 +110,7 @@ int rel_test (int argc, char **argv)
rt_kprintf("rel connect [%d] : sink\r\n", idx);
} else if ((0 == data[0])&&(1 == data[1])&&(1 == data[2])) {
rt_kprintf("rel connect [%d] : source\r\n", idx);
rt_kprintf("rel connect [%d] : p0=%d, p1=%d, p2=%d\r\n",idx, data[0], data[1], data[2]);
} else {
rt_kprintf("rel connect [%d] : p0=%d, p1=%d, p2=%d\r\n",
idx, data[0], data[1], data[2]);
+2 -1
View File
@@ -32,7 +32,8 @@ extern struct chrg_rel_t chrgrel[TOTAL_NOR_CHS];
其它说明: -
*****************************************************************/
extern void chrg_nor_sw_rel (eIDX_NOR_CH ch, eIDX_ID id);
#define Main_Relay 0x01
//#define Filter_Relay
#endif
+1 -5
View File
@@ -485,7 +485,7 @@ int chrg_tty_recv (struct chrg_tty_t *pTTY, void *buf, int size)
if ((recved & TTY_EVT_RX_BREAK) != 0) {
rt_mutex_release(pTTY->lock);
rt_thread_delay(2);
rt_thread_delay(1);
return 0;
}
}
@@ -508,7 +508,6 @@ int chrg_tty_send (struct chrg_tty_t *pTTY, void *buf, int size)
{
rt_err_t ret = RT_EOK;
int send_len = 0;
if (pTTY == RT_NULL || buf == RT_NULL || size == 0) {
LOG_E("param null.");
return (-RT_ERROR);
@@ -524,13 +523,10 @@ int chrg_tty_send (struct chrg_tty_t *pTTY, void *buf, int size)
LOG_E("mutex take failed. [%d]", ret);
return (-RT_ERROR);
}
chrg_tty_mode_set(pTTY, 1);//set to send mode
send_len = rt_device_write(pTTY->dev, 0, buf, size);
chrg_tty_mode_set(pTTY, 0);//set to receive mode
rt_mutex_release(pTTY->lock);
return send_len;
}
+3 -4
View File
@@ -26,16 +26,15 @@ typedef enum {
TOTAL_TTYS
} eIDX_TTY;
//#define TTY_USING_DMA_RX //使用DMA接收
//#define TTY_USING_DMA_RX 1 //使用DMA接收
//#define TTY_USING_INT_TX //使用中断发送
//#define TTY_USING_DMA_TX //使用DMA发送
//#define TTY_USING_DMA_TX 1 //使用DMA发送
#ifndef TTY_SW_DLY_US
#define TTY_SW_DLY_US 0 // 发送引脚控制切换延时
#endif
#define SIZE_BUF_TTY 256
#define SIZE_BUF_TTY 1029
#define TTY_TX_COMP_TMO_MAX (3 * RT_TICK_PER_SECOND) // 最大DMA传输完成超时
#define TTY_BYTE_TMO_MIN 2 // 最小字节超时
+4 -3
View File
@@ -27,17 +27,18 @@ void show_app_version (void)
int main(void)
{
//rt_uint32_t tick = 0;
// rt_uint32_t tick = 0;
#if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH)
finsh_set_prompt("chrg ");
#endif
while (1) {
rt_thread_mdelay(1000);
chrg_wdt_feed();
// chrg_wdt_feed();
//rt_kprintf("%d\r\n", ++tick);
// rt_kprintf("%d\r\n", ++tick);
}
}
File diff suppressed because it is too large Load Diff
+84 -25
View File
@@ -13,23 +13,30 @@
#include <rtthread.h>
#include "chrg_tty.h"
#include "chrg_regs.h"
#define MODBUS_ADDRESS_DEFAULT 0x01
#define BITS_UCHAR 8U
#define S_DISCRETE_INPUT_START 0
#define S_DISCRETE_INPUT_NDISCRETES 16
#define S_COIL_START 0
#define S_COIL_NCOILS 64
#define S_REG_INPUT_START 0
#define S_REG_INPUT_NREGS 100
#define S_REG_HOLDING_START 0
#define S_REG_HOLDING_NREGS 100
#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);
typedef enum {
MB_REG_READ, /*!< Read register values and pass to protocol stack. */
MB_REG_WRITE /*!< Update register values. */
@@ -45,20 +52,55 @@ typedef enum {
MB_EILLSTATE, /*!< protocol stack in illegal state. */
MB_ETIMEDOUT /*!< timeout error occurred. */
} eMBErrorCode;
// ========== 新寄存器地址映射 (使用0x06/0x10标准Modbus功能码) ==========
// 详细寄存器偏移定义见 chrg_regs.h
#define MB_ADDRESS_BROADCAST (0) // 广播地址
#define MB_ADDRESS_MIN (1) // 地址最小值
#define MB_ADDRESS_MAX (247) // 地址最大值
// 判断寄存器地址属于哪个区块的宏
#define REG_IS_SINK(addr) (((addr / 4) < TOTAL_SINK_CH_REGS))
#define REG_IS_SRC(addr) (((addr / 4) < TOTAL_SRC_CH_REGS))
#define REG_IS_SYS(addr) (((addr / 4) < TOTAL_SYS_CH_REGS))
#define MB_READ_COILS (0x01) // 读线圈
#define MB_READ_DISCRETE_INPUTS (0x02) // 读离散输入
#define MB_READ_HOLDING_REGISTER (0x03) // 读保持寄存器
#define MB_READ_INPUT_REGISTER (0x04) // 读输入寄存器
#define MB_WRITE_SINGLE_COIL (0x05) // 写单个线圈
#define MB_WRITE_REGISTER (0x06) // 写单个寄存器
#define MB_WRITE_MULTIPLE_COILS (0x0F) // 写多个线圈
#define MB_WRITE_MULTIPLE_REGISTERS (0x10) // 写多个寄存器
#define MB_FUNC_ERROR (0x80)
// 根据地址提取通道号和区块内偏移
#define REG_GET_SINK_CH(addr) ((addr) / TOTAL_SINK_CH_REGS)
#define REG_GET_SINK_OFFSET(addr) ((addr) % TOTAL_SINK_CH_REGS)
#define REG_GET_SRC_CH(addr) ((addr) / TOTAL_SRC_CH_REGS)
#define REG_GET_SRC_OFFSET(addr) ((addr) % TOTAL_SRC_CH_REGS)
#define REG_GET_SYS_CH(addr) ((addr) / TOTAL_SYS_CH_REGS)
#define REG_GET_SYS_OFFSET(addr) ((addr) % TOTAL_SYS_CH_REGS)
//继电器偏移量
// 继电器寄存器偏移量
#define MODBUS_COIL_PWR_SRC 0x00 // 功率板-主电源继电器(每通道第0个)
#define MODBUS_COIL_PWR_SINK 0x01 // 功率板-主负载继电器(每通道第1个)
#define MODBUS_COIL_SINK_CC 0x02 // 协议板-负载CC继电器(每通道第2个)
#define MODBUS_COIL_SRC_CC 0x03 // 协议板-电源CC继电器(每通道第3个)
// 预留偏移量(对应每通道第4,可后续扩展)
#define MODBUS_COIL_PWR_ALL 0x04 // 功率板-俩个继电器
#define MODBUS_COIL_RESERVE2 0x05 // 预留继电器2(每通道第5个)
////复位相关
//#define RESET_NORTH_ADDR 0x0F00
//#define RESET_NORTH_VALUE 0x5A5A
//#define RESET_SOUTH_ADDR 0x0F01
#define MB_ADDRESS_BROADCAST (0) // 广播地址
#define MB_ADDRESS_MIN (1) // 地址最小值
#define MB_ADDRESS_MAX (247) // 地址最大值
// Modbus 标准功能码
#define MB_READ_COILS (0x01) // 读线圈
#define MB_READ_DISCRETE_INPUTS (0x02) // 读离散输入
#define MB_READ_HOLDING_REGISTER (0x03) // 读保持寄存器
#define MB_READ_INPUT_REGISTER (0x04) // 读输入寄存器
#define MB_WRITE_SINGLE_COIL (0x05) // 写单个线圈
#define MB_WRITE_REGISTER (0x06) // 写单个寄存器
#define MB_WRITE_MULTIPLE_COILS (0x0F) // 写多个线圈
#define MB_WRITE_MULTIPLE_REGISTERS (0x10) // 写多个寄存器
// 扩展功能码 (保留,非标准Modbus)
#define MB_YMODEM_UPDATAE (0x20) // Ymodem升级指令
#define MB_TRIM_ELOAD (0x21) // 校准源载指令
#define MB_FUNC_ERROR (0x80)
typedef enum {
MB_EX_NONE = 0x00,
@@ -79,6 +121,8 @@ typedef enum {
#define MB_SER_PDU_ADDR_OFF 0 /*!< Offset of slave address in Ser-PDU. */
#define MB_SER_PDU_PDU_OFF 1 /*!< Offset of Modbus-PDU in Ser-PDU. */
typedef eMBException(*pFunctionHandler) (rt_uint8_t *reqFrame, rt_uint16_t reqLen,
rt_uint8_t *resFrame, rt_uint16_t *resLen);
@@ -142,6 +186,18 @@ struct code_func_t {
#define MB_PDU_FUNC_WRITE_MUL_REGCNT_MAX (0x0078)
#define MB_PDU_FUNC_WRITE_MUL_COILCNT_MAX (0x07B0)
#define MB_YMODEM_DATA_SIZE (1029)
////升级协议状态
//typedef enum {
// Ymodem_No = 0,
// Ymodem_Wait,
// Ymodem_Rec_Start,
// Ymodem_Rec_1024,
// Ymodem_Rec_End,
// Ymodem_Rec_Finish
//} Ymodem_state;
#define THR_NAME_COMM "thr.comm"
#define DEV_NAME_COMM "uart1"
@@ -170,7 +226,10 @@ extern struct chrg_comm_t chrgcomm;
*****************************************************************/
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
+321 -148
View File
@@ -11,26 +11,25 @@
#include <stdlib.h>
#include <string.h>
#include <rtthread.h>
#include "chrg_rel.h"
#include "chrg_north_pkg.h"
#include "chrg_north.h"
#include "chrg_south.h"
#include "chrg_roll_sou.h"
#include "chrg_eload.h"
#include "chrg_utils.h"
#include "chrg_lcd.h"
#include "chrg_roll_nor.h"
#define LOG_TAG "chrg.lcd"
#define DBG_LEVEL DBG_LOG
#include <rtdbg.h>
#include "chrg_eload.h"
int Flag_R1=0,Flag_R2=0,Flag_R3=0,Flag_R4=0;
struct chrg_lcd_t chrglcd = {
.devname = DEV_NAME_LCD,
.tty = RT_NULL,
};
// 55 21 00 0D 0A 负载
// 55 21 01 0D 0A 电源
// 55 31 00 0D 0A 恒流
@@ -38,6 +37,89 @@ 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;
if(pSOU == RT_NULL){
return;
}
if(pSW->id == ID_SOURCE){
pSW->source.Stop_step_flag = 0;
pSW->source.On_Flag = 0;
pSW->sub = IDX_GET_SOURCE_VC;
}
else if(pSW->id == ID_SINK){
pSW->sink.On_work = 0;
pSW->sub = IDX_SET_SINK_WORK_STATE;
}
pSOU->online[ch] = 0;
#if LCD_OPEN
pNOR->free_flag = 1;
#endif
}
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;
if(pSW->sink.protocol==0xC1)
{
pSW->sink.protocol = 0xFE;
}
}
return 0;
}
void chrg_set_eload_sink(eIDX_SOU_CH ch,struct chrg_switch_t *pSW){
pSW->id = ID_SINK;
//pSW->sink.protocol = 0xFE;
chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_ELOAD, ELOAD_LOAD);
if(pSW->continue_flag==0){
}
}
void chrg_set_eload_source(eIDX_SOU_CH ch,struct chrg_switch_t *pSW){
pSW->id = ID_SOURCE;
chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_ELOAD, ELOAD_SOURCE);
}
void chrg_set_CV(rt_uint8_t ch,struct chrg_switch_t *pSW){
chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_MODE, MODE_CONSTANT_VOLTAGE);
}
void chrg_set_CC(rt_uint8_t ch,struct chrg_switch_t *pSW){
chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_MODE, MODE_CONSTANT_CURRENT);
}
//设置恒压恒流模式
void chrg_roll_set_cv(eIDX_NOR_CH ch,struct chrg_switch_t *pSW,rt_uint8_t CV_flag){
if(CV_flag ==1) chrg_set_CV(ch,pSW);
else chrg_set_CC(ch,pSW);
pSW->sub = IDX_SET_SOURCE_ID;
}
/*****************************************************************
函数名称: chrg_lcd_parse
函数描述: 接收显示屏的控制消息
@@ -46,117 +128,179 @@ struct chrg_lcd_t chrglcd = {
返回说明: <0: 错误
其它说明: 本部分为 HMI 文件自定义命令,需要统一规划管理
*****************************************************************/
rt_uint8_t On_Flag = 0;
rt_uint8_t ch = 0;
static int chrg_lcd_parse (rt_uint8_t *recv, rt_uint16_t len)
{
rt_uint16_t Recv_Data;
rt_uint16_t Recv_Data;
ch = 0;
if (len < 5) {
return -1;
}
if (len < 5) {
return -1;
}
if (0x55 != recv[LCD_IDX_HEAD]) {
return -2;
}
struct chrg_north_t *pNOR = &chrgnorth;
struct chrg_south_t *pSOU = &chrgsouth;
struct chrg_switch_t *pSW = RT_NULL;
struct chrg_rollsou_t *pROLL = &chrgrollsou;
switch (recv[LCD_IDX_CMD]) {
// 变电协议
case 0x11:
case 0x12:
case 0x13:
case 0x14:{
ch = recv[LCD_IDX_CMD] - 0x11;
pSW = &pNOR->sw[ch];
chrg_pro_set(pSW,recv[2]);
break;
}
// 电源/负载切换
case 0x21:
case 0x22:
case 0x23:
case 0x24: {
ch = recv[LCD_IDX_CMD] - 0x21;
if (Flag_R1 == 1 && ch == 0) return 0;
if (Flag_R2 == 1 && ch == 1) return 0;
if (Flag_R3 == 1 && ch == 2) return 0;
if (Flag_R4 == 1 && ch == 3) return 0;
pSW = &pNOR->sw[ch];
if (1 == recv[LCD_IDX_VAL]) {
// 电源模式(Source
chrg_set_eload_source(ch,pSW);
} else {
// 负载模式(Sink
chrg_set_eload_sink(ch,pSW);
}
break;
}
// 恒压/恒流模式
case 0x31:
case 0x32:
case 0x33:
case 0x34: {
ch = recv[LCD_IDX_CMD] - 0x31;
if (Flag_R1 == 1 && ch == 0) return 0;
if (Flag_R2 == 1 && ch == 1) return 0;
if (Flag_R3 == 1 && ch == 2) return 0;
if (Flag_R4 == 1 && ch == 3) return 0;
if (1 == recv[LCD_IDX_VAL]) {
chrg_set_CV((eIDX_SOU_CH)ch,pSW);
} else {
chrg_set_CC((eIDX_SOU_CH)ch,pSW);
}
break;
}
//运行停止
case 0x41:
case 0x42:
case 0x43:
case 0x44: {
ch = recv[LCD_IDX_CMD] - 0x41;
pSW = &pNOR->sw[ch];
//运行
if (1 == recv[LCD_IDX_VAL]) {
switch(ch) {
case 0: Flag_R1 = 1; break;
case 1: Flag_R2 = 1; break;
case 2: Flag_R3 = 1; break;
case 3: Flag_R4 = 1; break;
}
pNOR->enable[ch] = 1;
rt_kprintf("ch=%d\n",ch);
chrg_sou_work((eIDX_SOU_CH)ch,pSW);
pSW->continue_flag = 0;
}
//关闭
else {
switch(ch) {
case 0: Flag_R1 = 0; break;
case 1: Flag_R2 = 0; break;
case 2: Flag_R3 = 0; break;
case 3: Flag_R4 = 0; break;
}
chrg_sou_stop((eIDX_SOU_CH)ch,pSW,pNOR);
}
break;
}
// CV电压值设定
case 0x51:
case 0x52:
case 0x53:
case 0x54: {
ch = recv[LCD_IDX_CMD] - 0x51;
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->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);
}
else chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_VOLTAGE_OUT+1, 5000);
break;
}
if (0x55 != recv[LCD_IDX_HEAD]) {
return -2;
}
rt_uint8_t ch = 0;
struct chrg_north_t *pNOR = &chrgnorth;
struct chrg_south_t *pSOU = &chrgsouth;
struct chrg_switch_t *pSW = RT_NULL;
switch (recv[LCD_IDX_CMD]) {
case 0x21:
case 0x22:
case 0x23:
case 0x24: { // 电源/负载
ch = recv[LCD_IDX_CMD] - 0x21;
if (Flag_R1 == 1 && ch == 0) return 0;
if (Flag_R2 == 1 && ch == 1) return 0;
if (Flag_R3 == 1 && ch == 2) return 0;
if (Flag_R4 == 1 && ch == 3) return 0;
pSW = &pNOR->sw[ch];
if (1 == recv[LCD_IDX_VAL]) {
pSW->id = ID_SOURCE;
chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_ELOAD, ELOAD_SOURCE);
} else {
pSW->id = ID_SINK;
chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_ELOAD, ELOAD_LOAD);
}
}
break;
case 0x31:
case 0x32:
case 0x33:
case 0x34: { // 恒压/恒流
ch = recv[LCD_IDX_CMD] - 0x31;
if (Flag_R1 == 1 && ch == 0) return 0;
if (Flag_R2 == 1 && ch == 1) return 0;
if (Flag_R3 == 1 && ch == 2) return 0;
if (Flag_R4 == 1 && ch == 3) return 0;
if (1 == recv[LCD_IDX_VAL]) {
chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_MODE, MODE_CONSTANT_VOLTAGE);
} else {
chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_MODE, MODE_CONSTANT_CURRENT);
}
}
break;
case 0x41:
case 0x42:
case 0x43:
case 0x44: { // 运行/停止
ch = recv[LCD_IDX_CMD] - 0x41;
if (1 == recv[LCD_IDX_VAL]) {
//pNOR->enable[ch] = 0;
//pSOU->enable[ch] = 0;
switch(ch) {
case 0: Flag_R1 = 1; break;
case 1: Flag_R2 = 1; break;
case 2: Flag_R3 = 1; break;
case 3: Flag_R4 = 1; break;
// CC电流值设定
case 0x61:
case 0x62:
case 0x63:
case 0x64: {
ch = recv[LCD_IDX_CMD] - 0x61;
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->sink.loadc = Recv_Data; // 负载侧电流(mA
pSW->source.Set_Pro_Flag = 1;
// rt_kprintf("cur=%d",Recv_Data);
// 写入电流寄存器
for(int i = 0;i<10;i++){
chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_CURRENT_OUT+1, Recv_Data);
}
break;
}
//cc线设置
case 0x81:
case 0x82:
case 0x83:
case 0x84:{
ch = recv[LCD_IDX_CMD] - 0x81;
Recv_Data = recv[2];
pSW = &pNOR->sw[ch];
// rt_kprintf("data=%d",Recv_Data);
// rt_kprintf("ID=%d\r\n",pSW->id);
// if(pSW->id==ID_SINK){
// pSW->sub = IDX_SET_SINK_CCLINE;
// pSW->sink.cc_set = Recv_Data; // CC线开关设置
// }
switch(Recv_Data){
case 0:
chrg_set_sou_reg(ch, REG_REL_ON, ALL_REL_ON);
break;
case 1:
chrg_set_sou_reg(ch, REG_REL_ON, FU_REL_ON);
break;
case 2:
chrg_set_sou_reg(ch, REG_WORK, WORK_START);
break;
case 3:
chrg_set_sou_reg(ch, REG_WORK, WORK_START);
break;
}
break;
}
chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_WORK, WORK_START);
} else {
//pNOR->enable[ch] = 1;
//pSOU->enable[ch] = 1;
switch(ch) {
case 0: Flag_R1 = 0; break;
case 1: Flag_R2 = 0; break;
case 2: Flag_R3 = 0; break;
case 3: Flag_R4 = 0; break;
}
chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_WORK, WORK_STOP);
}
}
break;
case 0x51:
case 0x52:
case 0x53:
case 0x54: { //CV电压值设定
ch = recv[LCD_IDX_CMD] - 0x51;
Recv_Data = recv[LCD_IDX_VAL+1]<<8|recv[LCD_IDX_VAL];//get lower Reg_Data
//Recv_Data = swap_u16(Recv_Data);
chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_VOLTAGE_OUT+1, Recv_Data);//plus 1set voltage lower REG
}
break;
case 0x61:
case 0x62:
case 0x63:
case 0x64:{ //CC电流值设定
ch = recv[LCD_IDX_CMD] - 0x61;
Recv_Data = recv[LCD_IDX_VAL+1]<<8|recv[LCD_IDX_VAL];//get lower Reg_Data
//Recv_Data = swap_u16(Recv_Data);
chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_CURRENT_OUT+1,Recv_Data);//plus 1set current lower REG
break;
}
}
return 0;
}
return 0;
}
/*****************************************************************
函数名称: chrg_lcd_send
函数描述: 向显示屏发送控制消息
@@ -165,39 +309,69 @@ static int chrg_lcd_parse (rt_uint8_t *recv, rt_uint16_t len)
返回说明: 0:发送完成 <0: 发送失败
其它说明: 参考《淘晶驰串口屏开发手册》http://wiki.tjc1688.com/
*****************************************************************/
int chrg_lcd_send (char *cmd)
{
rt_ssize_t ret = -1;
struct chrg_tty_t *pTTY = chrglcd.tty;
if (RT_NULL == cmd) {
return -1;
}
int chrg_lcd_send (char *cmd)
{
rt_ssize_t ret = -1;
struct chrg_tty_t *pTTY = chrglcd.tty;
if (RT_NULL == cmd) {
return -1;
}
int len = rt_strlen(cmd);
rt_uint8_t *data = rt_malloc(len+3);
if (RT_NULL == data) {
LOG_E("malloc failed.");
return -1;
}
int len = rt_strlen(cmd);
rt_uint8_t *data = rt_malloc(len+3);
if (RT_NULL == data) {
LOG_E("malloc failed.");
return -1;
}
rt_memcpy(data, cmd, len);
rt_memset(&data[len], 0xFF, 3);
rt_memcpy(data, cmd, len);
rt_memset(&data[len], 0xFF, 3);
// for(int i=0;i<len+3;i++){
// rt_kprintf("%02x ",data[i]);
// }
if (RT_NULL != pTTY) {
ret = chrg_tty_send(pTTY, data, len+3);
// LOG_HEX("lcdS", 32, data, len+3);
}
if (RT_NULL != pTTY) {
ret = chrg_tty_send(pTTY, data, len+3);
// LOG_HEX("lcdS", 32, data, len+3);
}
if (RT_NULL != data) {
rt_free(data);
data = RT_NULL;
}
//rt_thread_mdelay(5);
if (RT_NULL != data) {
rt_free(data);
data = RT_NULL;
}
return ret;
}
// static rt_uint8_t lcd_send_buf[64] = {0};
rt_thread_mdelay(20);
// int chrg_lcd_send (char *cmd)
// {
// rt_ssize_t ret = -1;
// struct chrg_tty_t *pTTY = chrglcd.tty;
// // 1. 入参校验
// if (RT_NULL == cmd || RT_NULL == pTTY) {
// return -1;
// }
return ret;
}
// // 2. 计算指令长度(避免malloc,复用全局缓冲区)
// int len = rt_strlen(cmd);
// // 安全检查:避免缓冲区溢出(最长支持60字符,远大于你的36字符)
// if (len > 60) {
// LOG_E("cmd too long: %d", len);
// return -2;
// }
// // 3. 填充指令+补齐3个FF(复用全局缓冲区)
// rt_memcpy(lcd_send_buf, cmd, len);
// rt_memset(&lcd_send_buf[len], 0xFF, 3);
// // 4. 发送数据(无内存分配,直接发送)
// ret = chrg_tty_send(pTTY, lcd_send_buf, len+3);
// // 5. 无需free(全局缓冲区复用)
// return ret;
// }
/*****************************************************************
函数名称: chrg_lcd_thread_entry
@@ -207,10 +381,11 @@ int chrg_lcd_send (char *cmd)
返回说明: -
其它说明: -
*****************************************************************/
int delay_cnt = 0; // 延迟计数器
void chrg_lcd_thread_entry (void *data)
{
struct chrg_thread_t *pTHR = (struct chrg_thread_t *)data;
static uint8_t number = 0;
if (RT_NULL == pTHR) {
return ;
}
@@ -218,7 +393,7 @@ void chrg_lcd_thread_entry (void *data)
int len = 0;
struct chrg_tty_t *pTTY = RT_NULL;
struct chrg_lcd_t *pLCD = &chrglcd;
pTTY = chrg_tty_create(pLCD->devname, 115200, 0, -1, 1);
pTTY = chrg_tty_create(pLCD->devname, 921600, 0, -1, 1);
if (RT_NULL == pTTY) {
LOG_E("tty can't create.");
return ;
@@ -235,18 +410,16 @@ void chrg_lcd_thread_entry (void *data)
while (1) {
rt_memset(pLCD->rx_buf, 0, SIZE_BUF_TTY);
len = chrg_tty_recv(pTTY, pLCD->rx_buf, sizeof(pLCD->rx_buf));
if (len <= 0) {
rt_thread_mdelay(1);
continue;
}
// LOG_HEX("lcdR", 32, pLCD->rx_buf, len);
if (len >= 5) {
chrg_lcd_parse(pLCD->rx_buf, len);
}
if (len <= 0) {
rt_thread_mdelay(1);
delay_cnt++;
continue;
}
// LOG_HEX("lcdR", 32, pLCD->rx_buf, len);
if (len >= 5) {
chrg_lcd_parse(pLCD->rx_buf, len);
}
}
}
+11 -1
View File
@@ -13,7 +13,8 @@
#include <rtthread.h>
#include "chrg_tty.h"
#include "chrg_north.h"
#include "chrg_south.h"
#define THR_NAME_LCD "thr.lcd"
#define DEV_NAME_LCD "uart2"
@@ -41,7 +42,16 @@ extern int chrg_lcd_send (char *cmd);
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);
extern void chrg_set_CV(rt_uint8_t ch,struct chrg_switch_t *pSW);
extern void chrg_set_CC(rt_uint8_t ch,struct chrg_switch_t *pSW);
extern void chrg_roll_set_cv(eIDX_NOR_CH ch,struct chrg_switch_t *pSW,rt_uint8_t CV_flag);
#endif
+361 -39
View File
@@ -10,7 +10,7 @@
#include <string.h>
#include <stdlib.h>
#include <rtthread.h>
#include "chrg_eload.h"
#include "chrg_gpio.h"
#include "chrg_thread.h"
#include "chrg_north_pkg.h"
@@ -19,31 +19,328 @@
#include "chrg_switch.h"
#include "chrg_utils.h"
#include "ulog.h"
#include "chrg_rel.h"
//#define LOG_TAG "chrg.nor"
#define DBG_LEVEL DBG_LOG
#include <rtdbg.h>
rt_uint16_t volt;
uint16_t chrg_compare(rt_int16_t a, rt_int16_t b)
{
if(a>b) return a - b;
else return b - a;
}
/*****************************************************************
函数名称: chrg_source_stop
功能描述: 南向功率源停止流程控制函数(分步执行停止操作)
函数描述: 通过状态机分步执行南向功率停止流程:停止功率输出 -> 关闭北向继电器 -> 清空控制标志并禁用使能
输入参数:
frame_data :原始数据帧指针,用于提取当前电压值
pSW :北向通道控制结构体指针
idx :通道编号(功率通道/北向通道索引)
enable :北向通道使能,停止后关掉使能
返回说明: 无返回值
*****************************************************************/
void chrg_source_stop(rt_uint8_t *frame_data,struct chrg_switch_t *pSW,rt_uint8_t idx,rt_uint8_t *enable){
switch(pSW->source.Stop_step_flag){
case 0: // 停止工作
chrg_set_sou_reg((eIDX_SOU_CH)idx, REG_WORK, WORK_STOP);
rt_thread_mdelay(50);
rt_uint16_t volt_mv_Now = (frame_data[4] << 8) | frame_data[5];
volt = volt_mv_Now;
if(volt_mv_Now < 1000){
pSW->source.Stop_step_flag = 1;
}
break;
case 1: // 关闭北向继电器
chrg_nor_sw_rel((eIDX_NOR_CH)idx,0);
rt_thread_mdelay(50);
pSW->source.Stop_step_flag = 2;
break;
case 2: // 状态2:已执行完停止操作,清空标志位
pSW->source.Set_CV_Flag = 0;
*enable = 0;
break;
default:
break;
}
}
/*****************************************************************
函数名称: chrg_source_standard_output
功能描述: 南向功率源标准输出控制函数
函数描述: 根据CV标志位,分别设置电源输出电压或输出电流,实现标准模式下的恒压/恒流输出
输入参数:
idx :功率通道编号
pSW :北向通道控制结构体指针,包含电压/电流设定值、CV控制标志等参数
输出参数:
pSW :更新CV控制标志位
返回说明: 无返回值
*****************************************************************/
void chrg_source_standard_output(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
{
if(pSW->source.Set_CV_Flag) {
chrg_set_sou_reg((eIDX_SOU_CH)idx, REG_VOLTAGE_OUT+1, pSW->source.max_vol);
#if DEBUG_NORTH
rt_kprintf("Volt_Set%d\r\n",pSW->source.vc.set_voltage);
#endif
pSW->source.Set_CV_Flag = 1;
pSW->change_flag = 0;
}
// if(pSW->source.Set_CV_Flag==0){
// chrg_set_sou_reg((eIDX_SOU_CH)idx, REG_CURRENT_OUT+1, pSW->source.max_vol);
//#if DEBUG_NORTH
// rt_kprintf("Curr_set%d\r\n",Curr_mA);
//#endif
// pSW->source.Set_CV_Flag = 0;
// }
}
//电源快充
void chrg_source_fast_output(rt_uint8_t *frame_data, eIDX_SOU_CH idx,
struct chrg_switch_t *pSW, struct chrg_north_t *pNOR)
{
struct chrg_rollsou_t *pROLL = &chrgrollsou;
rt_uint16_t volt_mv = (frame_data[8] << 8) | frame_data[9];
rt_uint16_t Curr_mA = (frame_data[10] << 8) | frame_data[11];
rt_uint16_t volt_mv_Now = (frame_data[4] << 8) | frame_data[5];
rt_uint16_t Curr_mA_Now = (frame_data[6] << 8) | frame_data[7];
rt_uint16_t volt_compare = chrg_compare(volt_mv, volt_mv_Now);
rt_uint16_t Curr_compare = chrg_compare(Curr_mA, Curr_mA_Now);
static rt_uint8_t number = 0;
#if LCD_OPEN
// rt_kprintf("volt_mv=%d,volt_mv_Now=%d,compare=%d\r\n",volt_mv,volt_mv_Now,volt_compare);
if(volt_compare<5000){ //比较设定值与实际值差距,小于2V认为达成设定,允许屏幕开始变换
number++;
number = number%10;
if(number == 9)
{
pSW->change_flag = 0;
}
}else { //没有达成设定,屏幕不允许变换
pSW->change_flag = 0x01;
}
#endif
// if(volt_mv_Now==0){
// chrg_set_sou_reg((eIDX_SOU_CH)idx, REG_WORK, WORK_START);
// }
// else{
if (pSW->source.Set_CV_Flag == 0){
{
chrg_set_sou_reg((eIDX_SOU_CH)idx, REG_VOLTAGE_OUT+1, volt_mv);
}
pSW->source.Set_CV_Flag = 1;
#if DEBUG_NORTH
rt_kprintf("Volt_Set%d\r\n",volt_mv);
#endif
}
else if(pSW->source.Set_CV_Flag==1){
chrg_set_sou_reg((eIDX_SOU_CH)idx, REG_WORK, WORK_START);
pSW->source.Set_CV_Flag = 0;
}else{
pSW->source.Set_CV_Flag=0;
}
}
//电源设置
void chrg_source_setting(rt_uint8_t *frame_data, eIDX_SOU_CH idx,
struct chrg_switch_t *pSW, struct chrg_north_t *pNOR)
{
//执行输出调整
if (pSW->source.On_Flag == 1) {
if(pSW->source.protocol==0x00){//标准下输出设定值
chrg_source_standard_output(idx, pSW);
}
else{ //快充部分按协商结果输出
chrg_source_fast_output(frame_data, idx, pSW, pNOR);
// rt_kprintf("set_end\r\n");
}
}else if(pSW->source.On_Flag == 0){
//chrg_source_stop(frame_data,pSW,idx,&pNOR->enable[idx]);
pSW->sub = IDX_SET_SOURCE_STOP_STATE;
}
}
////解析负载返回数据
//void chrg_sink_parse(rt_uint8_t *frame_data, eIDX_SOU_CH idx,
// struct chrg_switch_t *pSW, struct chrg_north_t *pNOR)
//{
// rt_uint16_t volt_mv = ((frame_data[4] << 8) | frame_data[5])*10;
// static uint8_t volt_low[TOTAL_SOU_CHS] = {0};
// static uint8_t no_curr[TOTAL_SOU_CHS] = {0};
// pSW->VZ = ((frame_data[14] << 8) | frame_data[15]);
// pSW->VF = ((frame_data[16] << 8) | frame_data[17]);
//#if DEBUG_NORTH
// LOG_D("Sink[%d] real volt: %d mV", idx, volt_mv);
//#endif
//
// if(pSW->sink.On_work == 1) {
// if(pSW->sink.test.test_mode == 0){
// if (volt_mv <= WORK_MIN_VOLT) { // 电压过低,禁止进入工作状态机
// volt_low[idx]++;
// //if(volt_low[idx]>=5) pSW->sink.work_mode = SINK_WORK_LOW; // 复位工作状态机
// }
// else{ // 电压稳定时执行工作状态机(继电器/工作模式切换)
// volt_low[idx] = 0;
// pSW->change_flag = 0;
// if((pSW->sink.pro_loadv - volt_mv) <= 2000){
// pSW->sink.work_mode = SINK_WORK_RUNING;
// if(pSW->Now_current<=200){
// if(no_curr[idx]++>=5){
// pSW->sink.work_mode = SINK_WORK_WAIT;
// no_curr[idx] = 0;
// }
// }
// else no_curr[idx] = 0;
// }
// }
// }
// }
// else{
// volt_low[idx] = 0;
//// pSW->sink.work_mode = SINK_WORK_STOP;
// }
// chrg_sink_work(idx,pSW);
//}
//解析负载返回数据
void chrg_sink_parse(rt_uint8_t *frame_data, eIDX_SOU_CH idx,
struct chrg_switch_t *pSW, struct chrg_north_t *pNOR)
{
rt_uint16_t volt_mv = ((frame_data[4] << 8) | frame_data[5])*10;
static uint8_t volt_low[TOTAL_SOU_CHS] = {0};
static uint8_t no_curr[TOTAL_SOU_CHS] = {0};
pSW->VZ = ((frame_data[14] << 8) | frame_data[15]);
pSW->VF = ((frame_data[16] << 8) | frame_data[17]);
#if DEBUG_NORTH
LOG_D("Sink[%d] real volt: %d mV", idx, volt_mv);
#endif
if(pSW->sink.On_work == 1 && pSW->sink.test.test_mode == 0) {
if (volt_mv <= WORK_MIN_VOLT) { // 电压过低,禁止进入工作状态机
// volt_low[idx]++;
// if(volt_low[idx]>=5) pSW->sink.work_on_step = SINK_WORK_LOW; // 复位工作状态机
}
else{ // 电压稳定时执行工作状态机(继电器/工作模式切换)
volt_low[idx] = 0;
pSW->change_flag = 0;
if((pSW->sink.pro_loadv - volt_mv) <= 2000){
pSW->sink.work_mode = SINK_WORK_RUNING;
if(pSW->Now_current<=200){
if(no_curr[idx]++>=5){
pSW->sink.work_mode = SINK_WORK_WAIT;
no_curr[idx] = 0;
}
}
else no_curr[idx] = 0;
}
}
}
else{
volt_low[idx] = 0;
// pSW->sink.work_on_step = SINK_WORK_STOP; // 复位工作状态机
}
chrg_sink_work(idx,pSW);
}
/*****************************************************************
函数名称: chrg_north_handle_Seting_Volt
功能描述: 处理设置电压/电流命令,解析命令数据并执行相应操作
****************************************************/
rt_uint8_t change_number = 0;
static void chrg_north_handle_Seting_Volt(rt_uint8_t *frame_data, rt_uint16_t frame_len)
{
// 提取电压/电流值
struct chrg_north_t *pNOR = &chrgnorth;
rt_uint16_t idx = pNOR->idx;
struct chrg_switch_t *pSW = &chrgnorth.sw[idx];
static uint8_t number = 0;
//电源部分
if(pSW->id==ID_SOURCE){
chrg_source_setting(frame_data,(eIDX_SOU_CH)idx, pSW, pNOR);
}
else{
chrg_sink_parse(frame_data,(eIDX_SOU_CH)idx, pSW, pNOR);
}
}
struct chrg_north_t chrgnorth = {
.devname = DEV_NAME_NORTH,
.tty = RT_NULL,
.enable = {1, 1, 1, 1},
.sw[IDX_NOR_CH1] = {
.id = ID_SINK,
},
.sw[IDX_NOR_CH2] = {
.id = ID_SINK,
},
.sw[IDX_NOR_CH3] = {
.id = ID_SINK,
},
.sw[IDX_NOR_CH4] = {
.id = ID_SINK,
},
.devname = DEV_NAME_NORTH, // 设备名
.tty = RT_NULL, // 串口句柄初始为空
.enable = {0, 0, 0, 0}, // 4个通道使能初始关闭
.free_flag = 1,
// 通道1IDX_NOR_CH1)初始化
.sw[IDX_NOR_CH1] = {
.CV_mode = 2,
.change_flag = 0,
.show_step = 0,
.id = ID_SINK, // 初始为负载模式
.source = { // 电源侧参数初始化
.On_Flag = 0, // 启动标志初始关闭
.Set_CV_Flag = 1, // 启停控制初始置1
.Set_Pro_Flag = 1 // 电压/电流切换初始置1
}, // 关键:补充逗号分隔source和sink
.sink = {
.protocol = 0xFE,
.work_mode= SINK_WORK_WAIT,
.test.test_mode_old = 0,
}
},
// 通道2IDX_NOR_CH2)初始化
.sw[IDX_NOR_CH2] = {
.show_step = 0,
.id = ID_SINK,
.CV_mode = 2,
.change_flag = 0,
.source = {
.On_Flag = 0,
.Set_CV_Flag = 1,
.Set_Pro_Flag = 1
},
.sink = {
.protocol = 0xFE,
.work_mode= SINK_WORK_WAIT,
.test.test_mode_old = 0,
}
},
// 通道3IDX_NOR_CH3)初始化
.sw[IDX_NOR_CH3] = {
.show_step = 0,
.CV_mode = 2,
.id = ID_SINK,
.change_flag = 0,
.source = {
.On_Flag = 0,
.Set_CV_Flag = 1,
.Set_Pro_Flag = 1
},
.sink = {
.protocol = 0xFE,
.work_mode= SINK_WORK_WAIT,
.test.test_mode_old = 0,
}
},
// 通道4IDX_NOR_CH4)初始化
.sw[IDX_NOR_CH4] = {
.show_step = 0,
.CV_mode = 2,
.id = ID_SINK,
.change_flag = 0,
.source = {
.On_Flag = 0,
.Set_CV_Flag = 1,
.Set_Pro_Flag = 1
},
.sink = {
.protocol = 0xFE,
.work_mode= SINK_WORK_WAIT,
.test.test_mode_old = 0,
}
}
};
/*****************************************************************
函数名称: chrg_north_switch
函数描述: 北向通道选择
@@ -76,7 +373,9 @@ int chrg_north_send (rt_uint8_t *data, rt_size_t length)
struct chrg_tty_t *pTTY = chrgnorth.tty;
if (RT_NULL != pTTY) {
LOG_HEX("sendN", 32, data, length);
#if DEBUG_NORTH //是否打印
// LOG_HEX("sendN", 32, data, length);
#endif
ret = chrg_tty_send(pTTY, data, length);
}
@@ -100,14 +399,30 @@ static int chrg_north_frame_head (struct rt_ringbuffer *rb, rt_uint8_t *head, eI
rt_uint8_t len_frame = 0; // 帧长度
if (RT_NULL == rb) {
rt_kprintf("len_rb=NULL%d\r\n",len_rb);
return -1;
}
len_rb = rt_ringbuffer_data_len(rb);
if (len_rb < LEN_FRAME_HEAD + 2) { // 最短5字节
return -1;
}
if (len_rb < LEN_FRAME_HEAD + 2) { // 最短5字节
// =============================
// 简单版:打印错误帧 + 清空缓冲区
// =============================
rt_kprintf("[ERROR] 帧长度不足,len=%d, data: ", len_rb);
// 把所有数据读出来、打印、同时清空
rt_uint8_t dummy;
while (rt_ringbuffer_getchar(rb, &dummy) == RT_EOK)
{
rt_kprintf("%02x ", dummy); // 打印每一个字节
}
rt_kprintf("\r\n");
return -1;
}
for (i = 0; i < len_rb - 2; i++) { // 找头三个字节 [帧长, 0x00, id]
ret = rt_ringbuffer_getchar(rb, &data);
if (0 == ret) {
@@ -119,6 +434,7 @@ static int chrg_north_frame_head (struct rt_ringbuffer *rb, rt_uint8_t *head, eI
head[0] = data;
len_frame = data;
if (data < MIN_FRAME_LENGTH) { // 长度不符
stage = 0;
continue;
}
@@ -140,6 +456,13 @@ static int chrg_north_frame_head (struct rt_ringbuffer *rb, rt_uint8_t *head, eI
if ((rt_uint8_t)id != data) {
stage = 0;
} else {
// if (id == ID_SINK) {
// rt_uint8_t ext1, ext2;
// // 主动读取并丢弃2字节扩展字段
// rt_ringbuffer_getchar(rb, &ext1);
// rt_ringbuffer_getchar(rb, &ext2);
// rt_kprintf("Sink:%02X %02X\r\n", ext1, ext2);
// }
return len_frame;
}
break;
@@ -162,28 +485,29 @@ static int chrg_north_frame_head (struct rt_ringbuffer *rb, rt_uint8_t *head, eI
返回说明: <0: 错误 >0:帧长度
其它说明: -
*****************************************************************/
int a_number;
static int chrg_north_pickup_frame (struct rt_ringbuffer *rb,
struct pickup_info_t *pFrame, eIDX_NOR_CH idx)
{
int cnt = 0;
rt_size_t len_rb = 0;
if ((RT_NULL == rb)||(RT_NULL == pFrame)) {
return -1;
}
struct chrg_switch_t *pSW = &chrgnorth.sw[idx];
//rt_kprintf("north_idx=%d\r\n",idx);
do {
if (0 == pFrame->findhead) {
//pFrame->len_msg = chrg_north_frame_head(pSW->id,rb, pFrame->head, pSW->id);
pFrame->len_msg = chrg_north_frame_head(rb, pFrame->head, pSW->id);
// rt_kprintf("msg=:%d",pFrame->len_msg);
if (pFrame->len_msg > 0) {
pFrame->pMB = (struct mb_msg_t *)rt_malloc(sizeof(struct mb_msg_t));
if (RT_NULL == pFrame->pMB) {
LOG_E("malloc mb failed.");
return -2;
}
pFrame->pMB->length = pFrame->len_msg;
if (pFrame->pMB->length >= SIZE_BUF_TTY) {
rt_free(pFrame->pMB);
@@ -191,23 +515,23 @@ static int chrg_north_pickup_frame (struct rt_ringbuffer *rb,
LOG_E("too long msg.");
return -3;
}
pFrame->pMB->payload = (rt_uint8_t *)rt_malloc(pFrame->len_msg);
if (RT_NULL == pFrame->pMB->payload) {
LOG_E("malloc buf failed.");
return -4;
}
rt_memcpy(pFrame->pMB->payload, pFrame->head, LEN_FRAME_HEAD);
len_rb = rt_ringbuffer_data_len(rb);
// rt_kprintf("len_rb=%d\r\n",len_rb);
// rt_kprintf("len=%d",pFrame->len_msg - LEN_FRAME_HEAD);
if (len_rb >= pFrame->len_msg - LEN_FRAME_HEAD) {
rt_ringbuffer_get(rb, &pFrame->pMB->payload[LEN_FRAME_HEAD],
pFrame->len_msg - LEN_FRAME_HEAD);
if(pFrame->pMB->length==21){
chrg_north_handle_Seting_Volt(pFrame->pMB->payload, pFrame->pMB->length);
}
chrg_thread_mb_send(IDX_THR_NORTH, pFrame->pMB);
//chrg_north_pkg_decode(pFrame->pMB->payload, pFrame->len_msg, pSW);
pFrame->length = 0;
pFrame->len_msg = 0;
cnt++;
@@ -219,7 +543,6 @@ static int chrg_north_pickup_frame (struct rt_ringbuffer *rb,
break;
}
}
} else {
len_rb = rt_ringbuffer_data_len(rb);
int len_need = pFrame->len_msg - LEN_FRAME_HEAD;
@@ -240,8 +563,8 @@ static int chrg_north_pickup_frame (struct rt_ringbuffer *rb,
break;
}
}
len_rb = rt_ringbuffer_data_len(rb);
} while (len_rb >= LEN_FRAME_HEAD);
return cnt;
@@ -266,16 +589,16 @@ void chrg_north_thread_entry (void *data)
int len = 0;
struct chrg_tty_t *pTTY = RT_NULL;
struct chrg_north_t *pNOR = &chrgnorth;
//北向协议板线程体通道初始化为CH1,
chrg_north_switch(IDX_NOR_CH1);
pTTY = chrg_tty_create(pNOR->devname, BAUD_RATE_921600, 0, -1, 1);
pTTY = chrg_tty_create(pNOR->devname, 230400, 0, -1, 1);
if (RT_NULL == pTTY) {
LOG_E("tty can't create.");
return ;
}
chrg_tty_set_recv_tmo(pTTY, 100);
chrg_tty_set_recv_tmo(pTTY, 10);
if (chrg_tty_connect(pTTY) != RT_EOK) {
chrg_tty_destory(pTTY);
return ;
@@ -298,8 +621,9 @@ void chrg_north_thread_entry (void *data)
}
rt_ringbuffer_put(pNOR->rb, pNOR->rx_buf, len);
#if DEBUG_NORTH
LOG_HEX("recvN", 32, pNOR->rx_buf, len);
#endif
if (1 == pNOR->frame.findhead) {
if (rt_tick_get() >= pNOR->frame.last_tick + 100) { // 100ms
pNOR->frame.findhead = 0; // reset
@@ -309,7 +633,6 @@ void chrg_north_thread_entry (void *data)
chrg_north_pickup_frame(pNOR->rb, &pNOR->frame, pNOR->idx);
}
}
@@ -333,4 +656,3 @@ MSH_CMD_EXPORT(north_ch, north channel select);
#endif
+69 -8
View File
@@ -11,9 +11,8 @@
#define __CHRG_NORTH_H__
#include <rtthread.h>
#include "chrg_tty.h"
#include "chrg_source.h"
#include "chrg_tty.h"
#include "chrg_sink.h"
#include "chrg_def.h"
@@ -22,15 +21,21 @@
#define LEN_FRAME_HEAD (3) // [帧长, 0x00, id]
#define MIN_FRAME_LENGTH (5) // 帧最短5字节
#define WORK_MIN_VOLT 3000 // 工作电压下限,单位mV
#define DEBUG_NORTH 0x00 // 0 = 关闭,1 = 开启
#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
IDX_NOR_CH1 = IDX_CH1, // J3
IDX_NOR_CH2 = IDX_CH2, // J4
IDX_NOR_CH3 = IDX_CH3, // J9
IDX_NOR_CH4 = IDX_CH4, // J10
TOTAL_NOR_CHS
TOTAL_NOR_CHS
} eIDX_NOR_CH;
@@ -38,6 +43,60 @@ struct chrg_switch_t {
eIDX_ID id;
struct chrg_src_t source;
struct chrg_sink_t sink;
rt_uint8_t protoCmd; // 协议类型
rt_uint8_t sub; //状态机步骤
rt_uint8_t show_step; // 显示步骤标志位,0-各项参数,1-显示电压电流,
rt_uint8_t continue_flag;
rt_uint8_t CV_mode; //恒压恒流
rt_uint8_t change_flag; //正在调整功率标志位
rt_uint16_t Now_voltage; // 当前电压 mV
rt_uint16_t Now_current; // 当前电流 mA
rt_uint16_t VZ;
rt_uint16_t VF;
};
//校准结构体
//#define ModbusRTU_Trim_Start 0x01 //进入校准模式
//#defin ModbusRTU_Trim_Stop 0x02 //退出校准模式
#define ModbusRTU_Volt_CAL_K_H 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_H 0x2F //2F-30 电流校准K值
#define ModbusRTU_Current_CAL_K_L 0x30
#define ModbusRTU_Current_CAL_B 0x31 //31 电流校准B值
#define ModbusRTU_SourceCurrent_CAL_K_H 0x32 //32-33 电流校准K值
#define ModbusRTU_SourceCurrent_CAL_K_L 0x33
#define ModbusRTU_SourceCurrent_CAL_B 0x34 //34 电流校准B值
#define ModbusRTU_Trim_Zero_CAL 0x35 //35 校准零点,写入后会将电压电流都校准到0,读取时会返回当前的零点值
#define ModbusRTU_Trim_CRC_CAL 0x36 //36 校准CRC校验,写入后会将之前的校准数据生效,读取时会返回当前的CRC校验值
#define ModbusRTU_CAL_WriteEnable_ADD 0x37 //使能写入FLASH的地址
#define ModbusRTU_CAL_WriteValue 0x4361 //写入FALSH的魔数
#define ModbusRTU_CAL_WriteRecovery 0x38 //使能写入出厂数据区域;0x5763
#define ModbusRTU_CAL_WriteRecovery_Value 0x5763 //写入FALSH的魔数
#define ModbusRTU_CAL_ReadRecovery 0x39 //使能读出;将出厂数据读到当前的bank中,并更新6个参数
#define MODE_VOLT_CAL 0x01
#define MODE_CURR_CAL 0x02
#define MODE_SOURCE_CURR_CAL 0x03
#define MODE_ZERO_CAL 0x04
struct chrg_trim {
rt_uint16_t trim_volt_k_H; // 校准电压值高16位 mV
rt_uint16_t trim_volt_k_L; // 校准电压值低16位 mV
rt_int16_t trim_volt_b; // 校准电压值b mV
rt_uint16_t trim_curr_k_H; // 校准电流值高16位 mA
rt_uint16_t trim_curr_k_L; // 校准电流值低16位 mA
rt_int16_t trim_curr_b; // 校准电流值b mA
rt_uint16_t trim_source_curr_k_H; // 校准电源电流值高16位 mA
rt_uint16_t trim_source_curr_k_L; // 校准电源电流值低16位 mA
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则写出场数据区
};
struct chrg_north_t {
@@ -46,13 +105,14 @@ struct chrg_north_t {
struct chrg_tty_t *tty;
struct rt_ringbuffer *rb;
struct pickup_info_t frame;
struct chrg_trim trim[TOTAL_NOR_CHS];
rt_uint8_t rx_buf[SIZE_BUF_TTY];
rt_uint8_t free_flag;
rt_uint8_t enable[TOTAL_NOR_CHS]; // 通路使能
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;
@@ -86,7 +146,8 @@ extern int chrg_north_send (rt_uint8_t *data, rt_size_t length);
-
*****************************************************************/
extern void chrg_north_thread_entry (void *data);
extern rt_uint8_t On_Flag2;
extern rt_bool_t Set_Pro_Flag;
#endif
+456 -126
View File
@@ -20,11 +20,10 @@
#include "chrg_north.h"
#include "chrg_switch.h"
#include "chrg_utils.h"
#include "chrg_rel.h"
#include "chrg_wdt.h"
#define LOG_TAG "chrg.rollnor"
#include <rtdbg.h>
const rt_base_t sw_uart[TOTAL_NOR_CHS] = {
IDX_GPO_UART_SW1,
IDX_GPO_UART_SW2,
@@ -35,8 +34,166 @@ const rt_base_t sw_uart[TOTAL_NOR_CHS] = {
struct chrg_rollnor_t chrgrollnor = {
.run = RUN_CONSOLE, // RUN_AUTO,
.ch = IDX_NOR_CH1,
// .Set_Role = ID_SINK,
// .group = 0,
};
/*****************************************************************
sink_fill_pd_buf
PD指令的5字节数据缓冲区
pd_val: 0xC1/0xF8/0xFB
pd_volt: mV16
pd_curr: mA16
buf:
buf: 5
0: -1:
*****************************************************************/
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)
{
// 参数合法性校验
if (buf == RT_NULL) {
rt_kprintf("sink_fill_pd_buf: buf is a null pointer!\n");
return -1;
}
// 先清空缓冲区(默认全0
rt_memset(buf, 0, 5);
// 按协议类型填充buf
switch(pd_val) {
// 标准/QC2.0/QC3.0/FCP(仅电压,第五位=电压)
case 0xFE: // 标准协议
case 0xF8: // QC2.0协议
case 0xF6: // QC3.0协议
case 0xF2: // FCP协议
buf[0] = pd_volt / 100; // 第5字节=电压(0.1V)
buf[1] = pd_curr / 100; // 第6字节=电流(0.1A)
#if PRO_TEST_DEBUG
rt_kprintf("type: %02X, Voltage(0.1V)=%d\n", pd_val, pd_volt/100);
rt_kprintf("type: %02x, Curr(0.1A)=%d\n",pd_curr,pd_curr/100);
#endif
break;
// PDO/PPS/PD3.1/UFCS/AVS(组号+电压+电流)
case 0xFC: // PPS手动/自动
case 0xE3: // AVS协议
buf[0] = group; // 第5字节=组号(默认0
buf[1] = (pd_volt >> 8) & 0xFF; // 第6字节=电压高8位(mV)
buf[2] = pd_volt & 0xFF; // 第7字节=电压低8位(mV)
buf[3] = (pd_curr >> 8) & 0xFF; // 第8字节=电流高8位(mA)
buf[4] = pd_curr & 0xFF; // 第9字节=电流低8位(mA)
#if PRO_TEST_DEBUG
rt_kprintf("type: %02X, Group=0, Voltage=%d mV, Current=%d mA\n", pd_val, pd_volt, pd_curr);
#endif
break;
case 0xE0: // UFCS协议
case 0xE1: // PD3.1协议
case 0xFB: // PDO手动
buf[0] = 0x00; // 第5字节=组号(默认0
buf[1] = (pd_volt >> 8) & 0xFF; // 第6字节=电压高8位(mV)
buf[2] = pd_volt & 0xFF; // 第7字节=电压低8位(mV)
buf[3] = (pd_curr >> 8) & 0xFF; // 第8字节=电流高8位(mA)
buf[4] = pd_curr & 0xFF; // 第9字节=电流低8位(mA)
#if PRO_TEST_DEBUG
rt_kprintf("type: %02X, Group=0, Voltage=%d mV, Current=%d mA\n", pd_val, pd_volt, pd_curr);
#endif
break;
// SCP/VIVO/传音(电压+电流)
case 0xF3: // SCP协议
case 0xFD: // VIVO协议
case 0xF7: // 传音/TFC协议
buf[0] = (pd_volt >> 8) & 0xFF; // 第6字节=电压高8位(mV)
buf[1] = pd_volt & 0xFF; // 第7字节=电压低8位(mV)
buf[2] = (pd_curr >> 8) & 0xFF; // 第8字节=电流高8位(mA)
buf[3] = pd_curr & 0xFF; // 第9字节=电流低8位(mA)
buf[4] = 0;
#if PRO_TEST_DEBUG
rt_kprintf("type: %02X, Voltage=%d mV, Current=%d mA\n", pd_val, pd_volt, pd_curr);
#endif
break;
// VOOC(无参数)
case 0xE2: // VOOC协议
#if PRO_TEST_DEBUG
rt_kprintf("type: VOOC(0xE2), No parameters\n");
#endif
break;
case 0xF9: // AFC协议
{
// 1. 电压转HEX
rt_uint8_t volt_hex = 0;
if (pd_volt >= 5000 && pd_volt <= 20000) { // 电压范围:5V(5000mV)~20V(20000mV)
rt_uint8_t volt_v = pd_volt / 1000; // 转成V5000mV→5V
volt_hex = volt_v - 5; // 5V对应020V对应150xF
} else {
#if PRO_TEST_DEBUG
rt_kprintf("AFC VOLT ERROR VOLT=:%d mV Set 5000~20000\n", pd_volt);
#endif
return -1;
}
// 2. 电流转HEX
rt_uint8_t curr_hex = 0;
if (pd_curr >= 750 && pd_curr <= 3000) { // 电流范围:0.75A(750mA)~3.0A(3000mA)
rt_uint16_t curr_ma_step = (pd_curr - 750) / 150; // 步长150mA0.75→1.5→...→3.0
curr_hex = curr_ma_step; // 0.75A对应03.0A对应150xF
rt_kprintf("curr_ma_step = %d",curr_ma_step);
} else {
#if PRO_TEST_DEBUG
rt_kprintf("AFC CURR ERROR%d mA SET 750~3000 \n", pd_curr);
#endif
return -1;
}
// 3. 合并电压Hex(高4位)和电流Hex(低4位)→ 填充第五字节
buf[0] = (volt_hex << 4) | curr_hex;
rt_kprintf("type: AFC(0xF9), Voltage=%d V, Current=%.2f A, volaue=0x%X\n",
pd_volt/1000, pd_curr/1000.0, buf[0]);
}
break;
// 未知类型
default:
// rt_kprintf("Unknown fast charge type: %02X, Parameters cleared\n", pd_val);
break;
}
return 0;
}
rt_uint16_t v1=0,v2=0;
//电源关闭
void chrg_nor_source_stop(struct chrg_switch_t *pSW,rt_uint8_t idx,rt_uint8_t *enable){
switch(pSW->source.Stop_step_flag){
case 0:
chrg_set_sou_reg((eIDX_SOU_CH)idx, REG_WORK, WORK_STOP);
pSW->source.Stop_step_flag = 1;
break;
case 1: // 停止工作
chrg_set_sou_reg((eIDX_SOU_CH)idx, REG_WORK, WORK_STOP);
pSW->source.Stop_step_flag = 2;
break;
case 2: // 关闭北向继电器
chrg_nor_sw_rel((eIDX_NOR_CH)idx,0);
pSW->source.Stop_step_flag = 3;
break;
case 3: // 状态2:已执行完停止操作,清空标志位
pSW->source.Set_CV_Flag = 0;
if(pSW->source.change_sink_Flag == 1){
pSW->source.change_sink_Flag = 0;
// chrg_com_sink_on(idx,pSW,enable);
}else{
*enable = 0;
}
break;
default:
pSW->source.Stop_step_flag = 0;
break;
}
}
/*****************************************************************
chrg_roll_nor_sw_uart
@@ -60,89 +217,42 @@ static void chrg_roll_nor_sw_uart (eIDX_NOR_CH ch, eIDX_ID id)
}
static int chrg_roll_nor_cmd (struct chrg_rollnor_t *pROLL)
//设置负载协议
void chrg_roll_nor_sink_pro_set(struct chrg_switch_t *pSW)
{
if (RT_NULL == pROLL) {
return -1;
}
chrg_north_switch((eIDX_NOR_CH)pROLL->ch);
if (1 == pROLL->type) {
chrg_roll_nor_sw_uart((eIDX_NOR_CH)pROLL->ch, ID_SOURCE);
switch (pROLL->sub) {
case IDX_GET_SOURCE_VC: {
source_get_vc(5000, 1000);
}
break;
case IDX_GET_SOURCE_PD: {
source_get_pd();
}
break;
case IDX_SET_SOURCE_PD: {
source_set_pd(pROLL->pd, pROLL->src, pROLL->pps,
pROLL->max_vol, pROLL->min_vol, pROLL->max_curr);
}
break;
case IDX_SET_SOURCE_CCLVL: {
source_set_cc_lvl(pROLL->cc_level);
}
break;
default:
return -1;
break;
}
} else if (0 == pROLL->type) {
chrg_roll_nor_sw_uart((eIDX_NOR_CH)pROLL->ch, ID_SINK);
switch (pROLL->sub) {
case IDX_GET_SINK_VC: {
sink_get_vc(pROLL->voltage, pROLL->current);
}
break;
case IDX_GET_SINK_PD: {
sink_get_pd();
}
break;
case IDX_SET_SINK_PD: {
rt_uint8_t buf[5] = {0};
sink_set_pd(pROLL->pd, buf);
}
break;
case IDX_SET_SINK_CCLINE: {
sink_set_cc_line(pROLL->cc_line);
}
break;
case IDX_SET_SINK_CCLVL: {
sink_set_cc_lvl(pROLL->cc_level);
}
break;
default:
return -1;
}
} else {
return -1;
}
return 0;
rt_uint8_t buf[6] = {0};
sink_fill_pd_buf(pSW->sink.Pro_Group,pSW->sink.protocol,pSW->sink.pro_loadv,pSW->sink.pro_loadc,buf);
sink_set_pd(pSW->sink.protocol,buf);
#if DEBUG_NORTH
rt_kprintf("set_pro\r\n");
#endif
}
//设置电源协议
void chrg_roll_nor_source_pro_set(struct chrg_switch_t *pSW){
if(pSW->source.Set_Pro_Flag == 1){
pSW->source.Set_Pro_Flag = 0;
if(pSW->source.LCD_Set_Pro_Flag==1){
source_set_pd(pSW->source.protocol,0,0,pSW->source.vc.set_voltage,0,pSW->source.vc.set_current);
}
else if(pSW->source.LCD_Set_Pro_Flag==2){
source_set_pd_com(pSW->source.protocol,pSW->source.pro_gear_idx);
}
else if(pSW->source.LCD_Set_Pro_Flag==3){
source_set_pd_new_com(pSW->source.protocol,pSW);
}
}else {
pSW->sub = IDX_GET_SOURCE_VC;
}
}
static int chrg_roll_nor_parse (struct chrg_rollnor_t *pROLL, rt_uint8_t *data)
{
if ((RT_NULL == pROLL)||(RT_NULL == data)) {
return -1;
}
chrg_north_switch(IDX_NOR_CH1);
// 读取北向全局结构体中当前通道的Source/Sink参数
struct chrg_switch_t *pSW = &chrgnorth.sw[pROLL->ch];
if (1 == pROLL->type) {
switch (pROLL->sub) {
case IDX_GET_SOURCE_VC: {
@@ -171,9 +281,10 @@ static int chrg_roll_nor_parse (struct chrg_rollnor_t *pROLL, rt_uint8_t *data)
}
} else if (0 == pROLL->type) {
chrg_roll_nor_sw_uart(IDX_NOR_CH1,ID_SINK);
switch (pROLL->sub) {
case IDX_GET_SINK_VC: {
sink_get_vc(pSW->sink.pro_loadv,pSW->sink.pro_loadc);
}
break;
@@ -206,7 +317,79 @@ static int chrg_roll_nor_parse (struct chrg_rollnor_t *pROLL, rt_uint8_t *data)
return 0;
}
static int chrg_roll_nor_cmd (struct chrg_rollnor_t *pROLL)
{
if (RT_NULL == pROLL) {
return -1;
}
return 0;
}
void chrg_roll_nor_set(rt_uint8_t ch, struct chrg_switch_t *pSW,rt_uint8_t *enable)
{
if(pSW->id==ID_SOURCE){ //电源
chrg_roll_nor_sw_uart((eIDX_NOR_CH)ch, ID_SOURCE);
switch(pSW->sub){
case IDX_SET_SOURCE_ID: //角色
chrg_set_eload_source(ch,pSW);
if(pSW->continue_flag)
pSW->sub = IDX_SET_SOURCE_CC_SET;
// rt_kprintf("set_start\r\n");
break;
case IDX_SET_SOURCE_CC_SET:
source_set_cc_choose(pSW->source.cc_set);
pSW->sub = IDX_SET_SOURCE_CV;
break;
case IDX_SET_SOURCE_CV: //恒压恒流
pSW->sub = IDX_SER_SOURCE_VOLT;
break;
case IDX_SER_SOURCE_VOLT://电压
chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_VOLTAGE_OUT+1, 0);
pSW->sub = IDX_SER_SOURCE_CURR;
break;
case IDX_SER_SOURCE_CURR://电流
chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_CURRENT_OUT+1, pSW->source.protective_curr);
pSW->sub = IDX_SET_SOURCE_WORK;
break;
case IDX_SET_SOURCE_WORK:
chrg_sou_work(ch,pSW);
break;
case IDX_SET_SOURCE_PD:
chrg_roll_nor_source_pro_set(pSW);
pSW->source.On_Flag = 1;
break;
case IDX_GET_SOURCE_VC:
source_get_vc(pSW->source.vc.set_voltage, pSW->source.vc.set_current);
break;
case IDX_SET_SOURCE_CCLVL:
source_set_cc_lvl(pSW->source.vol_lvl);
break;
case IDX_SET_SOURCE_STOP_STATE:
chrg_nor_source_stop(pSW,ch,enable);
break;
default:
break;
}
}else{
chrg_roll_nor_sw_uart((eIDX_NOR_CH)ch, ID_SINK);
switch(pSW->sub){
case IDX_GET_SINK_VC: //查询
sink_get_vc(pSW->sink.pro_loadv,pSW->sink.pro_loadc);
break;
case IDX_SET_SINK_CCLINE: //CC线选择
sink_set_cc_line(pSW->sink.cc_set);
pSW->sub = IDX_SET_SINK_PD;
break;
case IDX_SET_SINK_CCLVL: //CC电平
sink_set_cc_lvl(pSW->sink.cc_lvl);
break;
case IDX_SET_SINK_PD:
chrg_roll_nor_sink_pro_set(pSW);
pSW->sub = IDX_GET_SINK_VC;
break;
}
}
}
/*****************************************************************
chrg_roll_nor_thread_entry
@@ -232,41 +415,36 @@ void chrg_roll_nor_thread_entry (void *data)
struct chrg_north_t *pNOR = &chrgnorth;
struct chrg_switch_t *pSW = RT_NULL;
struct mb_msg_t *pMB_R = RT_NULL;
for (i = 0; i < TOTAL_NOR_CHS; i++) {
chrg_roll_nor_sw_uart((eIDX_NOR_CH)i, ID_SINK);
}
while (1) {
chrg_wdt_feed();
rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
run = pROLL->run;
rt_mutex_release(pTHR->mutex);
rt_mutex_release(pTHR->mutex);
switch (run) {
case RUN_AUTO: {
idx = index%TOTAL_NOR_CHS;
if (0 == pNOR->enable[idx]) {
index++;
rt_thread_mdelay(10);
rt_thread_mdelay(2);
continue;
} else {
chrg_led_flashing(IDX_LED2, TIMES_ONE, PULSE_TIME*2, PULSE_TIME*2);
chrg_north_switch((eIDX_NOR_CH)idx);
chrgnorth.idx = idx;
pROLL->idx = idx;
pSW = &pNOR->sw[idx];
if (ID_SOURCE == pSW->id) {
chrg_roll_nor_sw_uart((eIDX_NOR_CH)idx, ID_SOURCE);
source_get_vc(pSW->source.voltage, pSW->source.current);
} else if (ID_SINK == pSW->id) {
chrg_roll_nor_sw_uart((eIDX_NOR_CH)idx, ID_SINK);
sink_get_vc(pSW->sink.loadv, pSW->sink.loadc);
rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
if(pNOR->north_mode == 0){
chrg_roll_nor_set(pROLL->idx,pSW,&pNOR->enable[idx]);
}
//rt_kprintf("Nor[%d].%d\r\n", idx, pSW->id);
if(pNOR->north_mode == 1){
chrg_roll_trim_set(pROLL->idx,pNOR);
}
rt_mutex_release(pTHR->mutex);
}
index++;
}
break;
@@ -275,15 +453,18 @@ void chrg_roll_nor_thread_entry (void *data)
chrg_roll_nor_cmd(pROLL);
}
break;
case RUN_CONSOLE: {
chrg_roll_nor_cmd(pROLL);
}
break;
case RUN_COM:
// {
// chrg_roll_nor_cmd(pROLL);
// }
break;
case RUN_NONE:
default:
rt_thread_mdelay(100);
rt_thread_mdelay(5);
continue;
break;
}
@@ -294,7 +475,7 @@ void chrg_roll_nor_thread_entry (void *data)
if (crc == pMB_R->payload[pMB_R->length-1]) { // 数据正确
if (RUN_AUTO != run) { // 恢复自动轮巡
rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
//todo pROLL->run = RUN_AUTO;
pROLL->run = RUN_AUTO;
rt_mutex_release(pTHR->mutex);
} else {
chrg_roll_nor_parse(pROLL, pMB_R->payload);
@@ -313,11 +494,12 @@ void chrg_roll_nor_thread_entry (void *data)
pMB_R = RT_NULL;
}
rt_thread_mdelay(200); // 间隔 200ms
rt_thread_mdelay(20); // 间隔 200ms
} else {
if (RUN_AUTO != run) { // 非自动轮巡
rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
//todo pROLL->run = RUN_AUTO; // 切换会自动轮巡
//todo
pROLL->run = RUN_AUTO; // 切换会自动轮巡
rt_mutex_release(pTHR->mutex);
}
}
@@ -357,7 +539,7 @@ static int sink (int argc, char **argv)
if (strcmp(argv[3], "vc") == 0) {
if (0 == gset) {
pROLL->sub = IDX_GET_SINK_VC;
pROLL->sub = IDX_SET_SINK_WORK_STATE;
} else {
ret = -1;
rt_kprintf("sink vc can't set.\r\n");
@@ -367,6 +549,7 @@ static int sink (int argc, char **argv)
if (0 == gset) {
pROLL->sub = IDX_GET_SINK_PD;
} else {
//长度
if (argc != 5) {
rt_kprintf("help : %s set 0-3 ccline 0-3.\r\n", argv[0]);
return -1;
@@ -471,12 +654,15 @@ static int source (int argc, char **argv)
pROLL->sub = IDX_GET_SOURCE_PD;
} else {
if (argc != 5) {
//if (argc != 5) {
rt_kprintf("help : %s set 0-3 pd 0-.\r\n", argv[0]);
return -1;
// sink_set_pd
} else { // sink set 0 pd 0
int type = atoi(argv[4]);
//协议
pROLL->pd = (rt_uint8_t)type;
//子命令
pROLL->sub = IDX_SET_SOURCE_PD;
}
}
@@ -516,29 +702,173 @@ static int source (int argc, char **argv)
MSH_CMD_EXPORT(source, north source test);
static int north_run (int argc, char **argv)
{
if (2 != argc) {
rt_kprintf("help : %s start|stop\r\n", argv[0]);
return -1;
}
struct chrg_rollnor_t *pROLL = &chrgrollnor;
if (rt_strcmp(argv[1], "start") == 0) {
pROLL->run = RUN_AUTO;
} else if (rt_strcmp(argv[1], "stop") == 0) {
pROLL->run = RUN_NONE;
} else {
rt_kprintf("help : %s start|stop\r\n", argv[0]);
return -1;
}
return 0;
}
MSH_CMD_EXPORT(north_run, north auto run);
#endif
//校准CRC计算
rt_uint16_t chrg_trim_crc(rt_uint8_t ch, struct chrg_north_t *pNOR)
{
struct chrg_trim *pTrim = &pNOR->trim[ch];
rt_uint8_t buf[22];
int idx = 0;
buf[idx++] = (pTrim->trim_volt_k_H >> 8) & 0xFF;
buf[idx++] = pTrim->trim_volt_k_H & 0xFF;
buf[idx++] = (pTrim->trim_volt_k_L >> 8) & 0xFF;
buf[idx++] = pTrim->trim_volt_k_L & 0xFF;
buf[idx++] = (pTrim->trim_volt_b >> 8) & 0xFF;
buf[idx++] = pTrim->trim_volt_b & 0xFF;
buf[idx++] = (pTrim->trim_curr_k_H >> 8) & 0xFF;
buf[idx++] = pTrim->trim_curr_k_H & 0xFF;
buf[idx++] = (pTrim->trim_curr_k_L >> 8) & 0xFF;
buf[idx++] = pTrim->trim_curr_k_L & 0xFF;
buf[idx++] = (pTrim->trim_curr_b >> 8) & 0xFF;
buf[idx++] = pTrim->trim_curr_b & 0xFF;
buf[idx++] = (pTrim->trim_source_curr_k_H >> 8) & 0xFF;
buf[idx++] = pTrim->trim_source_curr_k_H & 0xFF;
buf[idx++] = (pTrim->trim_source_curr_k_L >> 8) & 0xFF;
buf[idx++] = pTrim->trim_source_curr_k_L & 0xFF;
buf[idx++] = (pTrim->trim_source_curr_b >> 8) & 0xFF;
buf[idx++] = pTrim->trim_source_curr_b & 0xFF;
buf[idx++] = (pTrim->trim_zero >> 8) & 0xFF;
buf[idx++] = pTrim->trim_zero & 0xFF;
return mb_crc16(buf, 20);
}
//电源校准设置
void chrg_trim_set_volt(rt_uint8_t ch,struct chrg_north_t *pNOR){
struct chrg_trim *pTRIM = &pNOR->trim[ch];
switch(pTRIM->trim_step){
case 0:
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_Volt_CAL_K_H, pTRIM->trim_volt_k_H);
break;
case 1:
break;
case 2:
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_Volt_CAL_K_L, pTRIM->trim_volt_k_L);
break;
case 3:
break;
case 4:
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_Volt_CAL_B, pTRIM->trim_volt_b);
break;
pNOR->north_mode = 0;
break;
}
pTRIM->trim_step++;
}
//电流校准设置
void chrg_trim_set_curr(rt_uint8_t ch,struct chrg_north_t *pNOR){
struct chrg_trim *pTRIM = &pNOR->trim[ch];
switch(pTRIM->trim_step){
case 0:
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_Current_CAL_K_H, pTRIM->trim_curr_k_H);
break;
case 1:
break;
case 2:
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_Current_CAL_K_L, pTRIM->trim_curr_k_L);
break;
case 3:
break;
case 4:
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_Current_CAL_B, pTRIM->trim_curr_b);
pNOR->north_mode = 0;
break;
}
pTRIM->trim_step++;
}
//电源校准设置
void chrg_trim_set_source_curr(rt_uint8_t ch,struct chrg_north_t *pNOR){
struct chrg_trim *pTRIM = &pNOR->trim[ch];
rt_uint16_t crc = 0;
switch(pTRIM->trim_step){
case 0:
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_SourceCurrent_CAL_K_H, pTRIM->trim_source_curr_k_H);
break;
case 1:
break;
case 2:
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_SourceCurrent_CAL_K_L, pTRIM->trim_source_curr_k_L);
break;
case 3:
break;
case 4:
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_SourceCurrent_CAL_B, pTRIM->trim_source_curr_b);
break;
case 5:
break;
case 6:
crc = chrg_trim_crc(ch, pNOR);
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_Trim_CRC_CAL, crc);
rt_kprintf("crc=%04X\n",crc);
break;
case 7:
break;
case 8:
if(pTRIM->trim_enable_flag == 0){
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_CAL_WriteEnable_ADD,ModbusRTU_CAL_WriteValue);
}else{
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_CAL_WriteRecovery,ModbusRTU_CAL_WriteRecovery_Value);
}
pNOR->north_mode = 0;
break;
}
pTRIM->trim_step++;
}
//校准飘零设置
void chrg_trim_set_zero(rt_uint8_t ch,struct chrg_north_t *pNOR){
struct chrg_trim *pTRIM = &pNOR->trim[ch];
rt_uint16_t crc = 0;
switch(pTRIM->trim_step){
case 0:
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_Trim_Zero_CAL, pTRIM->trim_zero);
break;
case 1:
break;
case 2:
crc = chrg_trim_crc(ch, pNOR);
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_Trim_CRC_CAL, crc);
break;
case 3:
break;
case 4:
if(pTRIM->trim_enable_flag == 0){
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_CAL_WriteEnable_ADD,ModbusRTU_CAL_WriteValue);
}else{
chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_CAL_WriteRecovery,ModbusRTU_CAL_WriteRecovery_Value);
}
pNOR->north_mode = 0;
break;
}
pTRIM->trim_step++;
}
//校准设置
void chrg_roll_trim_set(rt_uint8_t ch, struct chrg_north_t *pNOR){
struct chrg_trim *pTRIM = &pNOR->trim[ch];
switch(pTRIM->trim_mode){
case MODE_VOLT_CAL:
chrg_trim_set_volt(ch, pNOR);
break;
case MODE_CURR_CAL:
chrg_trim_set_curr(ch, pNOR);
break;
case MODE_SOURCE_CURR_CAL:
chrg_trim_set_source_curr(ch, pNOR);
break;
case MODE_ZERO_CAL:
chrg_trim_set_zero(ch, pNOR);
break;
}
}
+23 -6
View File
@@ -13,19 +13,34 @@
#include <rtthread.h>
#define THR_NAME_ROLL_NOR "thr.rollnor"
#define STATE_WORKING 0x03//运行标志位
enum {
IDX_GET_SOURCE_VC = 0,
IDX_GET_SOURCE_PD,
IDX_SET_SOURCE_PD,
IDX_SET_SOURCE_ID,
IDX_SET_SOURCE_CC_SET,
IDX_SER_SOURCE_VOLT,
IDX_SER_SOURCE_CURR,
IDX_SET_SOURCE_WORK,
IDX_SET_SOURCE_CCLVL,
IDX_SET_SOURCE_CV,
IDX_SET_SOURCE_STOP_STATE,
IDX_GET_SINK_VC,
IDX_GET_SINK_PD,
IDX_SET_SINK_VOLT,
IDX_SET_SINK_CURR,
IDX_SET_SINK_PD,
IDX_SET_SINK_CCLINE,
IDX_SET_SINK_CCLVL,
IDX_SET_SINK_ID,
IDX_SET_SINK_VOLT_ON,
IDX_SET_SINK_WORK,
IDX_SET_SINK_CV,
IDX_SET_SINK_WORK_STATE,
IDX_SET_SINK_STOP_TEST,//停止负载测试
IDX_SET_SINK_STORP_WAIT,
};
struct chrg_rollnor_t {
@@ -44,8 +59,7 @@ struct chrg_rollnor_t {
rt_uint8_t pps;
rt_uint16_t voltage; // 触发插入时,当前电压 mV
rt_uint16_t current; // 触发插入时,当前电流 mA
rt_uint16_t max_vol; // 触发插入时,最大电压 mV
rt_uint16_t min_vol; // 触发插入时,最小电压 mV
rt_uint16_t max_curr; // 触发插入时,最大电流 mA
@@ -64,7 +78,10 @@ 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);
#define sink_time 3
#endif
+515 -32
View File
@@ -1,3 +1,373 @@
// /****************************************************************************
// 文件名称 : chrg_roll_sou.c
// 完成日期 :
// 当前版本号 : V1.0
// 主要功能 : 实现南向通信轮巡请求命令。以独立线程处理。
// 版本历史 : 创建原始版本
// 说明 :
// ******************************************************************************/
// #include <stdlib.h>
// #include <string.h>
// #include <rtthread.h>
// #include "chrg_def.h"
// #include "chrg_led.h"
// #include "chrg_thread.h"
// #include "chrg_roll_sou.h"
// #include "chrg_eload.h"
// #include "chrg_utils.h"
// #define LOG_TAG "chrg.rollsou"
// #include <rtdbg.h>
// struct chrg_rollsou_t chrgrollsou = {
// .run = RUN_AUTO,
// .ch = IDX_SOU_CH1,
// .part = MB_R_PART1,
// .mode = 0,
// };
// #define SOU_CMD_QUEUE_SIZE 4
// struct chrg_sou_cmd_t {
// eIDX_SOU_CH ch;
// rt_uint16_t reg;
// rt_uint16_t value;
// };
// static struct chrg_sou_cmd_t sou_cmd_queue[SOU_CMD_QUEUE_SIZE];
// static rt_uint8_t sou_cmd_head = 0;
// static rt_uint8_t sou_cmd_tail = 0;
// static rt_uint8_t sou_cmd_count = 0;
// static void sou_cmd_enqueue(eIDX_SOU_CH ch, rt_uint16_t reg, rt_uint16_t value)
// {
// if (sou_cmd_count < SOU_CMD_QUEUE_SIZE) {
// sou_cmd_queue[sou_cmd_tail].ch = ch;
// sou_cmd_queue[sou_cmd_tail].reg = reg;
// sou_cmd_queue[sou_cmd_tail].value = value;
// sou_cmd_tail = (sou_cmd_tail + 1) % SOU_CMD_QUEUE_SIZE;
// sou_cmd_count++;
// } else {
// LOG_W("sou command queue full, drop command\n");
// }
// }
// static int sou_cmd_dequeue(struct chrg_sou_cmd_t *cmd)
// {
// if (sou_cmd_count == 0) {
// return -1;
// }
// cmd->ch = sou_cmd_queue[sou_cmd_head].ch;
// cmd->reg = sou_cmd_queue[sou_cmd_head].reg;
// cmd->value = sou_cmd_queue[sou_cmd_head].value;
// sou_cmd_head = (sou_cmd_head + 1) % SOU_CMD_QUEUE_SIZE;
// sou_cmd_count--;
// return 0;
// }
// static int sou_cmd_exists(void)
// {
// return sou_cmd_count > 0;
// }
// /*****************************************************************
// 函数名称: chrg_set_sou_reg
// 函数描述: 南向通道设置寄存器请求命令
// 输入参数: idx:通道 reg:寄存器地址 value:寄存器值
// 输出参数: -
// 返回说明: -
// 其它说明: -
// *****************************************************************/
// void chrg_set_sou_reg (eIDX_SOU_CH idx, rt_uint16_t reg, rt_uint16_t value)
// {
// struct chrg_thread_t *pTHR = &chrgthr[IDX_THR_ROLL_SOU];
// struct chrg_rollsou_t *pROLL = &chrgrollsou;
// rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
// sou_cmd_enqueue(idx, reg, value);
// pROLL->run = RUN_LCD;
// rt_mutex_release(pTHR->mutex);
// rt_kprintf("ch=:%d,reg=%02x,value=%02x\n",idx,reg,value);
// }
// /*****************************************************************
// 函数名称: chrg_send_sou_upadata_data
// 函数描述: 南向通道升级命令
// 输入参数: idx:通道 reg:寄存器地址 value:寄存器值
// 输出参数: -
// 返回说明: -
// 其它说明: -
// *****************************************************************/
// void chrg_send_sou_upadata_data (rt_uint8_t *buf,rt_uint16_t leng)
// {
// struct chrg_thread_t *pTHR = &chrgthr[IDX_THR_ROLL_SOU];
// struct chrg_rollsou_t *pROLL = &chrgrollsou;
// pROLL->updata_data = buf;
// pROLL->leng = leng;
// // rt_kprintf("idx=%d,reg=%02x,value=%02x\n",RUN_UPDATAidx,reg,value);
// rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
// pROLL->run = RUN_UPDATA;
// rt_mutex_release(pTHR->mutex);
// }
// ///*****************************************************************
// //函数名称: chrg_set_sou_more_reg
// //函数描述: 南向通道设置寄存器请求命令
// //输入参数: idx:通道 reg:寄存器地址 value:寄存器值 value2:第二个寄存器值
// //输出参数: -
// //返回说明: -
// //其它说明: -
// //*****************************************************************/
// //void chrg_set_sou_more_reg (eIDX_SOU_CH idx, rt_uint16_t reg, rt_uint16_t value,rt_uint16_t value2)
// //{
// // struct chrg_thread_t *pTHR = &chrgthr[IDX_THR_ROLL_SOU];
// // struct chrg_rollsou_t *pROLL = &chrgrollsou;
// // pROLL->more_reg_flag = 1; // 使用多寄存器标志位
// // pROLL->ch = idx;
// // pROLL->reg = reg;
// // pROLL->value = value;
// // pROLL->value2 = value2;
// // rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
// // pROLL->run = RUN_LCD;
// // rt_mutex_release(pTHR->mutex);
// //}
// /*****************************************************************
// 函数名称: chrg_roll_sou_thread_entry
// 函数描述: 南向通道轮巡请求数据线程体
// 输入参数: *data: 本线程信息
// 输出参数: -
// 返回说明: -
// 其它说明: -
// *****************************************************************/
// rt_uint8_t aaaaaa = 0;
// void chrg_roll_sou_thread_entry (void *data)
// {
// struct chrg_thread_t *pTHR = (struct chrg_thread_t *)data;
// if (RT_NULL == pTHR) {
// return ;
// }
// rt_uint8_t run = 0;
// rt_uint8_t index = 0, idx = 0;
// rt_err_t ret = RT_EOK;
// struct chrg_rollsou_t *pROLL = &chrgrollsou;
// struct chrg_thread_t *pTS = &chrgthr[IDX_THR_SOUTH];
// struct mb_msg_t *pMB_R = RT_NULL;
// rt_uint8_t number = 0;
// while (1) {
// /* 每轮先非阻塞排空积压消息,防止邮箱满导致 south 线程永久阻塞 */
// {
// rt_uint8_t drain_cnt = 0;
// struct mb_msg_t *pDrain = RT_NULL;
// while (drain_cnt < 8) {
// ret = rt_mb_recv(pTS->mb, (rt_uint32_t *)&pDrain, 0);
// if (ret != RT_EOK) break;
// if (pDrain != RT_NULL) {
// if (pDrain->payload != RT_NULL) rt_free(pDrain->payload);
// rt_free(pDrain);
// }
// drain_cnt++;
// }
// }
// rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
// run = pROLL->run;
// rt_mutex_release(pTHR->mutex);
// switch (run) {
// // rt_kprintf("-------- ROLL SOU TIME START \n --------");
// case RUN_AUTO: {
// if(pROLL->mode!=0){
// }else{
// idx = index%(TOTAL_SOU_CHS); // [0, 3]
// // rt_kprintf("start_idx = %d",idx);
// if (0 == chrgsouth.enable[idx]) { // 通道未启用
// index++;
// rt_thread_mdelay(5);
// continue;
// } else { // 通道启用
// chrg_led_flashing(IDX_LED3, TIMES_ONE, PULSE_TIME*2, PULSE_TIME*2);
// if (idx != (rt_uint8_t)pROLL->idx) {
// pROLL->idx = (eIDX_SOU_CH)idx;
// chrg_south_switch((eIDX_SOU_CH)idx);
// pROLL->part = MB_R_PART1;
// }
// chrg_eload_refresh(ID_ELOAD, pROLL->part);
// if (pROLL->part < TOTAL_MB_R) {
// //pROLL->part++;
// //if (pROLL->part > MB_R_PART1) { // 仅1条,若需轮巡全部,注释此条件
// index++;
// //}
// } else {
// index++;
// }
// }
// }
// }
// break;
// case RUN_LCD: {
// struct chrg_sou_cmd_t cmd;
// rt_uint8_t do_cmd = 0;
// rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
// if (sou_cmd_dequeue(&cmd) == 0) {
// do_cmd = 1;
// pROLL->ch = cmd.ch;
// }
// rt_mutex_release(pTHR->mutex);
// if (do_cmd) {
// chrg_south_switch(cmd.ch);
// chrg_eload_write_reg(ID_ELOAD, cmd.reg, cmd.value);
// }
// rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
// if (!sou_cmd_exists()) {
// pROLL->run = RUN_AUTO;
// }
// rt_mutex_release(pTHR->mutex);
// }
// break;
// case RUN_CONSOLE: {
// chrg_south_switch((eIDX_SOU_CH)pROLL->ch);
// chrg_eload_refresh(ID_ELOAD, pROLL->part);
// }
// break;
// case RUN_UPDATA:{
// chrg_south_switch((eIDX_SOU_CH)pROLL->ch);
// if(pROLL->send_flag==1){
// chrg_eload_send_ymodem_data(pROLL->updata_data,pROLL->leng);
// pROLL->send_flag = 0;
// }
// /* 升级模式不下发Modbus邮件,等待south线程捕获ymodem应答后继续 */
// rt_thread_mdelay(50);
// continue;
// }
// break;
// case RUN_COM: {
// chrg_south_switch((eIDX_SOU_CH)pROLL->ch);
// chrg_eload_write_reg(ID_ELOAD, pROLL->reg, pROLL->value);
// }
// break;
// case RUN_NONE:
// default:
// rt_thread_mdelay(5);
// continue;
// break;
// }
// ret = rt_mb_recv(pTS->mb, (rt_uint32_t *)&pMB_R, 100 ); // 超时 200ms
// if ((RT_EOK == ret)&&(RT_NULL != pMB_R)) { // 存在返回数据
// if (0 == mb_crc16(pMB_R->payload, pMB_R->length)) {
// if (RUN_AUTO != run) { // 恢复自动轮巡或继续执行待发命令
// rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
// pROLL->run = sou_cmd_exists() ? RUN_LCD : RUN_AUTO;
// rt_mutex_release(pTHR->mutex);
// }
// else { // 自动轮巡态,分析接收的数据
// #if DEBUG_SOUTH
// rt_kprintf("length = %d",pMB_R->length);
// #endif
// if(pMB_R->length!=43){//31修改成43,一共19个寄存器*2+4,多读了4位
// ret = rt_mb_recv(pTS->mb, (rt_uint32_t *)&pMB_R, 30); // 超时 200ms
// #if DEBUG_SOUTH
// rt_kprintf("ret = %d\n",ret);
// #endif
// if ((RT_EOK == ret)&&(RT_NULL != pMB_R)) { // 存在返回数据
// chrg_eload_parse(idx, pROLL->part, pMB_R->payload, pMB_R->length);
// }
// }
// else chrg_eload_parse(idx, pROLL->part, pMB_R->payload, pMB_R->length);
// }
// }
// else {
// LOG_E("crc failed.");
// }
// if (RT_NULL != pMB_R->payload) {
// rt_free(pMB_R->payload);
// pMB_R->payload = RT_NULL;
// }
// if (RT_NULL != pMB_R) {
// rt_free(pMB_R);
// pMB_R = RT_NULL;
// }
// // rt_thread_mdelay(200); // 间隔 20ms
// rt_thread_mdelay(10); // 间隔 200ms
// } else { // 设备应答超时
// if (RUN_AUTO != run) { // 非自动轮巡
// rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
// pROLL->run = sou_cmd_exists() ? RUN_LCD : RUN_AUTO; // 切换会自动轮巡或继续执行待发命令
// rt_mutex_release(pTHR->mutex);
// }
// }
// // rt_kprintf("-------- ROLL SOU TIME END\n --------");
// }
// }
// #if 1
// static int south_send(rt_uint8_t argc, char **argv)
// {
// int ch = 0, pt = 0;
// if (3 != argc) {
// rt_kprintf("help : %s [0-3] [0-1]\r\n", argv[0]);
// return -1;
// }
// ch = (rt_uint8_t)atoi(argv[1]);
// if ((ch < 0)||(ch >= TOTAL_SOU_CHS)) {
// rt_kprintf("help : %s [0-3] [0-1]\r\n", argv[0]);
// return -1;
// }
// pt = (rt_uint8_t)atoi(argv[2]);
// if ((pt < 0)||(pt >= TOTAL_MB_R)) {
// rt_kprintf("help : %s [0-3] [0-1]\r\n", argv[0]);
// return -1;
// }
// struct chrg_rollsou_t *pROLL = &chrgrollsou;
// pROLL->run = RUN_CONSOLE;
// pROLL->ch = (rt_uint8_t)ch;
// pROLL->part = (rt_uint8_t)pt;
// return 0;
// }
// MSH_CMD_EXPORT(south_send, south send test);
// static int south_run (int argc, char **argv)
// {
// if (2 != argc) {
// rt_kprintf("help : %s start|stop\r\n", argv[0]);
// return -1;
// }
// struct chrg_rollsou_t *pROLL = &chrgrollsou;
// if (rt_strcmp(argv[1], "start") == 0) {
// pROLL->run = RUN_AUTO;
// } else if (rt_strcmp(argv[1], "stop") == 0) {
// pROLL->run = RUN_NONE;
// } else {
// rt_kprintf("help : %s start|stop\r\n", argv[0]);
// return -1;
// }
// return 0;
// }
// MSH_CMD_EXPORT(south_run, south auto run);
// #endif
/****************************************************************************
: chrg_roll_sou.c
:
@@ -21,13 +391,38 @@
#define LOG_TAG "chrg.rollsou"
#include <rtdbg.h>
chrg_rollsou_com_t g_sou_com_batch = {0};
struct chrg_rollsou_t chrgrollsou = {
.run = RUN_AUTO,
.ch = IDX_SOU_CH1,
.part = MB_R_PART1,
};
//向通道批量缓存添加一条寄存器
int chrg_sou_com_batch_add_reg(eIDX_SOU_CH ch, rt_uint16_t reg, rt_uint16_t val)
{
if(ch >= TOTAL_SOU_CHS) return -1;
sou_com_batch_ch_t *pBatch = &g_sou_com_batch.ch[ch];
if(pBatch->reg_cnt >= SOU_COM_BATCH_REG_MAX)
{
LOG_E("sou com batch reg full");
return -2;
}
pBatch->reg_list[pBatch->reg_cnt] = reg;
pBatch->val_list[pBatch->reg_cnt] = val;
pBatch->reg_cnt++;
pBatch->pending = RT_TRUE;
return 0;
}
//启动批量下发(填充完影子结构体后调用)
void chrg_sou_com_sou_set(void)
{
struct chrg_thread_t *pTHR = &chrgthr[IDX_THR_ROLL_SOU];
struct chrg_rollsou_t *pROLL = &chrgrollsou;
pROLL->run = RUN_COM;
}
/*****************************************************************
chrg_set_sou_reg
@@ -51,6 +446,31 @@ void chrg_set_sou_reg (eIDX_SOU_CH idx, rt_uint16_t reg, rt_uint16_t value)
rt_mutex_release(pTHR->mutex);
}
/*****************************************************************
chrg_set_sou_reg
idx: reg: value:
-
-
-
*****************************************************************/
void chrg_set_sou_reg_com (eIDX_SOU_CH idx, rt_uint16_t reg, rt_uint16_t value)
{
struct chrg_thread_t *pTHR = &chrgthr[IDX_THR_ROLL_SOU];
struct chrg_rollsou_t *pROLL = &chrgrollsou;
pROLL->ch = idx;
pROLL->reg = reg;
pROLL->value = value;
rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
pROLL->run = RUN_COM;
rt_mutex_release(pTHR->mutex);
rt_kprintf("ch=:%d,reg=%02x,value=%02x\n",idx,reg,value);
}
/*****************************************************************
chrg_roll_sou_thread_entry
线
@@ -73,16 +493,16 @@ void chrg_roll_sou_thread_entry (void *data)
struct chrg_rollsou_t *pROLL = &chrgrollsou;
struct chrg_thread_t *pTS = &chrgthr[IDX_THR_SOUTH];
struct mb_msg_t *pMB_R = RT_NULL;
sou_com_batch_ch_t *pCurBatch = RT_NULL;
while (1) {
rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
run = pROLL->run;
rt_mutex_release(pTHR->mutex);
rt_uint8_t batch_ch = 0; // 缓存当前正在下发的批量通道
// rt_kprintf("------ROLL SOU START \n--------");
switch (run) {
case RUN_AUTO: {
idx = index%(TOTAL_SOU_CHS); // [0, 3]
if (0 == chrgsouth.enable[idx]) { // 通道未启用
index++;
rt_thread_mdelay(10);
@@ -94,14 +514,8 @@ void chrg_roll_sou_thread_entry (void *data)
chrg_south_switch((eIDX_SOU_CH)idx);
pROLL->part = MB_R_PART1;
}
chrg_eload_refresh(ID_ELOAD, pROLL->part);
if (pROLL->part < TOTAL_MB_R) {
pROLL->part++;
if (pROLL->part > MB_R_PART1) { // 仅1条,若需轮巡全部,注释此条件
index++;
}
} else {
index++;
}
}
@@ -114,6 +528,36 @@ void chrg_roll_sou_thread_entry (void *data)
}
break;
case RUN_COM:
{
pCurBatch = RT_NULL;
// 遍历查找有待下发批量任务的通道
for(idx = 0; idx < TOTAL_SOU_CHS; idx++)
{
if(g_sou_com_batch.ch[idx].pending == RT_TRUE)
{
pCurBatch = &g_sou_com_batch.ch[idx];
break;
}
}
// 无任何批量任务,切回自动轮巡
if(pCurBatch == RT_NULL)
{
rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
pROLL->run = RUN_AUTO;
rt_mutex_release(pTHR->mutex);
break;
}
// 切换当前通道串口
chrg_south_switch((eIDX_SOU_CH)idx);
batch_ch = idx;
// 发送当前下标寄存器
rt_uint16_t reg = pCurBatch->reg_list[pCurBatch->cur_idx];
rt_uint16_t val = pCurBatch->val_list[pCurBatch->cur_idx];
chrg_eload_write_reg(ID_ELOAD, reg, val);
}
break;
case RUN_CONSOLE: {
chrg_south_switch((eIDX_SOU_CH)pROLL->ch);
chrg_eload_refresh(ID_ELOAD, pROLL->part);
@@ -127,41 +571,80 @@ void chrg_roll_sou_thread_entry (void *data)
break;
}
ret = rt_mb_recv(pTS->mb, (rt_uint32_t *)&pMB_R, 200); // 超时 200ms
if ((RT_EOK == ret)&&(RT_NULL != pMB_R)) { // 存在返回数据
if (0 == mb_crc16(pMB_R->payload, pMB_R->length)) {
if (RUN_AUTO != run) { // 恢复自动轮巡
rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
pROLL->run = RUN_AUTO;
rt_mutex_release(pTHR->mutex);
} else { // 自动轮巡态,分析接收的数据
ret = rt_mb_recv(pTS->mb, (rt_uint32_t *)&pMB_R, 50);
if ((RT_EOK == ret)&&(RT_NULL != pMB_R))
{
if (0 == mb_crc16(pMB_R->payload, pMB_R->length))
{
if (RUN_AUTO != run)
{
if(run == RUN_COM)
{
// CRC校验成功,本条发送完成,下标+1,下发下一条
sou_com_batch_ch_t *pBatch = &g_sou_com_batch.ch[batch_ch];
pBatch->cur_idx++;
// 当前通道全部指令发完,清除pending标记
if(pBatch->cur_idx >= pBatch->reg_cnt)
{
pBatch->pending = RT_FALSE;
pBatch->cur_idx = 0;
pBatch->reg_cnt = 0;
}
}
else
{
// LCD/CONSOLE单条模式,应答成功直接切回自动轮巡
rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
pROLL->run = RUN_AUTO;
rt_mutex_release(pTHR->mutex);
}
}
else
{
// AUTO自动采集,解析返回数据
chrg_eload_parse(idx, pROLL->part, pMB_R->payload, pMB_R->length);
}
} else {
LOG_E("crc failed.");
}
else
{
LOG_E("crc failed, resend current reg");
// CRC错误,不递增cur_idx,下一轮重发本条
}
if (RT_NULL != pMB_R->payload) {
// 释放报文内存
if (RT_NULL != pMB_R->payload)
{
rt_free(pMB_R->payload);
pMB_R->payload = RT_NULL;
}
if (RT_NULL != pMB_R) {
if (RT_NULL != pMB_R)
{
rt_free(pMB_R);
pMB_R = RT_NULL;
}
rt_thread_mdelay(200); // 间隔 200ms
} else { // 设备应答超时
if (RUN_AUTO != run) { // 非自动轮巡
rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
pROLL->run = RUN_AUTO; // 切换会自动轮巡
rt_mutex_release(pTHR->mutex);
rt_thread_mdelay(20);
}
else
{
// 应答超时处理
if (RUN_AUTO != run)
{
if(run == RUN_COM)
{
// 批量下发超时:不递增cur_idx,下一轮循环重发当前寄存器
LOG_E("com batch timeout, resend current reg");
}
else
{
// LCD/CONSOLE单条超时,切回自动轮巡
rt_mutex_take(pTHR->mutex, RT_WAITING_FOREVER);
pROLL->run = RUN_AUTO;
rt_mutex_release(pTHR->mutex);
}
}
}
// rt_kprintf("------ROLL SOU END \n--------");
}
}
#if 1
+39 -5
View File
@@ -6,7 +6,7 @@
:
:
******************************************************************************/
#include "chrg_south.h"
#ifndef __CHRG_ROLL_SOU_H__
#define __CHRG_ROLL_SOU_H__
@@ -15,9 +15,29 @@
#define THR_NAME_ROLL_SOU "thr.rollsou"
// 单通道批量下发缓存:保存当前需要同步的寄存器列表
#define SOU_COM_BATCH_REG_MAX 16
typedef struct
{
rt_uint16_t reg_cnt; // 当前待下发寄存器数量
rt_uint16_t reg_list[SOU_COM_BATCH_REG_MAX]; // 寄存器地址数组
rt_uint16_t val_list[SOU_COM_BATCH_REG_MAX]; // 对应寄存器值数组
rt_uint8_t cur_idx; // 当前下发到第几条
rt_bool_t pending; // 本通道有待下发批量指令
} sou_com_batch_ch_t;
// COM批量下发总控结构体
typedef struct
{
sou_com_batch_ch_t ch[TOTAL_SOU_CHS];
} chrg_rollsou_com_t;
// 全局批量下发实例
extern chrg_rollsou_com_t g_sou_com_batch;
struct chrg_rollsou_t {
rt_uint8_t run; // 下一轮运行方式 1:自动轮巡 2:LCD触发插入 3:控制台触发插入
rt_uint8_t run; // 下一轮运行方式 1:自动轮巡 2:LCD触发插入 3:控制台触发插入4.com触发插入
rt_uint8_t part; // 自动轮巡时,多条命令序号(若存在多条命令时)
rt_uint8_t idx; // 自动轮巡时,通道序号
@@ -25,7 +45,11 @@ 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 mode;// 0 为正常轮询,1为升级,2为校准
};
extern struct chrg_rollsou_t chrgrollsou;
@@ -39,7 +63,15 @@ extern struct chrg_rollsou_t chrgrollsou;
-
*****************************************************************/
extern void chrg_set_sou_reg (eIDX_SOU_CH idx, rt_uint16_t reg, rt_uint16_t value);
/*****************************************************************
chrg_set_sou_reg_com
com端南向通道设置寄存器请求命令
idx: reg: value:
-
-
*****************************************************************/
extern void chrg_set_sou_reg_com (eIDX_SOU_CH idx, rt_uint16_t reg, rt_uint16_t value);
/*****************************************************************
chrg_roll_sou_thread_entry
线
@@ -50,7 +82,9 @@ extern void chrg_set_sou_reg (eIDX_SOU_CH idx, rt_uint16_t reg, rt_uint16_t valu
*****************************************************************/
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);
extern int chrg_sou_com_batch_add_reg(eIDX_SOU_CH ch, rt_uint16_t reg, rt_uint16_t val);
#endif
+17 -4
View File
@@ -16,6 +16,7 @@
#include "chrg_roll_sou.h"
#include "chrg_switch.h"
#include "chrg_utils.h"
#include "chrg_eload.h"
#include "ulog.h"
//#define LOG_TAG "chrg.sou"
@@ -29,6 +30,7 @@ struct chrg_south_t chrgsouth = {
.tty = RT_NULL,
.rb = RT_NULL,
.enable = {1, 1, 1, 1},
.online = {0, 0, 0, 0},
};
/*****************************************************************
@@ -155,10 +157,8 @@ int chrg_south_send (rt_uint8_t *data, rt_size_t length)
struct chrg_tty_t *pTTY = chrgsouth.tty;
if (RT_NULL != pTTY) {
// LOG_HEX("sendS", 32, data, length);
ret = chrg_tty_send(pTTY, data, length);
}
return ret;
}
@@ -183,6 +183,7 @@ 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字节
rt_kprintf("len_rb=:%d",len_rb);
return -1;
}
@@ -357,7 +358,7 @@ void chrg_south_thread_entry (void *data)
return ;
}
chrg_tty_set_recv_tmo(pTTY, 100);
chrg_tty_set_recv_tmo(pTTY, 10);
if (chrg_tty_connect(pTTY) != RT_EOK) {
chrg_tty_destory(pTTY);
return;
@@ -380,6 +381,19 @@ void chrg_south_thread_entry (void *data)
}
rt_ringbuffer_put(pSOU->rb, pSOU->rx_buf, len);
/* 升级模式下: 南向板返回原始ymodem应答字节(ACK/NAK/C),非Modbus帧 */
if (chrgrollsou.mode == 1) {
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) {
chrg_eload_set_ymodem_resp(resp_byte);
}
}
continue;
}
//LOG_HEX("recvS", 32, pSOU->rx_buf, len);
if (1 == pSOU->frame.findhead) {
@@ -394,7 +408,6 @@ void chrg_south_thread_entry (void *data)
}
#if 1
static int south_ch(rt_uint8_t argc, char **argv)
+4 -1
View File
@@ -39,11 +39,14 @@ struct chrg_south_t {
rt_uint8_t rx_buf[SIZE_BUF_TTY];
rt_uint8_t enable[TOTAL_SOU_CHS]; // 通路使能
rt_uint8_t online[TOTAL_SOU_CHS]; // 在线状态
//rt_uint8_t manual; // 0: 程序自动 1:手动插入命令 2:插入设置模式
//eIDX_SOU_CH idx; // 当前通路
eIDX_SOU_CH idx; // 当前通路
eIDX_MB_PART part;
struct chrg_eload_t eload[TOTAL_SOU_CHS]; // 负载
rt_uint8_t rel_flag[8];
};
extern struct chrg_south_t chrgsouth;
+15 -4
View File
@@ -59,7 +59,7 @@ struct chrg_thread_t chrgthr[TOTAL_THRS] = {
.mask = EN_THR_MUTEX | EN_THR_MAILBOX,
.index = IDX_THR_COMM,
.priority = PRI_THR_COMM,
.stack = 2048,
.stack = 4096,
.tick = 20,
.entry = chrg_comm_thread_entry,
},
@@ -74,7 +74,7 @@ struct chrg_thread_t chrgthr[TOTAL_THRS] = {
.mq = RT_NULL,
.mask = EN_THR_MUTEX,
.index = IDX_THR_LCD,
.priority = PRI_THR_LCD,
.priority = PRI_THR_LCD-2,
.stack = 2048,
.tick = 20,
.entry = chrg_lcd_thread_entry,
@@ -159,7 +159,18 @@ rt_err_t chrg_thread_mb_send (eIDX_THRS idx, void *data)
if (RT_NULL != pTHR->mb) {
ret = rt_mb_send(pTHR->mb, (rt_uint32_t)data);
if (RT_EOK != ret) {
LOG_E("mb send failed. [%d]", 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);
}
}
}
@@ -227,7 +238,7 @@ int chrg_thread_create (eIDX_THRS idx)
}
if (pTHR->mask & EN_THR_MAILBOX) {
pTHR->mb = rt_mb_create(pTHR->name, 16, RT_IPC_FLAG_FIFO);
pTHR->mb = rt_mb_create(pTHR->name, 64, RT_IPC_FLAG_FIFO);
if (RT_NULL == pTHR->mb) {
LOG_E("create mb '%s' failed.", pTHR->name);
return -RT_ERROR;
+7 -6
View File
@@ -30,12 +30,12 @@ typedef enum {
TOTAL_THRS
} eIDX_THRS;
#define PRI_THR_NORTH 15
#define PRI_THR_SOUTH 14
#define PRI_THR_COMM 13
#define PRI_THR_LCD 12
#define PRI_THR_ROLL_NOR 16
#define PRI_THR_ROLL_SOU 16
#define PRI_THR_NORTH 10
#define PRI_THR_SOUTH 10
#define PRI_THR_COMM 9
#define PRI_THR_LCD 8
#define PRI_THR_ROLL_NOR 11
#define PRI_THR_ROLL_SOU 11
#define EN_THR_NONE 0x00
@@ -67,6 +67,7 @@ struct chrg_thread_t {
void (*entry)(void *parameter); // 线程体入口
};
extern struct chrg_thread_t chrgthr[TOTAL_THRS];
/*****************************************************************
+31 -4
View File
@@ -23,9 +23,9 @@ typedef enum {
} eIDX_CH;
typedef enum {
ID_SINK = 0x01, // SINK 的 ID 为 1, 波特率 200K
ID_SOURCE = 0x02, // SOURCE 的 ID 为 2, 波特率 200K
ID_ELOAD = 0x03, // LOAD ID 3 波特率 115200
ID_SINK = 0x01, // SINK 的 ID 为 1, 波特率 200K //sink协议板
ID_SOURCE = 0x02, // SOURCE 的 ID 为 2, 波特率 200K //source协议板
ID_ELOAD = 0x03, // LOAD ID 3 波特率 115200 //功率板
} eIDX_ID;
enum {
@@ -33,9 +33,35 @@ enum {
RUN_AUTO, // 执行轮巡
RUN_LCD, // 执行LCD触发
RUN_CONSOLE, // 执行控制台触发
RUN_UPDATA,
RUN_COM, //执行com触发
};
/* ======================== Ymodem 协议常量 (CRC-16/XMODEM) ======================== */
/* Ymodem 协议状态枚举 */
typedef enum {
Ymodem_No = 0xFF, // 非升级模式
Ymodem_Wait = 0, // 空闲等待,定时发送'C'
Ymodem_Rec_Start, // 收到文件名帧(SOH),待CRC校验
Ymodem_Rec_1024, // 数据帧接收中(SOH=128B / STX=1024B)
Ymodem_Rec_End, // 收到EOT,传输结束握手
Ymodem_Rec_Finish // 升级完成,准备收尾
} Ymodem_state;
/* Ymodem 协议控制字符 */
#define SOH 0x01 // 128字节数据包帧头
#define STX 0x02 // 1024字节数据包帧头
#define EOT 0x04 // 传输结束
#define ACK 0x06 // 正确应答
#define ACK_C 0x43 // 'C'CRC模式请求
#define NAK 0x15 // 错误应答
#define YM_CAN 0x18 // 取消传输
/* Ymodem 数据包大小常量 */
#define YMODEM_SOH_SIZE 133 // SOH包总长: 1+1+1+128+2
#define YMODEM_STX_SIZE 1029 // STX包总长: 1+1+1+1024+2
#define YMODEM_DATA_OFFSET 3 // 有效数据在包内偏移(跳帧头+块号+反码)
// 电压电流极值
struct vc_mm_t {
rt_uint16_t max_vol; // 最大电压 mV
@@ -59,6 +85,7 @@ enum {
// PD协议数据
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]; // 电压电流极值
+299 -85
View File
@@ -11,11 +11,68 @@
#include <stdlib.h>
#include <string.h>
#include <rtthread.h>
#include "chrg_south.h"
#include "chrg_roll_sou.h"
#include "chrg_north.h"
#include "chrg_eload.h"
#include "chrg_lcd.h"
#include "chrg_regs.h"
#include "chrg_utils.h"
#include "chrg_south.h"
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);
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};
/* ======================== Ymodem 升级应答缓存 ======================== */
static rt_uint8_t g_eload_ymodem_resp = 0; // 南向返回的ymodem应答字节(0=无应答)
static rt_uint8_t g_eload_ymodem_ready = 0; // 应答就绪标志(1=有新应答待取)
/*****************************************************************
chrg_eload_set_ymodem_resp
ymodem应答字节(chrg_roll_sou在RUN_UPDATA调用)
resp: ymodem应答 (ACK=0x06 / NAK=0x15 / 'C'=0x43)
*****************************************************************/
void chrg_eload_set_ymodem_resp(rt_uint8_t resp)
{
g_eload_ymodem_resp = resp;
g_eload_ymodem_ready = 1;
}
/*****************************************************************
chrg_eload_get_ymodem_resp
ymodem应答字节(chrg_comm的ymodem_send调用)
0
*****************************************************************/
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;
}
return resp;
}
/*****************************************************************
chrg_eload_clear_ymodem_resp
ymodem应答缓存()
*****************************************************************/
void chrg_eload_clear_ymodem_resp(void)
{
g_eload_ymodem_resp = 0;
g_eload_ymodem_ready = 0;
}
static int memcmp_8bytes(const rt_uint8_t *buf1, const rt_uint8_t *buf2)
{
for (int i = 0; i < 8; i++) {
if (buf1[i] != buf2[i]) {
return -1;
}
}
return 0;
}
/*****************************************************************
chrg_eload_read_regs
@@ -48,19 +105,111 @@ int chrg_eload_read_regs (rt_uint8_t addr, rt_uint16_t reg, rt_uint16_t len)
<0: >0:
-
*****************************************************************/
int chrg_eload_write_reg (rt_uint8_t addr, rt_uint16_t reg, rt_uint16_t value)
int chrg_eload_write_reg (rt_uint8_t addr, rt_uint16_t reg, rt_uint16_t value)
{
rt_uint8_t buf[8] = {0};
rt_uint16_t crc = 0;
buf[0] = addr;
buf[1] = MB_REGISTER_WR;
u16_to_u8v(reg, &buf[2]);
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);
return chrg_south_send(buf, 8);
}
/*****************************************************************
chrg_eload_send_ymodem_data
ymodem协议升级数据
buf: leng:
-
<0: >0:
-
*****************************************************************/
int chrg_eload_send_ymodem_data (rt_uint8_t *buf, rt_uint16_t leng)
{
rt_uint8_t buf[8] = {0};
rt_uint16_t crc = 0;
if(NULL == buf){
return 0;
}
return chrg_south_send(buf, leng);
}
buf[0] = addr;
buf[1] = MB_REGISTER_WR;
u16_to_u8v(reg, &buf[2]);
u16_to_u8v(value, &buf[4]);
crc = mb_crc16(buf, 6);
u16_to_u8v(swap_u16(crc), &buf[6]);
/**
return chrg_south_send(buf, 8);
*/
int chrg_eload_write_More_reg(rt_uint8_t addr,
rt_uint16_t reg_start,
rt_uint16_t reg_num,
const rt_uint16_t *data_buf)
{
rt_uint16_t total_len = 7 + (reg_num * 2) + 2;
rt_uint8_t buf[20] = {0};
rt_uint16_t idx = 0;
// 填充Modbus指令帧
buf[0] = addr; // 0: 设备地址
// rt_kprintf("addr=%d\r\n", addr);
buf[1] = MB_REGISTER_MORE_WR; // 1: 功能码(固定0x10
idx += 2;
u16_to_u8v(reg_start, &buf[idx]); // 2-3: 起始地址(idx从2开始)
idx += 2;
u16_to_u8v(reg_num, &buf[idx]); // 4-5: 寄存器数量
idx += 2;
buf[idx++] = reg_num * 2; // 6: 数据字节数
// 填充多组数据
for (rt_uint16_t i = 0; i < reg_num; i++) {
u16_to_u8v(data_buf[i], &buf[idx]); // 逐个填充数据的高低8位
idx += 2;
}
//计算并填充CRC16校验
rt_uint16_t crc = mb_crc16(buf, idx); // 计算CRC
u16_to_u8v(swap_u16(crc), &buf[idx]); // CRC字节序交换后填充
idx += 2;
// 发送指令
return chrg_south_send(buf, idx);
// 7. 释放动态缓冲区
}
void chrg_write_cv(rt_uint16_t curr,rt_uint16_t volt)
{
rt_uint16_t cv_value[4] = {0};
cv_value[0] = 0x00;
cv_value[1] = curr;
cv_value[2] = 0x00;
cv_value[3] = volt;
chrg_eload_write_More_reg(ID_ELOAD, REG_CV, 4,cv_value);
}
rt_uint8_t ret = 0;
int chrg_eload_send_relay(rt_uint8_t cmd_type)
{
rt_uint8_t relay_cmd[8] = {0};
rt_memcpy(relay_cmd, EXTRA_CMD_SOURCE, 8);
switch (cmd_type) {
case 0: // 停止(关闭俩个继电器)
relay_cmd[5] = 0x00;
relay_cmd[6] = 0xD9;
relay_cmd[7] = 0xE8;
break;
case 1: // 电源模式(打开主继电器,同时关闭滤波继电器)
break;
case 2: // 打开滤波继电器,关闭主继电器
relay_cmd[5] = 0x02;
relay_cmd[6] = 0x58;
relay_cmd[7] = 0x29;
break;
case 3: //打开俩个继电器
relay_cmd[5] = 0x03;
relay_cmd[6] = 0x99;
relay_cmd[7] = 0xE9;
break;
default:
return -1; // 无效命令类型
}
return chrg_south_send(relay_cmd, 8);
}
/*****************************************************************
@@ -76,7 +225,7 @@ int chrg_eload_refresh (rt_uint8_t addr, rt_uint8_t part)
int ret = 0;
if (0 == part) {
chrg_eload_read_regs(addr, REG_STA1, SIZE_P1_RD); // reg 0~13
chrg_eload_read_regs(addr, REG_STA1, SIZE_P1_RD); // reg 0~18
} else if (1 == part) {
chrg_eload_read_regs(addr, REG_POWER, SIZE_P2_RD); // reg 20~39
}
@@ -94,87 +243,152 @@ int chrg_eload_refresh (rt_uint8_t addr, rt_uint8_t part)
*****************************************************************/
int chrg_eload_parse (rt_uint8_t idx, rt_uint8_t pt, rt_uint8_t *data, rt_uint16_t len)
{
rt_uint8_t pro = 0;
if (idx >= TOTAL_SOU_CHS) {
return -1;
}
struct chrg_north_t *pNOR = &chrgnorth;
struct chrg_south_t *pSOU = &chrgsouth;
struct chrg_switch_t *pSW = &chrgnorth.sw[idx];
struct chrg_eload_t *pLOAD = &chrgsouth.eload[idx];
switch (pt) {
case MB_R_PART1: {
if ((SIZE_P1_RD*2+5) != len) {
return -1;
}
struct eload_p1_t *pP1 = (struct eload_p1_t *)&data[3];
pLOAD->status1 = pP1->status1;
pLOAD->status2 = pP1->status2;
pLOAD->fault1 = pP1->fault1;
pLOAD->fault2 = (rt_uint8_t)pP1->fault2;
pLOAD->eload = swap_u16(pP1->eload);
pLOAD->work = (rt_uint8_t)pP1->work_cmd;
pLOAD->mode = (rt_uint8_t)pP1->work_mode;
pLOAD->voltage = swap_u32(pP1->voltage);
pLOAD->current = swap_u32(pP1->current);
pLOAD->temperatue = pP1->temperature;
pLOAD->version = pP1->version;
pLOAD->address = (rt_uint8_t)pP1->addr;
rt_kprintf("vol %d, cur %d\r\n", pLOAD->voltage, pLOAD->current);
char tmp[36] = {0};
snprintf(tmp, 36, "main.CH%d_Volt_Show.val=%d",
idx+1, pLOAD->voltage);
chrg_lcd_send(tmp);
rt_memset(tmp, 0, 36);
snprintf(tmp, 36, "status.CH%d_Volt_Sta.txt=\"%d.%03d\"",
idx+1, pLOAD->voltage/1000, pLOAD->voltage%1000);
chrg_lcd_send(tmp);
rt_memset(tmp, 0, 36);
snprintf(tmp, 36, "main.CH%d_Curr_Show.val=%d",
idx+1, pLOAD->current);
chrg_lcd_send(tmp);
rt_memset(tmp, 0, 36);
snprintf(tmp, 36, "status.CH%d_Curr_Sta.txt=\"%d.%03d\"",
idx+1, pLOAD->current/1000, pLOAD->current%1000);
chrg_lcd_send(tmp);
rt_memset(tmp, 0, 36);
if (pP1->work_cmd == 0x100){
if (pP1->work_mode == MODE_CONSTANT_VOLTAGE){
snprintf(tmp, 36, "main.CH%d_Status.txt=\"恒压\"", idx+1);
} else {
snprintf(tmp, 36, "main.CH%d_Status.txt=\"恒流\"", idx+1);
}
} else {
snprintf(tmp, 36, "main.CH%d_Status.txt=\"停止\"", idx+1);
}
chrg_lcd_send(tmp);
rt_memset(tmp, 0, 36);
if ((SIZE_P1_RD*2+5) != len) {
return -1;
}
break;
case MB_R_PART2: {
if ((SIZE_P2_RD*2+5) != len) {
return -1;
}
struct eload_p2_t *pP2 = (struct eload_p2_t *)&data[3];
struct eload_p1_t *pP1 = (struct eload_p1_t *)&data[3];
// for(int i = 0;i<36;i++){
// rt_kprintf("%02x ",data[i+3]);
// }
pLOAD->status1 = pP1->status1;
pLOAD->status2 = pP1->status2;
pLOAD->fault1 = pP1->fault1;
pLOAD->fault2 = (rt_uint8_t)pP1->fault2;
pLOAD->eload = swap_u16(pP1->eload);
pLOAD->work = (rt_uint8_t)pP1->work_cmd;
pLOAD->mode = (rt_uint8_t)pP1->work_mode;
pLOAD->voltage = swap_u32(pP1->voltage);
pLOAD->current = swap_u32(pP1->current);
pLOAD->SHORT_volt = swap_u16(pP1->SHORT_volt);
pLOAD->SHORT_curr = swap_u16(pP1->SHORT_curr);
pLOAD->OCP_volt = swap_u16(pP1->OCP_volt);
pLOAD->OCP_curr = swap_u16(pP1->OCP_curr);
pLOAD->OCP_volt = swap_u16(pP1->OCP_volt);
pLOAD->vpkp = swap_u16(pP1->Vpkp);
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)
#if LCD_OPEN
// for(int i = 0;i<4;i++){
// if(pNOR->sw[i].change_flag == 0x01){
// pNOR->free_flag = 0x00;
// }else {
// pNOR->free_flag = 0x01;
// }
// }
// rt_kprintf("ch=%d,free_flag=%d,",idx,pNOR->free_flag);
if(pNOR->free_flag==0x01){
LCD_SHOW(idx, pP1, pLOAD, pSW, pSOU->online[idx]);
}
break;
default:
break;
}
#endif
usRegInBuf[INPUT_REG_CH0_STA1+idx*TOTAL_INPUT_CH_REGS] = pLOAD->status1;
usRegInBuf[INPUT_REG_CH0_STA2+idx*TOTAL_INPUT_CH_REGS] = pLOAD->status2;
usRegInBuf[INPUT_REG_CH0_FAULT1+idx*TOTAL_INPUT_CH_REGS] = pLOAD->fault1;
usRegInBuf[INPUT_REG_CH0_FAULT2+idx*TOTAL_INPUT_CH_REGS] = pLOAD->fault2;
usRegHoldBuf[HOLD_REG_CH0_ELOAD+idx*TOTAL_HOLD_CH_REGS] = pLOAD->eload;
usRegHoldBuf[HOLD_REG_CH0_WORK+idx*TOTAL_HOLD_CH_REGS] = pLOAD->work;
usRegHoldBuf[HOLD_REG_CH0_MODE+idx*TOTAL_HOLD_CH_REGS] = pLOAD->mode;
usRegHoldBuf[HOLD_REG_CH0_VOL_H+idx*TOTAL_HOLD_CH_REGS] = (pLOAD->voltage>>16)&0xFFFF;
usRegHoldBuf[HOLD_REG_CH0_VOL_L+idx*TOTAL_HOLD_CH_REGS] = pLOAD->voltage&0xFFFF;
usRegHoldBuf[HOLD_REG_CH0_CUR_H+idx*TOTAL_HOLD_CH_REGS] = (pLOAD->current>>16)&0xFFFF;
usRegHoldBuf[HOLD_REG_CH0_CUR_L+idx*TOTAL_HOLD_CH_REGS] = pLOAD->current&0xFFFF;
// usRegHoldBuf[HOLD_REG_CH0_TEMP+idx*TOTAL_HOLD_CH_REGS] = pLOAD->temperatue;
// usRegHoldBuf[HOLD_REG_CH0_VERSION+idx*TOTAL_HOLD_CH_REGS] = pLOAD->version;
// usRegHoldBuf[HOLD_REG_CH0_ADDR+idx*TOTAL_HOLD_CH_REGS] = pLOAD->address;
usRegHoldBuf[TEST_SHORT_CH0_VOLT+idx*TOTAL_HOLD_CH_REGS] = pLOAD->SHORT_volt;
usRegHoldBuf[TEST_SHORT_CHO_CURR+idx*TOTAL_HOLD_CH_REGS] = pLOAD->SHORT_curr;
usRegHoldBuf[TEST_OCP_CHO_VOLT+idx*TOTAL_HOLD_CH_REGS] = pLOAD->OCP_volt;
usRegHoldBuf[TEST_OCP_CHO_CURR+idx*TOTAL_HOLD_CH_REGS] = pLOAD->OCP_curr;
usRegHoldBuf[HOLD_REG_CH0_VPKP+idx*TOTAL_HOLD_CH_REGS] = pLOAD->vpkp;
usRegHoldBuf[HOLD_REG_CH0_VPKN+idx*TOTAL_HOLD_CH_REGS] = pLOAD->vpkn;
usRegHoldBuf[HOLD_REG_CH0_VPP+idx*TOTAL_HOLD_CH_REGS] = pLOAD->vpp;
usRegHoldBuf[HOLD_REG_CH0_Ripple+idx*TOTAL_HOLD_CH_REGS] = pLOAD->Ripple;
usRegHoldBuf[HOLD_REG_CH0_VZ+idx*TOTAL_HOLD_CH_REGS] = pSW->VZ;
usRegHoldBuf[HOLD_REG_CH0_VF+idx*TOTAL_HOLD_CH_REGS] = pSW->VF;
// rt_kprintf("---------NOW VOLT END = %d\n----------",pSW->Now_voltage);
return 0;
}
// 公共格式化辅助函数
static void snp_ch(char *tmp, rt_uint8_t idx, const char *name, rt_uint32_t val, rt_uint8_t online)
{
snprintf(tmp, 36, "status.CH%d_%s.val=%d", idx+1, name, online ? val : 0);
}
// 各显示函数增加 online 入参
void Show_Volt(rt_uint8_t idx, struct chrg_eload_t *pLOAD, char *tmp, rt_uint8_t online)
{
snp_ch(tmp, idx, "Volt", pLOAD->voltage, online);
}
void Show_Curr(rt_uint8_t idx, struct chrg_eload_t *pLOAD, char *tmp, rt_uint8_t online)
{
snp_ch(tmp, idx, "Curr", pLOAD->current, online);
}
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){
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)
{
snp_ch(tmp, idx, "VZF", vzf, online);
}
void Sta_compute(rt_uint8_t idx,int work_mode,char *tmp,struct chrg_switch_t *pSW)
{
int pro_name=0,val=0;
if(!pSW)return;
if(pSW->id==ID_SINK){
for(int i=0;i<LOAD_PRO_MAP_NUM;i++){
if(load_pro_map[i].pro_val==pSW->sink.protocol){
pro_name=load_pro_map[i].pro_name;val=pro_name*1000;
if(pSW->sink.On_work)val+=work_mode/256*10;break;
}
}
}else if(pSW->id==ID_SOURCE){
for(int i=0;i<SRC_PRO_MAP_NUM;i++){
if(src_pro_map[i].pro_val==pSW->source.protocol){
pro_name=src_pro_map[i].pro_name;val=pro_name*1000+100;
if(pSW->source.On_Flag)val+=work_mode/256*10;break;
}
}
}
snprintf(tmp,36,"status.va%d.val=%d",idx+1,val);
}
// 总调度函数
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)
{
char tmp[36] = {0};
rt_uint32_t vzf = pSW->VZ*1000+pSW->VF;
switch(pSW->show_step)
{
case SHOW_STATUS: Sta_compute(idx, pP1->work_mode, tmp, pSW); pSW->show_step = SHOW_VOLT; break;
case SHOW_VOLT: Show_Volt(idx, pLOAD, tmp, online); pSW->show_step = SHOW_CURR; break;
case SHOW_CURR: Show_Curr(idx, pLOAD, tmp, online); pSW->show_step = SHOW_RIPPLE; break;
case SHOW_RIPPLE: Show_Ripple(idx, pLOAD, tmp, online,pSW); pSW->show_step = SHOW_DZF; break;
case SHOW_DZF: Show_DZF(idx, pLOAD, tmp, online,vzf); pSW->show_step = SHOW_STATUS; break;
}
chrg_lcd_send(tmp);
}
+103 -14
View File
@@ -6,21 +6,69 @@
:
:
******************************************************************************/
#ifndef __CHRG_ELOAD_H__
#define __CHRG_ELOAD_H__
#include <rtthread.h>
#include "chrg_def.h"
//显示的类别
#define SHOW_STATUS 0x00
#define SHOW_VOLT 0x01
#define SHOW_CURR 0x02
#define SHOW_RIPPLE 0x03
#define SHOW_DZF 0x04
// 恒压
static const rt_uint8_t CV[29] = {
0x73,0x74,0x61,0x74,0x75,0x73,0x2E,
0x43, 0x48, 0x31, 0x5F, 0x52, 0x75, 0x6E, 0x5F, 0x53, 0x74, 0x61,
0x2E, 0x74, 0x78, 0x74, 0x3D, 0x22, 0xBA, 0xE3, 0xD1, 0xB9, 0x22
};
// 恒流
static const rt_uint8_t CC[29] = {
0x73,0x74,0x61,0x74,0x75,0x73,0x2E,
0x43, 0x48, 0x31, 0x5F, 0x52, 0x75, 0x6E, 0x5F, 0x53, 0x74, 0x61,
0x2E, 0x74, 0x78, 0x74, 0x3D, 0x22, 0xBA, 0xE3, 0xC1, 0xF7, 0x22
};
// 停止
static const rt_uint8_t STOP[29] = {
0x73,0x74,0x61,0x74,0x75,0x73,0x2E,
0x43, 0x48, 0x31, 0x5F, 0x52, 0x75, 0x6E, 0x5F, 0x53, 0x74, 0x61,
0x2E, 0x74, 0x78, 0x74, 0x3D, 0x22, 0xCD, 0xA3, 0xD6, 0xB9, 0x22
};
// 电源
static const rt_uint8_t SOURCE[30] = {
0x73,0x74,0x61,0x74,0x75,0x73,0x2E,
0x43, 0x48, 0x31, 0x5F, 0x46, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F,
0x6E, 0x2E, 0x74, 0x78, 0x74, 0x3D, 0x22, 0xB5, 0xE7, 0xD4, 0xB4, 0x22
};
// 负载
static const rt_uint8_t LOAD[30] = {
0x73,0x74,0x61,0x74,0x75,0x73,0x2E,
0x43, 0x48, 0x31, 0x5F, 0x46, 0x75, 0x6E, 0x63, 0x74, 0x69, 0x6F,
0x6E, 0x2E, 0x74, 0x78, 0x74, 0x3D, 0x22, 0xB8, 0xBA, 0xD4, 0xD8, 0x22
};
//寄存器
#define MB_REGISTER_RD (0x03) // 读寄存器
#define MB_REGISTER_WR (0x06) // 写寄存器
#define MB_REGISTER_MORE_WR (0x10) // 写多个寄存器
#define REG_STA1 (0x00) // R 16bit 工作状态1
#define STA1_CHARGING (0x00) // 预充电中
#define STA1_READY (0x01) // 就绪/停止
#define STA1_RUNNING (0x02) // 运行
#define STA1_FAULT (0x03) // 故障
#define REG_CV 0X07 // 电压地址
#define REG_REL_ON (0X01) // 主继电器控制寄存器
#define ALL_REL_OFF (0X00) // 关闭主继电器
#define MAIN_REL_ON (0X01) // 打开主继电器(关闭滤波继电器)
#define FU_REL_ON (0X02) // 打开副继电器(关闭主继电器)
#define ALL_REL_ON (0X03) // 打开俩个继电器
#define REG_STA2 (0x01) // R 16bit 工作状态2
#define STA2_PRE_REL_CLOSE (1<<0) // 预充继电器闭合
#define STA2_MAIN_REL_CLOSE (1<<1) // 主继电器闭合
@@ -85,6 +133,8 @@
#define REG_VOL_LOOP_KP (0x1F) // RWP float 电压环KP 0.001~100 默认0.1
#define Eload_Start_V_ON 0x20 //10 16寄存器存储电子负载启动电压,负载检测到电压值为启动电压,才开启电子负载;可配
#define REG_VOL_LOOP_KI (0x21) // RWP float 电压环KI 0.001~100 默认0.01
#define REG_CUR_LOOP_KP (0x23) // RWP float 电流环KP 0.001~100 默认0.1
@@ -101,6 +151,10 @@
#define REG_TEMP_PROTECT (0x2F) // RWP 16bit 温度保护值 0.01C (60~100C) 默认90C
#define RESET_NORTH_ADDR 0xF0 // 北向复位地址
#define RESET_NORTH_VALUE 0x0001 // 北向复位值
#define RESET_SOUTH_ADDR 0xE0 // 南向复位地址
#define RESET_SOUTH_VALUE 0x61 //南向复位值
typedef enum {
@@ -110,7 +164,7 @@ typedef enum {
TOTAL_MB_R
} eIDX_MB_PART;
#define SIZE_P1_RD 13 // 读13个寄存器
#define SIZE_P1_RD 19 // 读19个寄存器
#define SIZE_P2_RD 28 // 读28个寄存器
#pragma pack(push,1)
@@ -122,11 +176,17 @@ struct eload_p1_t {
rt_uint16_t eload; // reg4
rt_uint16_t work_cmd; // reg5
rt_uint16_t work_mode; // reg6
rt_uint32_t voltage; // reg7-8
rt_uint32_t current; // reg9-10
rt_uint16_t temperature; // reg11
rt_uint16_t version; // reg12
rt_uint16_t addr; // reg13
rt_uint32_t voltage; // reg7-8
rt_uint32_t current; // reg9-10
rt_uint16_t SHORT_volt; // reg11
rt_uint16_t SHORT_curr; // reg12
rt_uint16_t OCP_volt; // reg13
rt_uint16_t OCP_curr; // reg14
rt_uint16_t Vpkp; // reg15
rt_uint16_t Vpkn; // reg16
rt_uint16_t Vpp; // reg17
rt_uint16_t Ripple; // reg18
};
struct eload_p2_t {
@@ -155,16 +215,20 @@ struct chrg_eload_t {
rt_uint16_t fault1; // 故障状态1
rt_uint8_t fault2; // 故障状态2
rt_uint8_t eload; // 源载 1:电源 2:负载
rt_uint8_t work; // 工作指令
rt_uint8_t mode; // 工作模式
rt_uint8_t work; // 工作指令
rt_uint8_t mode; // 工作模式
rt_uint32_t voltage; // 电压
rt_uint32_t current; // 电流
rt_uint16_t temperatue; // 温度
rt_uint16_t version; // 版本
rt_uint8_t address; // 地址
rt_uint16_t SHORT_volt;// 短路电压
rt_uint16_t SHORT_curr;// 短路电流
rt_uint16_t OCP_volt; //OCP电压
rt_uint16_t OCP_curr; //OCP电流
rt_uint16_t vpkp; //量测正峰值
rt_uint16_t vpkn; //量测负峰值
rt_uint16_t vpp; //量测峰峰值
rt_uint16_t Ripple; //读取纹波
};
#pragma pack(pop)
/*****************************************************************
chrg_eload_read_regs
@@ -204,8 +268,33 @@ 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);
// 定义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);
//写入多寄存器
extern int chrg_eload_write_More_reg(rt_uint8_t addr,
rt_uint16_t reg_start,
rt_uint16_t reg_num,
const rt_uint16_t *data_buf);
extern void chrg_write_cv(rt_uint16_t curr,rt_uint16_t volt);
extern int chrg_eload_send_ymodem_data (rt_uint8_t *buf, rt_uint16_t leng);
/*****************************************************************
chrg_eload_set_ymodem_resp / chrg_eload_get_ymodem_resp / chrg_eload_clear_ymodem_resp
Ymodem升级时南向板应答字节的存取接口
chrg_roll_sou在RUN_UPDATA模式下捕获南向返回的原始ymodem应答(ACK/NAK/C)
chrg_comm的ymodem_send根据此应答决定给上位机的响应位
resp: ymodem应答字节 (ACK=0x06 / NAK=0x15 / 'C'=0x43)
get返回当前缓存的应答字节0
-
-
*****************************************************************/
extern void chrg_eload_set_ymodem_resp(rt_uint8_t resp);
extern rt_uint8_t chrg_eload_get_ymodem_resp(void);
extern void chrg_eload_clear_ymodem_resp(void);
#endif
+11 -9
View File
@@ -9,13 +9,13 @@
#include <string.h>
#include <rtthread.h>
#include "chrg_thread.h"
#include "chrg_north.h"
#include "chrg_north_pkg.h"
#include "chrg_utils.h"
#include "chrg_roll_nor.h"
/*****************************************************************
chrg_north_pkg_encode
chrg_north_pkg_en code
id: sink/source cmd: *data_in: len_in:
*data_out: len_out:
@@ -23,6 +23,7 @@
<0: >0:
-
*****************************************************************/
rt_bool_t flag_set = 0;
int chrg_north_pkg_encode (eIDX_ID id, rt_uint8_t cmd, rt_uint8_t *data_in,
rt_uint8_t len_in, rt_uint8_t *data_out, rt_uint16_t *len_out)
{
@@ -33,20 +34,21 @@ int chrg_north_pkg_encode (eIDX_ID id, rt_uint8_t cmd, rt_uint8_t *data_in,
if ((len_in > 0) && (RT_NULL == data_in)) {
return -1;
}
data_out[0] = 5+len_in;
data_out[1] = 0x00;
data_out[2] = id;
data_out[3] = cmd;
if (len_in > 0) {
rt_memcpy(&data_out[4], data_in, len_in);
}
data_out[len_in+4] = calc_crc8(data_out, len_in+4);
data_out[len_in+4] = 0x2a;//calc_crc8(data_out, len_in+4);
// rt_kprintf("pro_data= \n");
*len_out = 5+len_in;
// for(int i = 0; i < *len_out;i++)
// {
// rt_kprintf("%02x ",data_out[i]);
// }
// rt_kprintf("\n");
return 0;
}
@@ -28,7 +28,7 @@ extern int chrg_north_pkg_encode (eIDX_ID id, rt_uint8_t cmd, rt_uint8_t *data_i
-
*****************************************************************/
extern int chrg_north_pkg_decode (rt_uint8_t *data, rt_uint16_t length, struct chrg_switch_t *pSW);
extern rt_bool_t flag_set;
#endif
+288
View File
@@ -0,0 +1,288 @@
/****************************************************************************
: chrg_regs.h
:
: V1.0
: MODBUS
:
:
******************************************************************************/
#ifndef __CHRG_REGS_H__
#define __CHRG_REGS_H__
#define DISC_REG_START (0) // 开关量起始地址
#define COIL_REG_START (0) // 继电器起始地址
#define INPUT_REG_START (0) // 输入寄存器起始地址
#define HOLD_REG_START (0) // 保持寄存器起始地址
#define PRO_REG_START 0X11 // 协议寄存器起始地址
#define TEST_REG_START 0X00 // 测试寄存器起始地址
// 开关量寄存器列表
enum {
DISC_REG_00 = DISC_REG_START, // 开关量00
DISC_REG_01, // 开关量01
DISC_REG_02, // 开关量02
DISC_REG_03, // 开关量03
DISC_REG_04, // 开关量04
DISC_REG_05, // 开关量05
DISC_REG_06, // 开关量06
DISC_REG_07, // 开关量07
DISC_REG_08, // 开关量08
DISC_REG_09, // 开关量09
DISC_REG_10, // 开关量10
DISC_REG_11, // 开关量11
DISC_REG_12, // 开关量12
DISC_REG_13, // 开关量13
DISC_REG_14, // 开关量14
DISC_REG_15, // 开关量15
DISC_REG_16, // 开关量16
DISC_REG_17, // 开关量17
DISC_REG_18, // 开关量18
DISC_REG_19, // 开关量19
DISC_REG_20, // 开关量20
DISC_REG_21, // 开关量21
DISC_REG_22, // 开关量22
DISC_REG_23, // 开关量23
DISC_REG_24, // 开关量24
DISC_REG_25, // 开关量25
DISC_REG_26, // 开关量26
DISC_REG_27, // 开关量27
DISC_REG_28, // 开关量28
DISC_REG_29, // 开关量29
DISC_REG_30, // 开关量30
DISC_REG_31, // 开关量31
TOTAL_DISC_REGS // 输入开关量总数
};
#define TOTAL_COIL_CH_REGS (6) // 单通道 继电器寄存器数
// 继电器寄存器列表(按通道分组,每通道6个继电器)
enum {
// ==================== 通道1CH1):6个继电器 ====================
COIL_REG_CH1_PWR_SRC = COIL_REG_START, // CH1-功率板-主电源继电器(第0个)
COIL_REG_CH1_PWR_SINK, // CH1-功率板-主负载继电器(第1个)
COIL_REG_CH1_SINK_CC, // CH1-功率板-负载CC继电器
COIL_REG_CH1_SRC_CC, // CH1-功率板-电源CC继电器
COIL_REG_CH1_RESERVE1, // CH1-预留继电器1(第4个)
COIL_REG_CH1_RESERVE2, // CH1-预留继电器2(第5个)
// ==================== 通道2CH2):6个继电器 ====================
COIL_REG_CH2_PWR_SRC, // CH2-功率板-主电源继电器(第6个)
COIL_REG_CH2_PWR_SINK, // CH2-功率板-主负载继电器(第7个)
COIL_REG_CH2_SINK_CC, // CH2-功率板-负载CC继电器
COIL_REG_CH2_SRC_CC, // CH2-功率板-电源CC继电器
COIL_REG_CH2_RESERVE1, // CH2-预留继电器1(第10个)
COIL_REG_CH2_RESERVE2, // CH2-预留继电器2(第11个)
// ==================== 通道3CH3):6个继电器 ====================
COIL_REG_CH3_PWR_SRC, // CH3-功率板-主电源继电器(第12个)
COIL_REG_CH3_PWR_SINK, // CH3-功率板-主负载继电器(第13个)
COIL_REG_CH3_SINK_CC, // CH3-功率板-负载CC继电器
COIL_REG_CH3_SRC_CC, // CH3-功率板-电源CC继电器
COIL_REG_CH3_RESERVE1, // CH3-预留继电器1(第16个)
COIL_REG_CH3_RESERVE2, // CH3-预留继电器2(第17个)
// ==================== 通道4CH4):6个继电器 ====================
COIL_REG_CH4_PWR_SRC, // CH4-功率板-主电源继电器(第18个)
COIL_REG_CH4_PWR_SINK, // CH4-功率板-主负载继电器(第19个)
COIL_REG_CH4_SINK_CC, // CH4-功率板-负载CC继电器
COIL_REG_CH4_SRC_CC, // CH4-功率板-电源CC继电器
COIL_REG_CH4_RESERVE1, // CH4-预留继电器1(第22个)
COIL_REG_CH4_RESERVE2, // CH4-预留继电器2(第23个)
TOTAL_COIL_REGS // 继电器总数(24个)
};
#define TOTAL_INPUT_CH_REGS (10) // 单通道 输入寄存器
// 输入寄存器列表
enum {
INPUT_REG_CH0_STA1 = INPUT_REG_START, // 通道0 工作状态1 定义同源载
INPUT_REG_CH0_STA2, // 通道0 工作状态2 定义同源载
INPUT_REG_CH0_FAULT1, // 通道0 故障状态1 定义同源载
INPUT_REG_CH0_FAULT2, // 通道0 故障状态2 定义同源载
INPUT_REG_04, // 输入寄存器04
INPUT_REG_05, // 输入寄存器05
INPUT_REG_06, // 输入寄存器06
INPUT_REG_07, // 输入寄存器07
INPUT_REG_08, // 输入寄存器08
INPUT_REG_09, // 输入寄存器09
// add more TOTAL_INPUT_CH_REGS
INPUT_REG_CH1_STA1, // 通道1 工作状态1
INPUT_REG_CH1_STA2, // 通道1 工作状态2
INPUT_REG_CH1_FAULT1, // 通道1 故障状态1
INPUT_REG_CH1_FAULT2, // 通道1 故障状态2
INPUT_REG_14, // 输入寄存器14
INPUT_REG_15, // 输入寄存器15
INPUT_REG_16, // 输入寄存器16
INPUT_REG_17, // 输入寄存器17
INPUT_REG_18, // 输入寄存器18
INPUT_REG_19, // 输入寄存器19
INPUT_REG_CH2_STA1, // 通道2 工作状态1
INPUT_REG_CH2_STA2, // 通道2 工作状态2
INPUT_REG_CH2_FAULT1, // 通道2 故障状态1
INPUT_REG_CH2_FAULT2, // 通道2 故障状态2
INPUT_REG_24, // 输入寄存器24
INPUT_REG_25, // 输入寄存器25
INPUT_REG_26, // 输入寄存器26
INPUT_REG_27, // 输入寄存器27
INPUT_REG_28, // 输入寄存器28
INPUT_REG_29, // 输入寄存器29
INPUT_REG_CH3_STA1, // 通道3 工作状态1
INPUT_REG_CH3_STA2, // 通道3 工作状态2
INPUT_REG_CH3_FAULT1, // 通道3 故障状态1
INPUT_REG_CH3_FAULT2, // 通道3 故障状态2
INPUT_REG_34, // 输入寄存器34
INPUT_REG_35, // 输入寄存器35
INPUT_REG_36, // 输入寄存器36
INPUT_REG_37, // 输入寄存器37
INPUT_REG_38, // 输入寄存器38
INPUT_REG_39, // 输入寄存器39
INPUT_REG_40, // 输入寄存器40
TOTAL_INPUT_REGS // 输入寄存器总数
};
//AI修改,不一定准确
// ======================== 新寄存器映射 (基于0x06/0x10标准Modbus功能码) ========================
// 地址空间规划:
// 负载(Sink): 0x0000 + 通道号×29 + 参数偏移 (4通道×29=116个, 0x0000~0x0073)
// 电源(Source): 0x0080 + 通道号×6 + 参数偏移 (4通道×6=24个, 0x0080~0x0097)
// 系统(System): 0x00A0 + 通道号×2 + 参数偏移 (4通道×2=8个, 0x00A0~0x00A7)
// ---- 单通道寄存器数量 ----
#define TOTAL_SINK_CH_REGS (50) // 负载单通道寄存器数
#define TOTAL_SRC_CH_REGS (50) // 电源单通道寄存器数
#define TOTAL_SYS_CH_REGS (50) // 系统单通道寄存器数
// ---- 各区块基地址 ----
#define HOLD_REG_SINK_BASE (0x10) // 负载区块基地址
#define HOLD_REG_SRC_BASE (0x20) // 电源区块基地址
#define HOLD_REG_SYS_BASE (0x30) // 系统区块基地址
// ---- 负载(Sink)参数偏移 (相对通道基地址: HOLD_REG_SINK_BASE + ch*29) ----
#define SINK_REG_PROTOCOL 0x00 // 协议类型
#define SINK_REG_PRO_GEAR 0x01 // 协议挡位
#define SINK_REG_PRO_VOLT 0x02 // 协议电压 (mV)
#define SINK_REG_PRO_CURR 0x03 // 协议电流 (mA)
#define SINK_REG_CC_SEL 0x04 // CC选择 (0=CC1+CC2,1=CC1,2=CC2,3=断开)
#define SINK_REG_EMARK 0x05 // E-Mark控制 (预留)
#define SINK_REG_LOAD_MODE 0x06 // 负载模式 (0x01=恒压, 0x02=恒流)
#define SINK_REG_LOAD_VOLT 0x07 // 负载电压 (mV)
#define SINK_REG_LOAD_CURR 0x08 // 负载电流 (mA)
#define SINK_REG_TEST_MODE 0x09 // 测试模式 (0=正常,1=短路,2=OCP,3=动态)
#define SINK_REG_LOAD_STATUS 0x0A // 负载状态 (0x01=运行, 0x02=停止)
#define SINK_REG_VON_VOLT 0x0B // Von电压 (mV)
#define SINK_REG_RISE_SLOPE 0x0C // 加载斜率 (预留)
#define SINK_REG_FALL_SLOPE 0x0D // 卸载斜率 (预留)
#define SINK_REG_SHORT_HOLD_TIME 0x0E // 短路测试保持时间 (ms)
#define SINK_REG_SHORT_SET_MODE 0x0F // 短路测试设置模式 (0=设定时间后释放,1=一直保持)
#define SINK_REG_SHORT_HAVE_CURR 0x10
#define SINK_REG_OCP_START_CURR 0x11 // OCP起始电流 (mA/步)
#define SINK_REG_OCP_END_CURR 0x12 // OCP终点电流 (mA/步)
#define SINK_REG_OCP_STEP_CURR 0x13 // OCP步进电流 (mA/步)
#define SINK_REG_OCP_STEP_TIME 0x14 // OCP步进保持时间 (ms, 1-100)
#define SINK_REG_OCP_RECOV_TIME 0x15 // OCP恢复时间 (ms)
#define SINK_REG_OCP_STOP_VOLT 0x16 // OCP截止电压 (mV)
#define SINK_REG_OCP_RECOV_LOAD 0x17 // OCP恢复后带载 (0=不带载,1=带载)
#define SINK_REG_OCP_SET_MODE 0x18 // OCP设置模式 (0=保持设定时间后恢复,1=一直保持)
#define SINK_REG_DYNA_LOAD1 0x19 // 动态负载1 (mA)
#define SINK_REG_DYNA_TIME1 0x1A // 负载1保持时间 (0.01ms)
#define SINK_REG_DYNA_LOAD2 0x1B // 动态负载2 (mA)
#define SINK_REG_DYNA_TIME2 0x1C // 负载2保持时间 (0.01ms)
#define SINK_REG_DYNA_SLOPE 0x1D // 动态加载斜率 (0.001A/us)
#define SINK_REG_DYNA_UNLOAD 0x1E // 动态卸载斜率 (0.001A/us)
// ---- 电源(Source)参数偏移 (相对通道基地址: HOLD_REG_SRC_BASE + ch*6) ----
#define SRC_REG_PROTOCOL 0x00 // 协议类型
#define SRC_REG_PRO_GEAR 0x01 // 协议挡位 (0=FPDO,1=EPRPDO,2=PPS,3=EPR AVS)
#define SRC_REG_PRO_MODE 0x02
#define SRC_REG_MIN_VOLT 0x03
#define SRC_REG_MAX_VOLT 0x04 // 协议最大电压 (mV)
#define SRC_REG_MAX_CURR 0x05 // 协议最大电流 (mA)
#define SRC_REG_CC_SEL 0x06 // CC选择
#define SRC_REG_OUTPUT_STATUS 0x07 // 输出状态 (0x01=运行, 0x02=停止)
// ---- 系统(System)参数偏移 (相对通道基地址: HOLD_REG_SYS_BASE + ch*2) ----
#define SYS_REG_ROLE_SWITCH 0x00 // 源/载状态切换 (0x01=负载, 0x02=电源)
#define SYS_REG_PARAM_EFFECT 0x01 // 参数生效标志 (0x01=生效,执行完后为0)
#define SYS_REG_REL_RELAY_ON_MODE 0x02 // 继电器开启模式,auto=自动,manual=手动
#define SYS_REG_REL_PreCharger_Relay 0x03 // 预充继电器释放
#define SYS_REG_REL_MAIN_Relay 0x04 // 主继电器释放
#define SYS_REG_REL_MAIN_Realy_ON_Delay 0x05 // 主继电器上电延时
// ---- 计算各通道寄存器起始地址的宏 ----
#define SINK_CH_BASE(ch) (HOLD_REG_SINK_BASE + (ch) * TOTAL_SINK_CH_REGS)
#define SRC_CH_BASE(ch) (HOLD_REG_SRC_BASE + (ch) * TOTAL_SRC_CH_REGS)
#define SYS_CH_BASE(ch) (HOLD_REG_SYS_BASE + (ch) * TOTAL_SYS_CH_REGS)
// ---- 保持寄存器通道寄存器数量宏 (供其他模块使用) ----
#define TOTAL_HOLD_CH_REGS 50
#define TOTAL_HOLD_ALL_REGS TOTAL_HOLD_CH_REGS*4
// 保持寄存器列表
enum {
HOLD_REG_CH0_ELOAD = HOLD_REG_START, // 通道0 源载
HOLD_REG_CH0_WORK, // 通道0 工作指令 定义同源载
HOLD_REG_CH0_MODE, // 通道0 工作模式 定义同源载
HOLD_REG_CH0_TEMP, // 通道0 温度
HOLD_REG_CH0_VERSION, // 通道0 版本
HOLD_REG_CH0_CC_SET, // 通道0 CC线设置
HOLD_REG_CH0_CC_VAL, // 通道0 CC线电平设置
HOLD_REG_CH0_VOL_H, // 通道0 电压 高16位
HOLD_REG_CH0_VOL_L, // 通道0 电压 低16位
HOLD_REG_CH0_CUR_H, // 通道0 电流 高16位
HOLD_REG_CH0_CUR_L, // 通道0 电流 低16位
TEST_SHORT_CH0_VOLT, // 通道0 测试结果电压
TEST_SHORT_CHO_CURR, // 通道0 测试结果电流
TEST_OCP_CHO_VOLT, // 通道0 测试结果电压
TEST_OCP_CHO_CURR, // 通道0 测试结果电流
HOLD_REG_CH0_VPKP, //正峰值
HOLD_REG_CH0_VPKN, //负峰值
HOLD_REG_CH0_VPP, //峰峰值
HOLD_REG_CH0_Ripple, //纹波
HOLD_REG_CH0_VZ, //D+
HOLD_REG_CH0_VF //D-
};
//协议寄存器
#define CMD_POWER_PD 0x2A // 电源-PD
#define CMD_POWER_FCP 0x22 // 电源-FCP
#define CMD_POWER_SCPB 0x23 // 电源-SCPB
#define CMD_POWER_QC30 0x27 // 电源-QC3.0
#define CMD_POWER_QC20 0x28 // 电源-QC2.0
#define CMD_POWER_AFC 0x29 // 电源-AFC
#define CMD_POWER_UFCS 0x2C // 电源-UFCS
#define CMD_POWER_SPBA 0x2F // 电源-SPBA
#define TOTAL_PROTOCAL_CNT 0X30 // 协议范围
#define BITS_UCHAR 8U
/* Ymodem 协议字符定义 */
#define SOH 0x01 // 128字节包
#define STX 0x02 // 1024字节包
#define EOT 0x04 // 传输结束
#define ACK 0x06 // 应答
#define ACK_C 0x43
#define ModbusRTU_Ripplse_K 0x6A //纹波K值;
#define ModbusRTU_Ripplse_B 0x6B //纹波B值;
extern rt_uint8_t ucDiscInBuf[(TOTAL_DISC_REGS+BITS_UCHAR-1)/BITS_UCHAR];
extern rt_uint8_t ucCoilBuf[(TOTAL_COIL_REGS+BITS_UCHAR-1)/BITS_UCHAR];
extern rt_uint16_t usRegInBuf[TOTAL_INPUT_REGS];
extern rt_uint16_t usRegHoldBuf[TOTAL_HOLD_ALL_REGS];
//extern rt_uint16_t usRegTestBuf[TOTAL_TEST_REGS];
#endif
+460 -4
View File
@@ -13,7 +13,11 @@
#include "chrg_north.h"
#include "chrg_north_pkg.h"
#include "chrg_utils.h"
#include "chrg_roll_sou.h"
#include "chrg_roll_nor.h"
#include "chrg_def.h"
#include "chrg_rel.h"
#include "chrg_comm.h"
/*****************************************************************
sink_get_vc
sink电压电流查询请求
@@ -73,7 +77,9 @@ int sink_set_cc_line (rt_uint8_t line)
data[0] = line;
chrg_north_pkg_encode(ID_SINK, SINK_CMD_SET_CC, data, 1, frame, &len);
// for(int i = 0; i < len; i++) {
// rt_kprintf("data[%d]=%02x\r\n", i, frame[i]);
// }
return chrg_north_send(frame, len);
}
@@ -108,19 +114,469 @@ int sink_set_cc_lvl (rt_uint8_t lvl)
*****************************************************************/
int sink_set_pd (rt_uint8_t pd, rt_uint8_t *buf)
{
rt_uint16_t len = 0;
rt_uint8_t data[8] = {0};
rt_uint8_t frame[16] = {0};
int i = 0;
for (i = 0; i < 5; i++) {
data[i] = buf[i];
}
chrg_north_pkg_encode(ID_SINK, pd, data, 5, frame, &len);
return chrg_north_send(frame, len);
}
//// 短路测试参数解析 指令码:0x01
//void sink_test_short_set(struct chrg_switch_t *pSW, rt_uint8_t *pData, rt_uint8_t run_flag)
//{
// struct test_short *pTest = &pSW->sink.test.short_test;
// // 解析报文:高字节pData[1]、低字节pData[2] → 测试保持时间
// pTest->hold_time = (pData[1] << 8) | pData[2];
// pTest->set_mode = pData[3]; // 模式选择:0=测试后一直保持;1=保持指定时长后恢复原有电流
// rt_kprintf("[SINK] Short Test: time=%d, mode=%d\n",
// pTest->hold_time, pTest->set_mode);
//}
////=============================================================================
//// OCP过流保护测试参数解析 指令码:0x02
////=============================================================================
//void sink_test_ocp_set(struct chrg_switch_t *pSW, rt_uint8_t *pData, rt_uint8_t run_flag)
//{
// struct test_OCP *pTest = &pSW->sink.test.OCP_test;
// pTest->start_curr = (pData[1] << 8) | pData[2]; // 解析:OCP测试起始电流
// pTest->end_curr = (pData[3] << 8) | pData[4]; // 解析:OCP测试终止电流
// pTest->change_curr = (pData[5] << 8) | pData[6]; // 解析:电流步进值
// pTest->change_keep_time = (pData[7] << 8) | pData[8]; // 解析:单步电流保持时间
// pTest->hold_time = (pData[9] << 8) | pData[10]; // 解析:OCP触发后保持时间
// pTest->stop_volt = (pData[11]<< 8) | pData[12]; // 解析:停止判定电压
// pTest->set_mode = pData[13]; // 测试结束模式:0=保持设定时间后恢复;1=一直保持
// pTest->hold_curr = pData[14]; // OCP触发后是否带载,0=带载,1=不带载
// // pTest->change_mode = pData[11]; // 电流变化模式(预留):0=置0;1=达标立即置0;2=保持当前电流
// // pTest->interval_time = pData[12]; // 指令保护间隔时间(预留)
// pSW->sink.loadc = pTest->start_curr; // 负载电流初始化为OCP起始电流
//#if SINK_TEST_DEBUG
// rt_kprintf("[SINK] OCP Test: start=%d, end=%d\n",
// pTest->start_curr, pTest->end_curr);
//#endif
//}
////=============================================================================
//// 动态负载测试参数解析 指令码:0x03
////=============================================================================
//void sink_test_dynamic_set(struct chrg_switch_t *pSW, rt_uint8_t *pData, rt_uint8_t run_flag)
//{
// struct test_change *pTest = &pSW->sink.test.change_test;
//// rt_uint16_t change_curr = 0;
// pTest->curr1_set = (pData[1] << 8) | pData[2]; // 解析:第一阶段设定电流
// pTest->time1_set = (pData[3] << 8) | pData[4]; // 解析:第一阶段保持时长
// pTest->curr2_set = (pData[5] << 8) | pData[6]; // 解析:第二阶段设定电流
// pTest->time2_set = (pData[7]<< 8) | pData[8]; // 解析:第二阶段保持时长
// pTest->k_Rise = (pData[9] << 8) | pData[10]; // 电流上升斜率
// pTest->k_Fall = (pData[11]<< 8) | pData[12]; // 电流下降斜率
// // pTest->start_time = (pData[14]<< 8) | pData[13]; // 产品稳定时长(预留)
// // pSW->sink.loadc = pTest->curr1_set;
//#if SINK_TEST_DEBUG
// rt_kprintf("[SINK] Dynamic Test: curr1=%d, curr2=%d\n",
// pTest->curr1_set, pTest->curr2_set);
//#endif
//}
////=============================================================================
//// 短路测试状态机执行函数
//// 依据 work_step 分步配置寄存器,启动短路测试
////=============================================================================
//void chrg_nor_sink_short_test(rt_uint8_t ch, struct chrg_switch_t *pSW)
//{
// struct test *pTest = &pSW->sink.test;
//
// switch (pTest->work_step)
// {
// case 0:
// // 第一步:切换为电子负载模式,吸合负载开关
// chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_ELOAD, ELOAD_LOAD);
//// rt_kprintf("first\r\n");
// chrg_nor_sw_rel((eIDX_NOR_CH)ch,ID_SINK);
// pTest->work_step = 1;
// break;
// case 1:
// // 根据模式分支配置参数
// if(pTest->short_test.set_mode == 0x00) { //直接释放
// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_ShortTest_CMD_MODE_FLAG , ModbusRTU_DYNA_CMD_MODE_RUN_NO_CURR); //直接为0
// pTest->work_step = 2;
// }
// else{ //按设定的时间后释放
// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_ShortTest_CMD_MODE_FLAG , ModbusRTU_DYNA_CMD_MODE_RUN_ALWAYS_KEPP); //保持
// pTest->work_step = 4;
// }
//
// rt_kprintf("set_mode = %d",pTest->short_test.set_mode);
// break;
// case 2:
// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_ShortTest_Hold_Time , pTest->short_test.hold_time);
// pTest->work_step = 4;
// break;
// case 4:
// // 启动整机工作,清零状态标志
// chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_WORK, WORK_START);
// pTest->work_step = 5;
// pSW->change_flag = 0;
// break;
// case 5:
// break;
// default:
// pTest->work_step = 0;
// break;
// }
//}
////=============================================================================
//// OCP过流保护测试状态机执行函数
//// 分步配置电流、时长、模式寄存器,最终启动OCP测试
////=============================================================================
//// OCP测试执行
//void chrg_nor_sink_OCP_test(rt_uint8_t ch, struct chrg_switch_t *pSW)
//{
// struct test *pTest = &pSW->sink.test;
// switch (pTest->work_step)
// {
// case 0: // 初始化:切负载模式、闭合负载开关
// chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_ELOAD, ELOAD_LOAD);
//// rt_kprintf("first\r\n");
// chrg_nor_sw_rel((eIDX_NOR_CH)ch,ID_SINK);
// pTest->work_step = SET_OCP_STARTCURR;
// break;
// case SET_OCP_STARTCURR: // 设置OCP起始电流
// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_OCPTest_StartCurrent, pTest->OCP_test.start_curr);
// pTest->work_step = SET_OCP_ENDCURR;
// break;
// case SET_OCP_ENDCURR: // 设置OCP终止电流
// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_OCPTest_StopCurrent , pTest->OCP_test.end_curr);
// pTest->work_step = SET_OCP_STEP;
// break;
// case SET_OCP_STEP: // 设置电流步进值
// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_OCPTest_Step_CURR , pTest->OCP_test.change_curr);
// pTest->work_step = SET_OCP_STEP_HOLD_TIME;
// break;
// case SET_OCP_STEP_HOLD_TIME: // 设置单步保持时间
// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_OCPTest_Step_Hold_Time , pTest->OCP_test.change_keep_time);
// pTest->work_step = SINK_OCP_STOP_VOLT;
// break;
// case SINK_OCP_STOP_VOLT: //设置截止电压
// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_OCPTest_Vtrig_Stop , pTest->OCP_test.stop_volt);
// pTest->work_step = SET_OCP_CMD_MODE_RUN;
// break;
// case SET_OCP_CMD_MODE_RUN: // 标记测试运行模式
// if(pTest->OCP_test.set_mode == 0x00) { //释放
// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_OCPTest_CMD_MODE_FLAG , ModbusRTU_DYNA_CMD_MODE_RUN_NO_CURR); //直接为0
// pTest->work_step = SET_OCP_HOLD_TIME;
// }
// else{ //保持
// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_OCPTest_CMD_MODE_FLAG , ModbusRTU_DYNA_CMD_MODE_RUN_ALWAYS_KEPP); //保持
// pTest->work_step = SET_OCP_RUNNING;
// }
// break;
// case SET_OCP_HOLD_TIME: // 设置OCP触发后保持时间
// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_OCPTest_Hold_Time , pTest->OCP_test.hold_time);
// pTest->work_step = SET_OCP_RUNNING;
// break;
// case SET_OCP_RUNNING: // 启动OCP测试
// chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_WORK, WORK_START);
// pSW->change_flag = 0;
// pTest->work_step = 0x10;
// break;
// case 0x10:
// break;
// default:
// break;
// }
//}
////=============================================================================
//// 动态负载测试状态机执行函数
//// 依次配置两段电流、时长、升降斜率,启动动态负载测试
////=============================================================================
//void chrg_nor_sink_change_test(rt_uint8_t ch, struct chrg_switch_t *pSW)
//{
// struct test *pTest = &pSW->sink.test;
// switch (pTest->work_step)
// {
// case 0: // 初始步骤:切换电子负载模式、闭合负载开关
// chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_ELOAD, ELOAD_LOAD);
// chrg_nor_sw_rel((eIDX_NOR_CH)ch,ID_SINK);
// pTest->work_step = SET_DYNA_CURR1;
// break;
// case SET_DYNA_CURR1: // 设置第一路输出电流
// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_DYNA_L1, pTest->change_test.curr1_set);
// pTest->work_step = SET_DYNA_TIME1;
// #if SINK_TEST_DEBUG
// rt_kprintf("Curr1: %d\n", pTest->change_test.curr1_set);
// #endif
// break;
// case SET_DYNA_TIME1: // 设置第一阶段保持时间
// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_DYNA_T1 , pTest->change_test.time1_set);
// pTest->work_step = SET_DYNA_CURR2;
// #if SINK_TEST_DEBUG
// rt_kprintf("Time1: %d\n", pTest->change_test.time1_set);
// #endif
// break;
// case SET_DYNA_CURR2: // 设置第二路输出电流
// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_DYNA_L2 , pTest->change_test.curr2_set);
// pTest->work_step = SET_DYNA_TIME2;
// #if SINK_TEST_DEBUG
// rt_kprintf("Curr2: %d\n", pTest->change_test.curr2_set);
// #endif
// break;
// case SET_DYNA_TIME2: // 设置第二阶段保持时间
// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_DYNA_T2 , pTest->change_test.time2_set);
// pTest->work_step = SET_DYNA_RISE_SLEW_RATE;
// #if SINK_TEST_DEBUG
// rt_kprintf("Time2: %d\n", pTest->change_test.time2_set);
// #endif
// break;
// case SET_DYNA_RISE_SLEW_RATE: // 设置电流上升斜率
// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_DYNA_Rise_Slew_Rate , pTest->change_test.k_Rise);
// pTest->work_step = SET_DYNA_FALL_SLEW_RATE;
// #if SINK_TEST_DEBUG
// rt_kprintf("Rise Slew Rate: %d\n", pTest->change_test.k_Rise);
// #endif
// break;
// case SET_DYNA_FALL_SLEW_RATE: // 设置电流下降斜率
// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_DYNA_Fall_Slew_Rate , pTest->change_test.k_Fall);
// pTest->work_step = SET_DYNA_CND_MODE;
// #if SINK_TEST_DEBUG
// rt_kprintf("Fall Slew Rate: %d\n", pTest->change_test.k_Fall);
// #endif
// break;
// case SET_DYNA_CND_MODE: // 标记动态测试为运行状态
// chrg_set_sou_reg((eIDX_SOU_CH)ch, ModbusRTU_DYNA_CMD_MODE_FLAG , ModbusRTU_DYNA_CMD_MODE_RUN);
// pTest->work_step = SET_DYNA_RUNNING;
// pTest->work_step = SET_DYNA_CND_MODE;
// #if SINK_TEST_DEBUG
// rt_kprintf("Fall Slew Rate: %d\n", pTest->change_test.k_Fall);
// #endif
// break;
// case SET_DYNA_RUNNING: // 启动整机工作,锁定当前运行步骤、清空标志位
// chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_WORK, WORK_START);
// pTest->work_step = SET_DYNA_RUNNING;
// pTest->work_step = 0x11;
// pSW->change_flag = 0;
// break;
// case 0x11:
// break;
// default:
// #if SINK_TEST_DEBUG
// rt_kprintf("Invalid work step: %d\n", pTest->work_step);
// #endif
// break;
// }
//}
////=============================================================================
//// 短路测试停止处理函数
//// 依据 stop_step 分步执行停止流程,清除测试标记并跳转状态
////=============================================================================
//void chrg_nor_sink_short_test_stop(rt_uint8_t idx, struct chrg_switch_t *pSW,rt_uint8_t *enable)
//{
// struct test *pTest = &pSW->sink.test;
// switch (pTest->stop_step)
// {
// case TEST_STOP_CMD_MODE: // 下发停止指令,关闭短路测试运行模式
// chrg_set_sou_reg(idx, ModbusRTU_ShortTest_CMD_MODE_FLAG, ModbusRTU_DYNA_CMD_MODE_STOP);
// // pTest->stop_step = TEST_STOP_RUN;
// // break;
// // case TEST_STOP_RUN: // 清除测试标志,切换至负载状态管理流程
// //chrg_set_sou_reg(idx, REG_WORK, WORK_STOP);
// //pTest->stop_step = TEST_STOP_REL;
// //chrg_nor_sw_rel((eIDX_NOR_CH)idx,0);
// //*enable = 0;
// pSW->change_flag = 0;
// pSW->sink.test.test_mode = 0; // 清空短路测试标记
// pSW->sub = 21; // IDX_SET_SINK_WORK_STATE; 跳转至负载工作状态处理
// break;
// default:
// break;
// }
//}
////=============================================================================
//// OCP过流保护测试停止处理函数
////=============================================================================
//void chrg_nor_sink_OCP_test_stop(rt_uint8_t idx, struct chrg_switch_t *pSW,rt_uint8_t *enable)
//{
// struct test *pTest = &pSW->sink.test;
// switch (pTest->stop_step)
// {
// case TEST_STOP_CMD_MODE: // 下发停止指令,关闭OCP测试运行模式
// chrg_set_sou_reg((eIDX_SOU_CH)idx, ModbusRTU_OCPTest_CMD_MODE_FLAG , ModbusRTU_DYNA_CMD_MODE_STOP);
// pSW->change_flag = 0;
// pSW->sink.test.test_mode = 0; // 清空OCP测试标记
// pSW->sub = 21; // IDX_SET_SINK_WORK_STATE;
// break;
// default:
// break;
// }
//}
////=============================================================================
//// 动态负载测试停止处理函数
////=============================================================================
//void chrg_nor_sink_change_test_stop(rt_uint8_t idx, struct chrg_switch_t *pSW,rt_uint8_t *enable)
//{
// struct test *pTest = &pSW->sink.test;
// switch (pTest->stop_step)
// {
// case TEST_STOP_CMD_MODE: // 下发停止指令,关闭动态测试运行模式
// chrg_set_sou_reg((eIDX_SOU_CH)idx, ModbusRTU_DYNA_CMD_MODE_FLAG , ModbusRTU_DYNA_CMD_MODE_STOP);
// pSW->change_flag = 0;
// pSW->sink.test.test_mode = 0; // 清空动态测试标记
// pSW->sub = 21; // IDX_SET_SINK_WORK_STATE;
// break;
// default:
// break;
// }
//}
//sink开机初始化
void chrg_sink_work_init(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
{
struct chrg_south_t *pSOU = &chrgsouth;
struct chrg_north_t *pNOR = &chrgnorth;
pSW->sink.On_work = 1;
pSOU->enable[idx] = 1;
pSOU->online[idx] = 1;
pNOR->enable[idx] = 1;
chrg_nor_sw_rel((eIDX_NOR_CH)idx, ID_SINK); //打开北向继电器
// 1. 电流输出置0
chrg_sou_com_batch_add_reg(idx, REG_CURRENT_OUT+1, 0);
// 2. 设置硬件恒压/恒流模式
chrg_sou_com_batch_add_reg(idx,REG_MODE,pSW->CV_mode);
switch(pSW->sink.test.test_mode_old){
case 0:
break;
case 1://短路测试退出
chrg_sou_com_batch_add_reg((eIDX_SOU_CH)idx, ModbusRTU_ShortTest_CMD_MODE_FLAG , ModbusRTU_DYNA_CMD_MODE_STOP);
break;
case 2:
break;
case 3:
chrg_sou_com_batch_add_reg((eIDX_SOU_CH)idx, ModbusRTU_DYNA_CMD_MODE_FLAG , ModbusRTU_DYNA_CMD_MODE_STOP);
break;
}
pSW->sink.test.test_mode_old = 0;
pSW->sink.work_mode = SINK_WORK_WAIT;
}
//sink进入运行状态
void chrg_sink_work_volt_runing(eIDX_SOU_CH idx, struct chrg_switch_t *pSW){
chrg_sou_com_batch_add_reg(idx, 0x01, 0x02);
//打开主继电器
chrg_sou_com_batch_add_reg(idx, 0x01, 0x03);
if(pSW->CV_mode == MODE_CONSTANT_VOLTAGE)
{
chrg_sou_com_batch_add_reg(idx, REG_VOLTAGE_OUT+1, pSW->sink.loadv);
}
else
{
chrg_sou_com_batch_add_reg(idx, REG_CURRENT_OUT+1, pSW->sink.loadc);
}
chrg_sou_com_batch_add_reg(idx, REG_WORK, WORK_START);
}
//sink进入低电压状态
void chrg_sink_nor_work_low(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
{
chrg_sou_com_batch_add_reg(idx, 0x01, 0x00);
chrg_sou_com_batch_add_reg(idx, REG_WORK, WORK_STOP);
}
//com端关机流程
void chrg_sink_nor_work_off(eIDX_SOU_CH idx, struct chrg_switch_t *pSW)
{
struct chrg_south_t *pSOU = &chrgsouth;
struct chrg_north_t *pNOR = &chrgnorth;
pSW->sink.On_work = 0;
pSOU->enable[idx] = 0;
pSOU->online[idx] = 0;
pNOR->enable[idx] = 0;
chrg_nor_sw_rel((eIDX_NOR_CH)idx, 0); //关闭北向继电器
chrg_sou_com_batch_add_reg(idx, 0x01, 0x00);
chrg_sou_com_batch_add_reg(idx, REG_WORK, WORK_STOP);
}
//动态测试启动
void chrg_sink_change_ON(rt_uint8_t ch, struct chrg_switch_t *pSW)
{
struct test *pTest = &pSW->sink.test;
chrg_sou_com_batch_add_reg((eIDX_SOU_CH)ch, ModbusRTU_DYNA_L1, pTest->change_test.curr1_set);
chrg_sou_com_batch_add_reg((eIDX_SOU_CH)ch, ModbusRTU_DYNA_T1 , pTest->change_test.time1_set);
chrg_sou_com_batch_add_reg((eIDX_SOU_CH)ch, ModbusRTU_DYNA_L2 , pTest->change_test.curr2_set);
chrg_sou_com_batch_add_reg((eIDX_SOU_CH)ch, ModbusRTU_DYNA_T2 , pTest->change_test.time2_set);
chrg_sou_com_batch_add_reg((eIDX_SOU_CH)ch, ModbusRTU_DYNA_CMD_MODE_FLAG , ModbusRTU_DYNA_CMD_MODE_RUN);
chrg_sou_com_batch_add_reg((eIDX_SOU_CH)ch, REG_WORK, WORK_START);
}
//短路测试启动
void chrg_sink_SHOUT_ON(rt_uint8_t ch, struct chrg_switch_t *pSW)
{
struct test *pTest = &pSW->sink.test;
chrg_sou_com_batch_add_reg((eIDX_SOU_CH)ch, ModbusRTU_ShortTest_CMD_MODE_FLAG , ModbusRTU_DYNA_CMD_MODE_RUN_ALWAYS_KEPP); //保持
chrg_sou_com_batch_add_reg((eIDX_SOU_CH)ch, REG_WORK, WORK_START);
}
//负载工作
void chrg_sink_work(eIDX_SOU_CH idx, struct chrg_switch_t *pSW){
static uint8_t last_state[TOTAL_SOU_CHS] ={100,100,100,100};
rt_uint8_t work_mode = pSW->sink.work_mode;
// 本次状态和上次一致,直接跳过,不重复下发寄存器
if (work_mode == last_state[idx])
{
return;
}
chrg_sou_com_sou_set();
switch(work_mode){
case SINK_WORK_INIT:
chrg_sink_work_init(idx,pSW);
break;
case SINK_WORK_WAIT:
break;
case SINK_WORK_RUNING:
chrg_sink_work_volt_runing(idx,pSW);
break;
case SINK_WORK_RUNING_2:
chrg_sink_work_volt_runing(idx,pSW);
break;
case SINK_WORK_ON_TEST_CHANGE:
chrg_sink_change_ON(idx,pSW);
break;
case SINK_WORK_ON_TEST_SHOUT:
chrg_sink_SHOUT_ON(idx,pSW);
break;
case SINK_WORK_LOW:
chrg_sink_nor_work_low(idx,pSW);
break;
case SINK_WORK_STOP:
chrg_sink_nor_work_off(idx,pSW);
break;
}
// 更新缓存,保存本次最新状态
last_state[idx] = work_mode;
}
+241 -57
View File
@@ -11,20 +11,63 @@
#define __CHRG_SINK_H__
#include <rtthread.h>
struct chrg_switch_t;
#include "chrg_def.h"
#include "chrg_south.h"
// 冠达快充板(SINK)通讯协议
// SINK的ID为1,波特率200KTTL
#define SINK_NO_TEST 0
#define SINK_TEST_SHORT 1
#define SINK_TEST_OCP 2
#define SINK_TEST_DYNA 3
//短路测试结构体
struct test_short {
rt_uint16_t hold_time; // 短路测试时间
rt_uint8_t set_mode; // 0为测试后电流保持设定的设定时间后恢复;1为一直保持
rt_uint8_t have_curr_flag; //0为不带,1为带(默认)
};
//OCP测试结构体
struct test_OCP {
rt_uint16_t start_curr; // 起始电流
rt_uint16_t end_curr; // 结束电流
rt_uint16_t change_curr; // 步进电流,单位mA
rt_uint16_t change_keep_time; // 每步保持时间,单位ms(1-100)
rt_uint16_t hold_time; // OCP触发后保持时间,单位ms
rt_uint16_t set_mode; // 0为测试后电流保持设定的设定时间后恢复;1为一直保持
rt_uint16_t stop_volt; // 停止电压,单位mv
rt_uint8_t hold_curr; // OCP触发后是否带载,0=带载,1=不带载
//rt_uint16_t Vtrig_Stop; // 达到触发OCP流点的电压值;
// rt_uint16_t Volt_OCP; // 无论short测试成功或者失败,都给出短路恒流值的时候的电压
// rt_uint16_t Current_OCP; // 无论short测试成功或者失败,都给出短路恒流值的时候的电流
// rt_uint_t change_mode; // 0=测试后电流设置为0;1=达到标准则电流立即为0;2=保持当前电流
};
//动态测试结构体
struct test_change {
rt_uint16_t curr1_set; // 电流1设置值
rt_uint16_t time1_set; // 电流1保持时间设置值,单位0.01s
rt_uint16_t curr2_set; // 电流2设置值
rt_uint16_t time2_set; // 电流2保持时间设置值,单位0.01s
rt_uint16_t k_Rise; // 上升斜率,单位0.001(A/us)
rt_uint16_t k_Fall; // 下降斜率,单位0.001(A/us)
// rt_uint16_t start_time; // 启动后稳定时间,单位ms
// rt_uint16_t work_step; // 总共多少次步进
};
struct test
{
struct test_short short_test;
struct test_change change_test;
struct test_OCP OCP_test;
rt_uint8_t test_mode_old; //进入测试模式后的角色
rt_uint8_t test_mode; // 测试标志位,0=无测试,1=短路测试,2=OCP测试,3=动态测试
rt_uint8_t run_flag; // 运行标志位,0=停止,1=运行,2=继续,3=结束
rt_uint8_t work_step; // 测试步骤,0=初始,1=第一步,2=第二步,3=第三步
rt_uint8_t stop_step; // 停止步骤,0=初始,1=第一步,2=第二步,3=第三步
};
#define SINK_CMD_GET_VOLTAGE 0x20 // 读取变电压板电压
// (需要实时比较设置的快充指令和读回来的快充指令,若有不一样,则重设)(注意vooc模式下数据返回会很慢)
// 发送 0B 00 01 20 loadvh loadvl loadch loadcl nc nc CRC8
// 长度+nc+id+指令+负载电压(2字节,0.01V)+负载电流(2字节,mA)+2个预留字节+CRC8校验
// 接收 15 00 01 20 VH VL qc_data1 qc_data2 qc_data3 qc_data4 qc_data5 qc_data6 ver_h ver_l nc nc nc nc nc nc CRC8
// 长度+nc+ID+指令+2字节电压(0.01V)+6字节快充指令+2字节版本号+6字节预留+CRC8校验
struct sink_vc_t {
rt_uint8_t voltage; // 电压 0.01V
@@ -33,17 +76,9 @@ struct sink_vc_t {
};
#define SINK_CMD_GET_PD 0x13 // 读取源端的PD协议数据(当前为PDO,PPS,PD3.1,AVS协议时有效)
// 发送 05 00 01 13 2A
// 接收 XX 00 01 13 // 长度(根据实际计算)+NC+ID+指令
// 00 00 VMINH VMINL VMAXH VMAXL CURH/PORH CURL/PORL NC NC NC NC NC NC
// 源类型(1字节,00为PDO,03为APDO) + PPS类型(1字节,源类型为3时有效,00为SPR PPS,01为EPR AVS,02为SPR AVS) +
// 最小电压(2字节,mV) + 最大电压(2字节,mV) + 最大电流/功率(2字节,mA/W) + 预留(6字节,当PPS类型为02时有效,意义与前6字节一致)
// 00 00 VMINH VMINL VMAXH VMAXL CURH/PORH CURL/PORL NC NC NC NC NC NC
// ...... CRC8
#define SINK_CMD_SET_CC 0x17 // 设置CC线
// 发送 06 00 01 17 00 2A // 长度+nc+id+指令+CC(0为都选通,1为选择CC1,2为CC2,3为全断开)+CRC8校验
// 接收 05 00 01 17 2A // 长度+nc+id+指令+CRC8校验
// CC 线选通
enum {
@@ -54,8 +89,7 @@ enum {
};
#define SINK_CMD_SET_LEVEL 0x16 // 设置CC线电平
// 发送 06 00 01 16 00 2A // 长度+nc+id+指令+电平等级(0-10,默认7)+CRC8校验
// 接收 05 00 01 16 2A // 长度+nc+id+指令+CRC8校验
// 电平等级
enum {
@@ -72,45 +106,85 @@ enum {
CC_LVL_10 = 10
};
//负载协议
typedef enum {
LOAD_PRO_NONE = 0xFE, // 0.无快充(标准)
LOAD_PRO_QC20 = 0xF8, // 1.QC2.0
LOAD_PRO_QC30 = 0xF6, // 2.QC3.0
LOAD_PRO_FCP = 0xF2, // 3.FCP
LOAD_PRO_AFC = 0xF9, // 4.AFC
LOAD_PRO_SCP = 0xF3, // 5.SCP
LOAD_PRO_VIVO = 0xFD, // 6.VIVO
LOAD_PRO_TFC_RFC = 0xF7, // 7.传音/TFC/RFCN
LOAD_PRO_PDO_MANUAL = 0xFB, // 8.PDO手动
LOAD_PRO_PDO_AUTO = 0xFB, // 9.PDO自动
LOAD_PRO_PPS_MANUAL = 0xFC, // 10.PPS手动
LOAD_PRO_PPS_AUTO = 0xFC, // 11.PPS自动
LOAD_PRO_PD31AVS = 0xE1, // 12.PD3.1
LOAD_PRO_UFCS = 0xE0, // 13.UFCS
LOAD_PRO_VOOC = 0xE2, // 14.VOOC
LOAD_PRO_AVS = 0xE3, // 15.AVS
// 设置快充协议(VOOC,UFCS模式下切换其他模式时,需要先把V+,V-,D+,D-,
// CC等和变电压有关的继电器切至悬空,至少等待1s后,等能读到数据且快充指令正确,再把继电器切回)
// 发送格式 长度+NC+ID+6字节快充数据+CRC8
// 接收 长度+NC+ID+指令+CRC8
TOTAL_LOAD_PROS // 负载协议总数
} eLOAD_PRO;
// 负载协议映射表:十六进制值 → 协议名称
typedef struct {
rt_uint8_t pro_val; // 协议对应的数值(如0xF8
int pro_name; // 协议名称(如"QC2.0"
} LoadProMap_t;
static const LoadProMap_t load_pro_map[] = {
{LOAD_PRO_NONE, 10},
{LOAD_PRO_QC20, 11},
{LOAD_PRO_QC30, 12},
{LOAD_PRO_FCP, 13},
{LOAD_PRO_AFC, 14},
{LOAD_PRO_SCP, 15},
{LOAD_PRO_VIVO, 16},
{LOAD_PRO_TFC_RFC, 17},
{LOAD_PRO_PDO_MANUAL, 18},
{LOAD_PRO_PDO_AUTO, 19},
{LOAD_PRO_PPS_MANUAL, 20},
{LOAD_PRO_PPS_AUTO, 21},
{LOAD_PRO_PD31AVS, 22},
{LOAD_PRO_UFCS, 23},
{LOAD_PRO_VOOC, 24},
{LOAD_PRO_AVS, 25}
};
// 命令码区分:负载(0x11-0x1F)
#define CMD_LOAD_QC20 0x11 // 负载-QC2.0
#define CMD_LOAD_QC30 0x12 // 负载-QC3.0
#define CMD_LOAD_FCP 0x13 // 负载-FCP
#define CMD_LOAD_AFC 0x14 // 负载-AFC
#define CMD_LOAD_SCP 0x15 // 负载-SCP
#define CMD_LOAD_VIVO 0x16 // 负载-VIVO
#define CMD_LOAD_TFC 0x17 // 负载-TFC
#define CMD_LOAD_PD0_MAN 0x18 // 负载-PD0手动
#define CMD_LOAD_PD0_AUTO 0x19 // 负载-PDO自动
#define CMD_LOAD_PPS_MAN 0x1A // 负载-PPS手动
#define CMD_LOAD_PPS_AUTO 0x1B // 负载-PPS自动
#define CMD_LOAD_PD31 0x1C // 负载-PD3.1
#define CMD_LOAD_UFCS 0x1D // 负载-UFCS
#define CMD_LOAD_VOOC 0x1E // 负载-VOOC
#define CMD_LOAD_AVS 0x1F // 负载-AVS
#define LOAD_PRO_MAP_NUM (sizeof(load_pro_map)/sizeof(load_pro_map[0])) // 映射表长度
#define SINK_CMD_SET_QC20 0xF8 // QC2.0
// QC2.0 电压5V/9V/12V/20V 命令:0A 00 01 F8 5A 00 00 00 00 2A
// 第5个字节为电压(0.1V)
#define SINK_CMD_SET_QC30 0xF6 // QC3.0
// QC3.0 电压3.3-20V 命令:0A 00 01 F6 5A 00 00 00 00 2A
// 第5个字节为电压(0.1V)
#define SINK_CMD_SET_FCP 0xF2 // FCP
// FCP 电压5V/9V/12V 命令:0A 00 01 F2 78 00 00 00 00 2A
// 第5个字节为电压(0.1V)
#define SINK_CMD_SET_AFC 0xF9 // AFC
// AFC 命令:0A 00 01 F9 46 00 00 00 00 2A
// 第5个字节为变电压数据,详细参考AFC文档
#define SINK_CMD_SET_SCP 0xF3 // SCP
// SCP 命令:0A 00 01 F3 27 10 0F A0 00 2A
// 5,6字节为电压(mv)7,8字节为电流(mA)
#define SINK_CMD_SET_VIVO 0xFD // VIVO
// VIVO 命令:0A 00 01 FD 27 10 00 00 00 2A
// 5,6字节为电压(mv)7,8字节为电流(mA)
#define SINK_CMD_SET_TFC 0xF7 // TFC 传音
// 传音/TFC 命令:0A 00 01 F7 2E E0 00 00 00/01 2A
// 5,6字节为电压(mv), 7,8字节为电流(mA), 9字节为RFC/TFC选择
#define SINK_CMD_SET_PD0 0xFB // PD0 手动/自动
// PDO手动,需要设定组号,电压和产品相关,命令:0A 00 01 FB 05 00 00 00 00 2A
// 5字节为组号
// PDO自动,组号设为0,自动变到指定电压,命令:0A 00 01 FB 00 2E E0 00 00 2A
// 5字节为组号,6,7字节为电压(mv),8、9字节为电流(mA)
enum {
SET_MANUAL = 0, // 手动
@@ -118,39 +192,138 @@ enum {
};
#define SINK_CMD_SET_PPS 0xFC // PPS 手动/自动
// PPS手动,需要设定组号、电压、电流,电流0最大, 命令: 0A 00 01 FC 06 4E 20 00 00 2A
// 5字节为组号,6,7字节为电压(mv),8、9字节为电流(mA)
// PPS自动,组号设为0,设定电压、电流,电流0最大,命令:0A 00 01 FC 00 4E 20 00 00 2A
// 5字节为组号,6,7字节为电压(mv),8、9字节为电流(mA)
#define SINK_CMD_SET_PD3P1 0xE1 // PD3.1
// PD3.1, 命令:0A 00 01 E1 00 2328 07d0 2A (组号设置和电压设置都支持)
// 5字节为组号,6,7字节为电压(mv),8、9字节为电流(mA)
#define SINK_CMD_SET_UFCS 0xE0 // UFCS
// UFCS,命令:0A 00 01 E0 00 2328 07d0 2A (组号设置和电压设置都支持)
// 5字节为组号,6,7字节为电压(mv),8、9字节为电流(mA)
#define SINK_CMD_SET_VOOC 0xE2 // VOOC
// VOOC,电压10/11V, 命令:0A 00 01 E2 00 0000 0000 2A
#define SINK_CMD_SET_AVS 0xE3 // AVS
// AVS,命令:0A 00 01 E3 00 4e 20 07 d0 2A (组号设置和电压设置都支持)
// 5字节为组号,6,7字节为电压(mv),8、9字节为电流(mA)
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 参数结构
struct chrg_sink_t {
rt_uint16_t loadv; // 负载电压 0.01V
rt_uint16_t loadc; // 负载电流 mA
rt_uint16_t loadv; // 设置负载电压 0.01V
rt_uint16_t loadc; // 设置负载电流 mA
rt_uint16_t pro_loadv; // 设置协议负载电压 0.01V
rt_uint16_t pro_loadc; // 设置协议负载电流 mA
rt_uint16_t volt_on; // 启动电压
rt_uint16_t Pro_Group; // 设置组号
struct sink_vc_t vc;
struct vc_pd_t pd_get[2];
rt_uint8_t cc_onoff; // 设置CC线开关
rt_uint8_t cc_lvl; // 设置CC线电平等级(0-10,默认7)
struct test test; //负载测试10++++++++++++++++
rt_uint16_t protocol; //协议类型
rt_uint8_t cc_set; // 选择cc线
rt_uint8_t cc_lvl; // 设置CC线电平等级(0-10,默认7)
rt_uint8_t Now_State; // 当前状态,0=停止,1=运行
rt_uint8_t On_work;
rt_uint8_t change_cv_flag;
rt_uint8_t change_source_flag; // 从sink切换到source标志位
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 //
//short测试
#define SHORT_TEST 0x01
//短路测试寄存器
#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 //无论测试成功或者失败,都给出短路恒流值的时候的电压
//短路测试执行步骤
#define SET_SHORT_CMD_MODE 0x01
#define SET_SHORT_WRITE_ENABLE 0x02
#define SET_SHORT_RUN 0x03
//短路测试结束步骤
#define READ_SHORTEST_VOLT_SHORT 0x03
#define READ_SHORTEST_CURRENT_SHORT 0x04
//OCP测试
#define OCP_TEST 0X02
//OCP测试功率板寄存器
#define ModbusRTU_OCPTest_CMD_MODE_FLAG 0x43 //16位;0x0101; 01启动,低字节的01,保持/卸载;
#define ModbusRTU_OCPTest_StartCurrent 0x44 //起始电流
#define ModbusRTU_OCPTest_StopCurrent 0x45 //终止电流
#define ModbusRTU_OCPTest_Step_CURR 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_HOLD_CURR 0x4A
//OCP测试步骤
#define SET_OCP_STARTCURR 0x01
#define SET_OCP_ENDCURR 0x02
#define SET_OCP_STEP 0x03
#define SET_OCP_STEP_HOLD_TIME 0x04
#define SET_OCP_HOLD_TIME 0x05
#define SET_OCP_CMD_MODE_RUN 0x06
#define SET_OCP_WRITE_ENABLE 0x07
#define SET_OCP_RUNNING 0x08
#define SET_OCP_HOLD_END_HAVE_CURR 0x09
#define SINK_OCP_STOP_VOLT 0x0A
//OCP测试结果读取
#define READ_OCP_VTRIG_STOP 0x03
#define READ_OCP_VOLT_OCP 0x04
#define READ_OCP_CURRENT_OCP 0x05
//动态测试
#define DYNA_TEST 0X03
//动态测试功率板寄存器
#define ModbusRTU_DYNA_CMD_MODE_FLAG 0x4B //动态测试 CMD启动、退出、 以及模式:Continuous、PULSE、ToggleLSB8 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 SET_DYNA_CURR1 0x01
#define SET_DYNA_CURR2 0x02
#define SET_DYNA_TIME1 0x03
#define SET_DYNA_TIME2 0x04
#define SET_DYNA_RISE_SLEW_RATE 0x05
#define SET_DYNA_FALL_SLEW_RATE 0x06
#define SET_DYNA_CND_MODE 0x07
#define SET_DYNA_WRITE_ENABLE 0x08
#define SET_DYNA_RUNNING 0x09
//测试停止通用前三步
#define TEST_STOP_CMD_MODE 0x00
#define TEST_STOP_RUN 0x01
#define TEST_STOP_REL 0x02
//短路和负载共用运行寄存器值
#define ModbusRTU_DYNA_CMD_MODE_RUN_NO_CURR 0x0100 //在保持时间结束后电流为0
//#define ModbusRTU_DYNA_CMD_MODE_RUN_KEPP 0x0101 //保持时间后恢复之前电流
#define ModbusRTU_DYNA_CMD_MODE_RUN_ALWAYS_KEPP 0x0101 //一直保持拉低后的电流
//动态测试运行寄存器值
#define ModbusRTU_DYNA_CMD_MODE_RUN 0x0101 //动态启动
//测试通用停止寄存器值
#define ModbusRTU_DYNA_CMD_MODE_STOP 0x0000 //停止
#define ModbusRTU_SYS_Reset 0x61 //系统复位指令,如果异常过压,通常发指令,让系统复位
/*****************************************************************
sink_get_vc
sink电压电流查询请求
@@ -200,7 +373,18 @@ extern int sink_set_cc_lvl (rt_uint8_t lvl);
-
*****************************************************************/
extern int sink_set_pd (rt_uint8_t pd, rt_uint8_t *buf);
// ===================== 负载测试函数声明 =====================
extern void sink_test_short_set (struct chrg_switch_t *pSW, rt_uint8_t *pData, rt_uint8_t run_flag);
extern void sink_test_ocp_set (struct chrg_switch_t *pSW, rt_uint8_t *pData, rt_uint8_t run_flag);
extern void sink_test_dynamic_set(struct chrg_switch_t *pSW, rt_uint8_t *pData, rt_uint8_t run_flag);
extern void chrg_nor_sink_short_test(rt_uint8_t ch, struct chrg_switch_t *pSW);
extern void chrg_nor_sink_OCP_test(rt_uint8_t ch, struct chrg_switch_t *pSW);
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);
#endif
+801 -23
View File
@@ -8,13 +8,14 @@
******************************************************************************/
#include <rtthread.h>
#include "chrg_source.h"
#include "chrg_north.h"
#include <string.h>
#include "chrg_north_pkg.h"
#include "chrg_utils.h"
#include "chrg_roll_nor.h"
#include "chrg_source.h"
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
};
/*****************************************************************
source_get_vc
source电压电流查询请求
@@ -78,6 +79,539 @@ int source_set_cc_lvl (rt_uint8_t lvl)
return chrg_north_send(frame, len);
}
/*****************************************************************
source_set_cc_lvl
source cc
lvl:
-
<0: >0:
-
*****************************************************************/
int source_set_cc_choose (rt_uint8_t cc_set)
{
rt_uint16_t len = 0;
rt_uint8_t data[8] = {0};
rt_uint8_t frame[16] = {0};
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 ");
}
rt_kprintf("\n");
return chrg_north_send(frame, len);
}
/*
*/
rt_uint8_t parse_mulit_gear_One(rt_uint16_t min_volt_mv,rt_uint16_t max_volt_mv, rt_uint16_t max_curr_ma) {
// 清空缓冲区
rt_memset(Pro_Group_VCMM, 0, sizeof(Pro_Group_VCMM));
Pro_Group_VCMM[0][0] = 0x00; // src
Pro_Group_VCMM[0][1] = 0x00; // pps
Pro_Group_VCMM[0][2] = (min_volt_mv >> 8) & 0xFF; // vmin_H
Pro_Group_VCMM[0][3] = min_volt_mv & 0xFF; // vmin_L
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
rt_kprintf("H_C=%02x",Pro_Group_VCMM[0][6]);
Pro_Group_VCMM[0][7] = max_curr_ma & 0xFF; // cur_set_L
rt_kprintf("L_C=%02x\n",Pro_Group_VCMM[0][7]);
return 0;
}
/*****************************************************************
parse_power_single_gear
QC3.0/QC2.0/SCPB
protoCmd: (0x27/0x28/0x23)
pData: ++CC线++
reqLen:
pSW:
-
-
+(1)+CC线(1)+(2)+(2)
*****************************************************************/
void parse_power_single_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_curr)
{
rt_uint16_t min_volt_mv = 0; // 最小输出电压(mv)
rt_uint16_t max_volt_mv = 0; // 最大输出电压(mV)
rt_uint16_t max_curr_ma = 0; // 最大输出电流(mA)
// 数据区索引:0=状态+通道,1=CV,2=CC线,3-4=最小电压,5-6=最大电压,7-8最大电流
min_volt_mv = u8v_to_u16(&pData[3]); // 大端
max_volt_mv = u8v_to_u16(&pData[5]); // 大端
max_curr_ma = u8v_to_u16(&pData[7]); // 大端
*protect_curr = u8v_to_u16(&pData[9]); // 大端
// rt_kprintf("\n");
// for(int i=0;i<10;i++){
// rt_kprintf("%0x",pData[i]);
// }
// rt_kprintf("\n");
#if PRO_TEST_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
*pro_gear_idx = 1; // 单档协议固定1
// 按协议命令码赋值
switch (protoCmd)
{
case 0x27: // QC3.0
*pro = PRO_QC30;
break;
case 0x28: // QC2.0
*pro = PRO_QC20;
break;
case 0x23: // SCPB
*pro = PRO_SCPB;
break;
default:
rt_kprintf("单档电源协议不支持:0x%02X\n", protoCmd);
return;
}
parse_mulit_gear_One(min_volt_mv,max_volt_mv,max_curr_ma);
return;
}
/*****************************************************************
parse_pd_11group_pdo
PD协议11组PDO数据8
pdoData: 11PDO数据缓冲区44
pdo_group_num: PDO组数
pSW:
-
-
1. type映射0src=0/pps=01src=03/pps=002src=03/pps=003src=03/pps=01
2. 16/
*****************************************************************/
void parse_pd_11group_pdo(rt_uint8_t *pdoData, rt_uint8_t pdo_group_num) {
rt_uint32_t pdo_val = 0;
rt_uint8_t pdo_type = 0;
rt_uint16_t vmin_mv = 0, vmax_mv = 0, cur_power = 0; // 16位原始值
// 清空缓冲区
rt_memset(Pro_Group_VCMM, 0, sizeof(Pro_Group_VCMM));
for (rt_uint8_t i = 0; i < pdo_group_num; i++) {
// 1. 拼接32位PDO值(低字节在前)
pdo_val = (rt_uint32_t)pdoData[i*4 + 3] << 24 |
(rt_uint32_t)pdoData[i*4 + 2] << 16 |
(rt_uint32_t)pdoData[i*4 + 1] << 8 |
(rt_uint32_t)pdoData[i*4];
// 2. 提取PDO类型(Bit30-31
pdo_type = (pdo_val >> 30) & 0x03;
// 3. 按type映射src和pps
switch (pdo_type) {
case 0: // FPDO → src=0x00, pps=0x00
Pro_Group_VCMM[i][0] = 0x00;
Pro_Group_VCMM[i][1] = 0x00;
break;
case 1: // EPRPDO → src=0x03, pps=0x00
Pro_Group_VCMM[i][0] = 0x00;
Pro_Group_VCMM[i][1] = 0x01;
break;
case 2: // PPS → src=0x03, pps=0x00
Pro_Group_VCMM[i][0] = 0x03;
Pro_Group_VCMM[i][1] = 0x00;
break;
case 3: // EPR AVS → src=0x03, pps=0x01
Pro_Group_VCMM[i][0] = 0x03;
Pro_Group_VCMM[i][1] = 0x01;
break;
default:
rt_kprintf("parse_pd_11group_pdo: unknown PDO type=%d (index=%d)\n", pdo_type, i);
continue;
}
// 4. 解析电压/电流/功率(16位值)
switch (pdo_type) {
case 0: // FPDO(固定电源)
case 1: // EPRPDO(固定电源)
vmin_mv = vmax_mv = ((pdo_val >> 10) & 0x03FF) * 50; // 电压(mV)
cur_power = (pdo_val & 0x03FF) * 10; // 电流(mA)
break;
case 2: // PPS(可编程电源)
vmin_mv = ((pdo_val >> 8) & 0x00FF) * 100; // 最小电压(mV)
vmax_mv = ((pdo_val >> 17) & 0x00FF) * 100; // 最大电压(mV)
cur_power = (pdo_val & 0x7F) * 50; // 电流(mA)
break;
case 3: // EPR AVS(功率型)
vmin_mv = ((pdo_val >> 8) & 0x00FF) * 100; // 最小电压(mV)
vmax_mv = ((pdo_val >> 17) & 0x1FF) * 100; // 最大电压(mV)
cur_power = (pdo_val & 0xFF) * 1; // 功率(W)
break;
default:
vmin_mv = vmax_mv = cur_power = 0;
break;
}
// 5. 拆分高低字节填充缓冲区(核心)
// 最小电压拆分
Pro_Group_VCMM[i][2] = (vmin_mv >> 8) & 0xFF; // vmin_H
Pro_Group_VCMM[i][3] = vmin_mv & 0xFF; // vmin_L
// 最大电压拆分
Pro_Group_VCMM[i][4] = (vmax_mv >> 8) & 0xFF; // vmax_H
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
// 调试打印
rt_kprintf("max_H=%d",Pro_Group_VCMM[i][4]);
rt_kprintf("max_L=%d",Pro_Group_VCMM[i][5]);
rt_kprintf("min_H=%d",Pro_Group_VCMM[i][2]);
rt_kprintf("min_L=%d",Pro_Group_VCMM[i][3]);
if (pdo_type == 3) { // EPR AVS 打印功率
rt_kprintf("PDO[%d]:src=0x%02X, pps=0x%02X, V_MIN=%dmV(0x%02X%02X),V_MAX=%dmV(0x%02X%02X),C/P=%dW(0x%02X%02X)\n",
i, Pro_Group_VCMM[i][0], Pro_Group_VCMM[i][1],
vmin_mv, Pro_Group_VCMM[i][2], Pro_Group_VCMM[i][3],
vmax_mv, Pro_Group_VCMM[i][4], Pro_Group_VCMM[i][5],
cur_power, Pro_Group_VCMM[i][6], Pro_Group_VCMM[i][7]);
} else { // 其他类型打印电流
rt_kprintf("PDO[%d]: src=0x%02X, pps=0x%02X, V_MIN=%dmV(0x%02X%02X), V_MAX=%dmV(0x%02X%02X),C/P=%dmA(0x%02X%02X)\n",
i, Pro_Group_VCMM[i][0], Pro_Group_VCMM[i][1],
vmin_mv, Pro_Group_VCMM[i][2], Pro_Group_VCMM[i][3],
vmax_mv, Pro_Group_VCMM[i][4], Pro_Group_VCMM[i][5],
cur_power, Pro_Group_VCMM[i][6], Pro_Group_VCMM[i][7]);
}
#endif
}
}
/*****************************************************************
parse_power_pdo_gear
PDO档电源协议解析函数PD协议
protoCmd: (0x2A)
pData: ++CC线+PDO组数+11PDO+++
reqLen:
pSW:
-
-
+(1)+CC线(1)+PDO组数(1)+11PDO(44)+(20)+(2)+(2)
*****************************************************************/
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)
{
rt_uint8_t pdo_group_num = 0; // PDO组数
rt_int16_t comp_volt_mv = 0; // 补偿电压(mV)
// 数据区索引:0=状态+通道,1=CC线,2=恒压恒流模式,3=PDO组数(bit12-15)
rt_kprintf("pdata=%04x",pData[3]);
pdo_group_num = (pData[3] >> 4) & 0x0F; // Bit12-15提取组数
rt_kprintf("num=%d\n",pdo_group_num);
*pro = PRO_PD0PSS;
*pro_gear_idx = pdo_group_num;
// 解析11组PDO(小端序,44字节)
parse_pd_11group_pdo(&pData[4], pdo_group_num);
// 解析保留字段(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
rt_kprintf("project_curr=%d mA, add_volt=%d mV\n", *protect_ma, comp_volt_mv);
// #endif.
}
/*****************************************************************
parse_mulit_gear_more
-8
pData: PDO原始数据缓冲区 gear_num: PDO组数
-
0: 1:
src/pps映射规则
*****************************************************************/
rt_uint8_t parse_mulit_gear_more(rt_uint8_t *pData, rt_uint8_t gear_num) {
// 入参合法性校验
if (pData == RT_NULL || gear_num == 0 || gear_num > 11) {
rt_kprintf("parse_mulit_gear_pd0:invalid params (gear_num=%d)\n", gear_num);
return 1;
}
// 清空缓冲区
rt_memset(Pro_Group_VCMM, 0, sizeof(Pro_Group_VCMM));
rt_uint32_t pdo_val = 0;
rt_uint8_t pdo_type = 0;
rt_uint16_t vmin_mv = 0, vmax_mv = 0, cur_power = 0;
for (rt_uint8_t i = 0; i < gear_num; i++) {
// 终止条件:PDO电压字段为0则停止
// 1. 拼接32位PDO值(低字节在前)
pdo_val = (rt_uint32_t)pData[i*4 + 3] << 24 |
(rt_uint32_t)pData[i*4 + 2] << 16 |
(rt_uint32_t)pData[i*4 + 1] << 8 |
(rt_uint32_t)pData[i*4];
// 2. 提取PDO类型(Bit30-31
pdo_type = (pdo_val >> 30) & 0x03;
// 3. 按type映射src和pps
switch (pdo_type) {
case 0: // FPDO → src=0x00, pps=0x00
Pro_Group_VCMM[i][0] = 0x00;
Pro_Group_VCMM[i][1] = 0x00;
break;
case 1: // EPRPDO → src=0x03, pps=0x00
Pro_Group_VCMM[i][0] = 0x00;
Pro_Group_VCMM[i][1] = 0x01;
break;
case 2: // PPS → src=0x03, pps=0x00
Pro_Group_VCMM[i][0] = 0x03;
Pro_Group_VCMM[i][1] = 0x00;
break;
case 3: // EPR AVS → src=0x03, pps=0x01
Pro_Group_VCMM[i][0] = 0x03;
Pro_Group_VCMM[i][1] = 0x01;
break;
default:
rt_kprintf("parse_mulit_gear_pd0:unknown PDO type=%d\n", pdo_type);
continue;
}
// 4. 解析电压/电流/功率(16位值)
switch (pdo_type) {
case 0: // FPDO(固定电源)
case 1: // EPRPDO(固定电源)
vmin_mv = vmax_mv = ((pdo_val >> 10) & 0x03FF) * 50; // 电压(mV)
cur_power = (pdo_val & 0x03FF) * 10; // 电流(mA)
break;
case 2: // PPS(可编程电源)
vmin_mv = ((pdo_val >> 8) & 0x00FF) * 100; // 最小电压(mV)
vmax_mv = ((pdo_val >> 17) & 0x00FF) * 100; // 最大电压(mV)
cur_power = (pdo_val & 0x7F) * 50; // 电流(mA)
break;
case 3: // EPR AVS(功率型)
vmin_mv = ((pdo_val >> 8) & 0x00FF) * 100; // 最小电压(mV)
vmax_mv = ((pdo_val >> 17) & 0x1FF) * 100; // 最大电压(mV)
cur_power = (pdo_val & 0xFF) * 1; // 功率(W)
break;
default:
vmin_mv = vmax_mv = cur_power = 0;
break;
}
// 5. 拆分高低字节填充缓冲区
Pro_Group_VCMM[i][2] = (vmin_mv >> 8) & 0xFF; // vmin_H
Pro_Group_VCMM[i][3] = vmin_mv & 0xFF; // vmin_L
Pro_Group_VCMM[i][4] = (vmax_mv >> 8) & 0xFF; // vmax_H
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
// 调试打印
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);
#endif
}
return 0;
}
/*****************************************************************
parse_power_multi_gear_more
-FCP/AFC/SCPA
protoCmd: (0x22/0x29/0x2C/0x2F)
pData: ++CC线++PDO组++
reqLen:
pSW:
-
-
1. FCP/AFC/SCPA(1)+PDO组(4*N)+(2)+(2)
2. UFCS(1)+PDO组(4*3)+(2)+(2)
*****************************************************************/
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)
{
rt_uint8_t gear_num = 0; // 挡位数量
rt_int16_t comp_volt_mv = 0;// 补偿电压(mV)
// 数据区索引:0=状态+通道,1=CC线,2=恒压恒流模式,3=挡位数量
gear_num = pData[3];
//挡位数量
if(gear_num > 11) {
rt_kprintf("THE GEARNUM MORE 11 GEAR_NUM=%d\n", gear_num);
return;
}
*pro_gear_idx = gear_num;
rt_kprintf("pro_gear_idx = %d\n",gear_num);
// 解析保护电流和补偿电压(不同协议偏移不同)
switch (protoCmd)
{
case 0x22: // FCP (挡位数量+PDO组(4*4)+保护电流+补偿电压)
*pro = PRO_FCP;
break;
case 0x29: // AFC (同FCP)
*pro = PRO_AFC;
break;
case 0x2F: // SCPA (同FCP)
*pro = PRO_SCPA;
break;
default:
rt_kprintf("THE PRO NO MORE PRO PRO=%02X\n", protoCmd);
return;
}
*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
for(int i = 0;i<30;i++){
rt_kprintf("data[%d]=%02x",i,pData[i]);
}
rt_kprintf("protect_curr=%d\n",*protect_ma);
#endif
// 解析PDO组(小端序)
parse_mulit_gear_more(&pData[4],gear_num);
}
/*****************************************************************
parse_ufcs_gear
UFCS协议单组PDO数据EPR AVS类型8
pData: UFCS单组PDO原始数据缓冲区4
gear_idx: 0
-
0: 1:
UFCS协议固定为EPR AVS类型Bit30-31=3
Bit0-7(1=1W) Bit8-15(1=100mV) Bit17-25(1=100mV)
0+PPS值
*****************************************************************/
rt_uint8_t parse_ufcs_gear_more(rt_uint8_t *pData, rt_uint8_t gear_num) {
// 入参合法性校验
if (pData == RT_NULL || gear_num == 0 || gear_num > 11) {
rt_kprintf("parse_ufcs_gear_more:invalid params (gear_num=%d)\n", gear_num);
return 1;
}
// 清空缓冲区
rt_memset(Pro_Group_VCMM, 0, sizeof(Pro_Group_VCMM));
rt_uint32_t pdo_val = 0;
rt_uint16_t vmin_mv = 0, vmax_mv = 0, cur_ma = 0;
for (rt_uint8_t i = 0; i < gear_num; i++) {
// 1. 拼接32位PDO
pdo_val = (rt_uint32_t)pData[i*4 + 3] << 24 |
(rt_uint32_t)pData[i*4 + 2] << 16 |
(rt_uint32_t)pData[i*4 + 1] << 8 |
(rt_uint32_t)pData[i*4];
// ================= 固定 =================
Pro_Group_VCMM[i][0] = 0x00;
Pro_Group_VCMM[i][1] = 0x00;
// ================= 位规则 =================
// Bit0-6 电流 1=50mA
cur_ma = (pdo_val & 0x3F) * 100;//原50,乘2了
// Bit8-15 最小电压 1=100mV
vmin_mv = ((pdo_val >> 8) & 0xFF) * 100;
// Bit17-25 最大电压 1=100mV
vmax_mv = ((pdo_val >> 17) & 0x1FF) * 100;
// ================= 填充缓冲区 =================
Pro_Group_VCMM[i][2] = (vmin_mv >> 8) & 0xFF;
Pro_Group_VCMM[i][3] = vmin_mv & 0xFF;
Pro_Group_VCMM[i][4] = (vmax_mv >> 8) & 0xFF;
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
// ================= 打印格式 =================
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);
#endif
}
return 0;
}
/*****************************************************************
parse_power_ufcs
UFCS协议专属解析函数
pData: ++CC线++PDO组++
reqLen:
pro_gear_idx:
pro: PRO_UFCS
-
-
UFCS固定格式(1)+PDO组(4*3)+(2)+(2)
UFCS协议
*****************************************************************/
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)
{
rt_uint8_t gear_num = 0;
rt_int16_t comp_volt_mv = 0;
gear_num = pData[3];
if(gear_num > 11) {
rt_kprintf("parse_power_ufcs: gear_num >11, set=3\n");
gear_num = 3;
}
*pro_gear_idx = gear_num;
*pro = PRO_UFCS;
// UFCS偏移
*protect_ma = u8v_to_u16(&pData[4 + 12]);
// for(int i = 0;i<24;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
rt_kprintf("parse_power_ufcs:gear=%d,protect=%dmA,comp=%dmV\n",
gear_num,*protect_ma, comp_volt_mv);
//#endif
// 调用下面的循环解析
parse_ufcs_gear_more(&pData[4], gear_num);
}
static rt_uint8_t pd_fill_single_group(rt_uint8_t *data, rt_uint8_t start_idx, rt_uint8_t group_idx,rt_uint16_t max_cur)
{
// 校验索引合法性
if (group_idx >= PD_VOLTAGE_CNT) {
rt_kprintf("ERROR GROUP IDX EXCEED IDX=%d)\n", group_idx);
return 0;
}
rt_uint8_t idx = start_idx;
const Pro_Group *target_group = &pd_voltage_map[group_idx]; // 仅取目标挡位
// 1. 填充pro + src2字节)
data[idx++] = target_group->src;
data[idx++] = target_group->pps;
// 2. 填充电压最小值(2字节,高8位+低8位)
data[idx++] = (target_group->v_min >> 8) & 0xff;
data[idx++] = target_group->v_min & 0xff;
// 3. 填充电压最大值(2字节,高8位+低8位)
data[idx++] = (target_group->v_max >> 8) & 0xff;
data[idx++] = target_group->v_max & 0xff;
// 4. 填充电流设置值(2字节,高8位+低8位)
data[idx++] = (max_cur >> 8) & 0xff;
data[idx++] = max_cur & 0xff;
// 5. 填充保留位(6字节全0
for (rt_uint8_t j = 0; j < 6; j++) {
data[idx++] = 0x00;
}
return idx - start_idx; // 返回填充的总字节数
}
/*****************************************************************
source_set_pd
source PD协议
@@ -89,29 +623,273 @@ int source_set_cc_lvl (rt_uint8_t lvl)
int source_set_pd (rt_uint8_t pro, rt_uint8_t src, rt_uint8_t pps,
rt_uint16_t vmax, rt_uint16_t vmin, rt_int16_t max_cur)
{
rt_uint16_t len = 0;
rt_uint8_t data[32] = {0};
rt_uint8_t frame[32] = {0};
rt_uint8_t data[80] = {0};
rt_uint8_t frame[80] = {0};
rt_uint8_t send_len = 0; //数据长度
rt_uint8_t max_group_idx = 0; //挡位索引
data[0] = pro; //协议
//rt_kprintf("cur_pro=%d",max_cur);
if(pro==0x07||pro==0x08||pro==0x03){
data[1] = 0;//src
data[2] = 0;//pps
data[3] = 0x13;//固定电压最小值为5V
data[4] = 0x88;
data[5] = (vmax>>8)&0xff;//电压最大值为设定电压
data[6] = vmax&0xff;
data[7] = (max_cur>>8)&0xff;//电流输出为设置值
data[8] = max_cur&0xff;
for (rt_uint8_t j = 9; j < 14; j++) {
data[j] = 0x00;
}
send_len=15;
}
else{
switch (vmax)
{
case 5000: max_group_idx = 0; break;
case 9000: max_group_idx = 1; break;
case 12000: max_group_idx = 2; break;
case 20000: max_group_idx = 3; break;
case 48000: max_group_idx = 4; break;
default:rt_kprintf("VOLT ERROR");break;
}
rt_uint8_t idx = 1; //从data[1]开始填充
// 循环填充从0到max_group_idx的所有挡位
for (rt_uint8_t i = 0; i <= max_group_idx; i++) {
rt_uint8_t fill_len = pd_fill_single_group(data, idx, i,max_cur);
if (fill_len == 0) {
rt_kprintf("Error: fill group %d failed\n", i);
return -1;
}
idx += fill_len; // 偏移到下一组起始位置
}
send_len = idx; // 总填充字节数
}
chrg_north_pkg_encode(ID_SOURCE, SRC_CMD_SET_PROTOCOL, data, send_len, frame, &len);
return chrg_north_send(frame, len);
}
data[0] = pro;
data[1] = src;
data[2] = pps;
u16_to_u8v(vmax, &data[3]);
u16_to_u8v(vmin, &data[5]);
u16_to_u8v(max_cur, &data[7]);
data[9] = 0x00;
data[10] = 0x00;
data[11] = 0x00;
data[12] = 0x00;
data[13] = 0x00;
data[14] = 0x00;
/*****************************************************************
pd_fill_single_group
PD挡位的协议数据
data: start_idx: group_idx:0=5V,1=9V...4=PPS
-
0:/ >0:14
-
*****************************************************************/
rt_uint8_t pd_fill_single_group_com(rt_uint8_t *data, rt_uint8_t start_idx, rt_uint8_t gear)
{
// 核心:直接索引已拆分好的高低位缓冲区,按位填充(无任何多余运算)
rt_uint8_t idx = start_idx;
// 1. src + pps2字节)
data[idx++] = Pro_Group_VCMM[gear][0];
data[idx++] = Pro_Group_VCMM[gear][1];
// 2. 最小电压(高+低,直接取已拆分好的值)
data[idx++] = Pro_Group_VCMM[gear][2];
data[idx++] = Pro_Group_VCMM[gear][3];
// 3. 最大电压(高+低,直接取已拆分好的值)
data[idx++] = Pro_Group_VCMM[gear][4];
data[idx++] = Pro_Group_VCMM[gear][5];
// 4. 电流/功率(高+低,直接取已拆分好的值)
data[idx++] = Pro_Group_VCMM[gear][6];
data[idx++] = Pro_Group_VCMM[gear][7];
// 5. 保留位6字节(直接填0
memset(&data[idx], 0x00, 6);
idx+=6;
return idx - start_idx; // 返回填充的总字节数
}
chrg_north_pkg_encode(ID_SOURCE, SRC_CMD_SET_PROTOCOL, data, 15, frame, &len);
rt_uint8_t pd_fill_single_group_need_src_com(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;
// 1. src + pps2字节)
data[idx++] = 0x00;
data[idx++] = 0x00;
// 2. 最小电压(高+低,直接取已拆分好的值)
data[idx++] = 0x13;
data[idx++] = 0x88;
// 3. 最大电压(高+低,直接取已拆分好的值)
data[idx++] = 0x13;
data[idx++] = 0x88;
// 4. 电流/功率(高+低,直接取已拆分好的值)
data[idx++] = source->protective_curr >> 8;
data[idx++] = source->protective_curr & 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);
// 2. 最小电压(高+低,直接取已拆分好的值)
data[idx++] = source->min_vol >> 8;
data[idx++] = source->min_vol & 0xFF;
// 3. 最大电压(高+低,直接取已拆分好的值)
data[idx++] = source->max_vol >> 8;
data[idx++] = source->max_vol & 0xFF;
// 4. 电流/功率(高+低,直接取已拆分好的值)
data[idx++] = source->protective_curr >> 8;
data[idx++] = source->protective_curr & 0xFF;
// 5. 保留位6字节(直接填0
memset(&data[idx], 0x00, 6);
idx+=6;
return idx - start_idx; // 返回填充的总字节数
}
rt_uint8_t pd_fill_single_group_no_src_com(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;
// 1. src + pps2字节)
data[idx++] = 0x00;
data[idx++] = 0x00;
// 2. 最小电压(高+低,直接取已拆分好的值)
data[idx++] = source->min_vol >> 8;
data[idx++] = source->min_vol & 0xFF;
// 3. 最大电压(高+低,直接取已拆分好的值)
data[idx++] = source->max_vol >> 8;
data[idx++] = source->max_vol & 0xFF;
// 4. 电流/功率(高+低,直接取已拆分好的值)
data[idx++] = source->protective_curr >> 8;
data[idx++] = source->protective_curr & 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 idx = start_idx;
struct chrg_src_t *source = &psw->source;
// 1. src + pps2字节)
data[idx++] = 0x00;
data[idx++] = 0x00;
// 2. 最小电压(高+低,直接取已拆分好的值)
data[idx++] = 0x13;
data[idx++] = 0x88;
// 3. 最大电压(高+低,直接取已拆分好的值)
data[idx++] = 0x13;
data[idx++] = 0x88;
// 4. 电流/功率(高+低,直接取已拆分好的值)
data[idx++] = source->protective_curr >> 8;
data[idx++] = source->protective_curr & 0xFF;
// 5. 保留位6字节(直接填0
memset(&data[idx], 0x00, 6);
idx+=6;
// 1. src + pps2字节)
data[idx++] = 0x00;
data[idx++] = 0x00;
// 2. 最小电压(高+低,直接取已拆分好的值)
data[idx++] = source->max_vol >> 8;
data[idx++] = source->max_vol & 0xFF;
// 3. 最大电压(高+低,直接取已拆分好的值)
data[idx++] = source->max_vol >> 8;
data[idx++] = source->max_vol & 0xFF;
// 4. 电流/功率(高+低,直接取已拆分好的值)
data[idx++] = source->protective_curr >> 8;
data[idx++] = source->protective_curr & 0xFF;
// 5. 保留位6字节(直接填0
memset(&data[idx], 0x00, 6);
idx+=6;
return idx - start_idx; // 返回填充的总字节数
}
rt_uint8_t pd_fill_single_group_UFCS(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;
// 1. src + pps2字节)
data[idx++] = 0x00;
data[idx++] = 0x00;
// 2. 最小电压(高+低,直接取已拆分好的值)
data[idx++] = 0x13;
data[idx++] = 0x88;
// 3. 最大电压(高+低,直接取已拆分好的值)
data[idx++] = 0x13;
data[idx++] = 0x88;
// 4. 电流/功率(高+低,直接取已拆分好的值)
data[idx++] = source->protective_curr >> 8;
data[idx++] = source->protective_curr & 0xFF;
// 5. 保留位6字节(直接填0
memset(&data[idx], 0x00, 6);
idx+=6;
// 1. src + pps2字节)
data[idx++] = 0x00;
data[idx++] = 0x00;
// 2. 最小电压(高+低,直接取已拆分好的值)
data[idx++] = source->min_vol >> 8;
data[idx++] = source->min_vol & 0xFF;
// 3. 最大电压(高+低,直接取已拆分好的值)
data[idx++] = source->max_vol >> 8;
data[idx++] = source->max_vol & 0xFF;
// 4. 电流/功率(高+低,直接取已拆分好的值)
data[idx++] = source->protective_curr >> 8;
data[idx++] = source->protective_curr & 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)
{
rt_uint16_t len = 0;
rt_uint8_t data[150] = {0};
rt_uint8_t frame[150] = {0};
rt_uint8_t send_len = 0; //数据长度
rt_uint8_t max_group_idx = 0; //挡位索引
data[0] = pro; //协议
rt_uint8_t idx = 1;
for(rt_uint8_t i = 0;i<pro_gear_idx;i++){
rt_uint8_t fill_len = pd_fill_single_group_com(data,idx,i);
if (fill_len == 0) {
rt_kprintf("Error: fill group %d failed\n", i);
return -1;
}
idx += fill_len; // 偏移到下一组起始位置
}
send_len = idx; // 总填充字节数
chrg_north_pkg_encode(ID_SOURCE, SRC_CMD_SET_PROTOCOL, data, send_len, frame, &len);
// for(rt_uint8_t i=0;i<len+5;i++){
// rt_kprintf("%02x",data[i]);
// }
// rt_kprintf("idx=%d",idx);
return chrg_north_send(frame, len);
}
int source_set_pd_new_com(rt_uint8_t pro, struct chrg_switch_t *pSW)
{
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; //从data[1]开始填充
rt_uint8_t fill_len = 0;
rt_uint8_t protocal = pSW->source.protocol;
if(protocal == 0x0A){
fill_len = pd_fill_single_group_need_src_com(data, idx, pSW);
}else if(protocal == 0x03||protocal == 0x07||protocal == 0x08 ){
fill_len = pd_fill_single_group_no_src_com(data, idx, pSW);
}else if(protocal == 0x0C){
fill_len = pd_fill_single_group_UFCS(data, idx, pSW);
}else{
fill_len = pd_fill_single_group_FCP_AFC(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);
// for(rt_uint8_t i=0;i<idx;i++){
// rt_kprintf("%02x",data[i]);
// }
// rt_kprintf("idx=%d",idx);
return chrg_north_send(frame, len);
}
+112 -42
View File
@@ -11,51 +11,44 @@
#define __CHRG_SOURCE_H__
#include <rtthread.h>
#include "chrg_north.h"
#include "chrg_def.h"
struct chrg_switch_t;
// 冠达快充板(SOURCE)通讯协议
// SOURCE的ID为2, 波特率200K
#define SRC_CMD_GET_VOLTAGE 0x20 // 读取数据
// 发送 0B 00 02 20 volh voll curh curl nc nc CRC8
// 长度+nc+id+指令+2字节当前电源电压(mV)+2字节当前电源电流(mA)+2个预留字节+CRC8校验
// 接收 15 00 02 20 VH VL setvh setvl setch setcl NC NC verh verl NC NC NC NC NC NC CRC8
// 长度+nc+ID+指令+2字节读取的电压(0.01V)+2字节source设置电压(mV)+2字节source设置电流(mA)+2字节预留+2字节版本号+6字节预留+CRC8校验
#define SRC_CMD_GET_PROTOCOL 0x13 // 读取source的PD协议数据(当前为PDO,PPS,PD3.1,AVS协议时有效)
// 发送 05 00 02 13 2A
// XX 00 02 13 //长度(根据实际计算)+NC+ID+指令
// 00 00 VMAXH VMAXL VMINH VMINL CURH/PORH CURL/PORL NC NC NC NC NC NC
//源类型(1字节,00为PDO,03为APDO) + PPS类型(1字节,源类型为3时有效,00为SPR PPS,01为EPR AVS,02为SPR AVS)
// + 最大电压(2字节,mV) + 最小电压(2字节,mA) + 最大电流/功率(2字节,mA/W) + 预留(6字节,当协议类型为02时有效,意义与前6字节一致)
// 00 00 VMAXH VMAXL VMINH VMINL CURH/PORH CURL/PORL NC NC NC NC NC NC
// ...... CRC8
#define SRC_CMD_SET_CC_LEVEL 0x16
// 发送 06 00 02 16 00 2A
// 长度+nc+id+指令+电平等级(0xff为根据当前电流自动设置,否则为手动设定,设置方法待定)+CRC8校验
// 接收 05 00 02 16 2A
// 长度+nc+id+指令+CRC8校验
#define SRC_CMD_SET_CC_CHOOSE 0x17
#define SRC_CMD_SET_PROTOCOL 0xD0
// 发送 XX 00 02 D0 // 长度(根据实际计算)+NC+ID+指令
// 00 00 00 VMAXH VMAXL VMINH VMINL CURH/PORH CURL/PORL NC NC NC NC NC NC
// 协议(1字节) + 源类型(1字节,PD协议有效,00为PDO,03为APDO) +
// PPS类型(1字节, PD协议有效,源类型为3时有效,00为SPR PPS,01为EPR AVS,02为SPR AVS) + 最大电压(2字节,mV) +
// 最小电压(2字节,mA) + 最大电流/功率(2字节,mA/W) + 预留(6字节,当协议类型为02时有效,意义与前6字节一致)
// 00 00 00 VMAXH VMAXL VMINH VMINL CURH/PORH CURL/PORL NC NC NC NC NC NC
// ...... CRC8
// 接收 05 00 02 D0 CRC8
#define PROTOCOL_NONE 0x00 // 无快充
#define PROTOCOL_VIFC 0x01 // VIFC(暂不支持)
#define PROTOCOL_FCP 0x02 // FCP
#define PROTOCOL_SCPB 0x03 // SCPB
#define PROTOCOL_RESERVED_04 0x04 // 预留
#define PROTOCOL_RESERVED_05 0x05 // 预留
#define PROTOCOL_RFC 0x06 // RFC(暂不支持)
#define PROTOCOL_QC30 0x07 // QC3.0
#define PROTOCOL_QC20 0x08 // QC2.0
#define PROTOCOL_AFC 0x09 // AFC
#define PROTOCOL_PD 0x0A // PD
#define PROTOCOL_RESERVED_0B 0x0B // 预留
#define PROTOCOL_UFCS 0x0C // UFCS
#define PROTOCOL_RESERVED_0D 0x0D // 预留
#define PROTOCOL_VOOC 0x0E // VOOC(暂不支持)
#define PROTOCOL_SCPA 0x0F // SCPA
typedef enum {
PRO_NONE = 0x00, // 无快充
PRO_NONE = 0x00, // 标准
PRO_VIFC = 0x01, // VIFC(暂不支持)
PRO_FCP = 0x02, // FCP
PRO_SCP = 0x03, // SCP
PRO_SCPB = 0x03, // SCP
PRO_SERV1 = 0x04, // 预留
PRO_SERV2 = 0x05, // 预留
PRO_RFC = 0x06, // RFC(暂不支持)
@@ -67,10 +60,38 @@ typedef enum {
PRO_UFCS = 0x0C, // UFCS
PRO_PD31AVS = 0x0D, // PD3.1/AVS
PRO_VOOC = 0x0E, // VOOC(暂不支持)
PRO_SCPA = 0x0F, // SCPA
TOTAL_PROS
} eSRC_PRO;
// 电源协议映射表:枚举值 ↔ 协议名称(和你的 eSRC_PRO 完全对齐)
typedef struct {
rt_uint8_t pro_val; // 协议数值(对应 eSRC_PRO 枚举)
int pro_name; // 协议显示名称(LCD展示用)
} SrcProMap_t;
// 按 eSRC_PRO 枚举顺序定义映射表,确保一一对应
static const SrcProMap_t src_pro_map[] = {
{PRO_NONE, 30},
{PRO_VIFC, 31},
{PRO_FCP, 32},
{PRO_SCPB, 33},
{PRO_SERV1, 34},
{PRO_SERV2, 35},
{PRO_RFC, 36},
{PRO_QC30, 37},
{PRO_QC20, 38},
{PRO_AFC, 39},
{PRO_PD0PSS, 40},
{PRO_SERV3, 41},
{PRO_UFCS, 42},
{PRO_PD31AVS, 43},
{PRO_VOOC, 44},
{PRO_SCPA, 45}
};
// 映射表长度宏(自动计算,避免手动维护)
#define SRC_PRO_MAP_NUM (sizeof(src_pro_map) / sizeof(src_pro_map[0]))
// 应答帧头
struct pkg_head_t {
rt_uint8_t length; // 帧长度
@@ -121,22 +142,34 @@ struct src_vc_t {
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
rt_uint8_t vol_lvl; // CC线电平
eSRC_PRO protocol; // 协议类型
struct src_vc_t vc; // 读取数据
struct vc_pd_t pd_get[2]; // 读取PD协议数据
struct vc_pd_t pd_set[2]; // 设置PD协议数据
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+21代表cc12代表cc2
rt_uint16_t protective_curr; // 保护电流
rt_uint8_t Now_State; // 当前状态
rt_uint8_t On_Flag; // 启动总标志(0/1
rt_uint8_t Set_CV_Flag; // 电压/电流切换标志(0/1
rt_uint8_t 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; // 读取数据
struct vc_pd_t pd_get[2]; // 读取PD协议数据
struct vc_pd_t pd_set[2]; // 设置PD协议数据
};
/*****************************************************************
source_get_vc
source电压电流查询请求
@@ -167,6 +200,16 @@ extern int source_get_pd (void);
*****************************************************************/
extern int source_set_cc_lvl (rt_uint8_t lvl);
/*****************************************************************
source_set_cc_choose
source cc线
cc_set 01+21cc12cc2
-
<0: >0:
-
*****************************************************************/
extern int source_set_cc_choose (rt_uint8_t cc_set);
/*****************************************************************
source_set_pd
source PD协议
@@ -178,7 +221,34 @@ extern int source_set_cc_lvl (rt_uint8_t lvl);
extern int source_set_pd (rt_uint8_t pro, rt_uint8_t src, rt_uint8_t pps,
rt_uint16_t vmax, rt_uint16_t vmin, rt_int16_t max_cur);
// 挡位参数结构体
typedef struct {
rt_uint8_t src; // 第1字段(如00/03
rt_uint8_t pps; // 第2字段(如00/01
rt_uint16_t v_min; // 电压最小值(如0x1388=5V
rt_uint16_t v_max; // 电压最大值(如0x1388=5V
rt_uint16_t cur_set; // 电流设置值(如0x0bb8=3A
} Pro_Group;
// 挡位映射表(索引对应挡位:0=5V,1=9V,2=12V,3=20V,4=PPS
static const Pro_Group pd_voltage_map[] = {
{0x00, 0x00, 0x1388, 0x1388, 0x0bb8}, // 05V挡位
{0x00, 0x00, 0x2328, 0x2328, 0x0bb8}, // 19V挡位
{0x00, 0x00, 0x2ee0, 0x2ee0, 0x0bb8}, // 212V挡位
{0x00, 0x00, 0x4e20, 0x4e20, 0x0bb8}, // 320V挡位
{0x00, 0x00, 0xBB80, 0xBB80, 0X0bb8} // 4:48V
// {0x03, 0x00, 0x1388, 0x4e20, 0x1388} // 4PPS挡位 5-20V
};
extern rt_uint8_t pd_fill_gear_index(rt_uint8_t *gear_index, rt_uint8_t *gear_cnt, rt_uint8_t hex_code);
extern int source_set_pd_com(rt_uint8_t pro,rt_uint8_t pro_gear_idx);
#define PD_VOLTAGE_CNT (sizeof(pd_voltage_map) / sizeof(Pro_Group))
extern rt_uint16_t pd_gear_parse(rt_uint8_t hex_code);
extern void parse_power_single_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_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);
#endif
+29 -3
View File
@@ -75,12 +75,19 @@ 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");
}
while ( usLen-- ) {
iIndex = ucCRCLo ^ *(pucFrame++);
ucCRCLo = (rt_uint8_t)(ucCRCHi ^ aucCRCHi[iIndex]);
ucCRCHi = aucCRCLo[iIndex];
}
return (rt_uint16_t)(ucCRCHi << 8 | ucCRCLo);
}
@@ -135,13 +142,32 @@ rt_uint8_t u16_to_u8v (rt_uint16_t value, rt_uint8_t *buf)
{
if (RT_NULL != buf) {
buf[0] = (value>>8)&0xFF;
// rt_kprintf("%d",buf[0]);
buf[1] = value&0xFF;
// rt_kprintf("%d",buf[0]);
return 2;
}
return 0;
}
/*****************************************************************
u16_to_u8v_com
u16
value: *buf:
-
-
-2026.7.1
*****************************************************************/
rt_uint8_t u16_to_u8v_com (rt_uint16_t value, rt_uint8_t *buf)
{
if (RT_NULL != buf) {
buf[1] = (value>>8)&0xFF;
// rt_kprintf("%d",buf[0]);
buf[0] = value&0xFF;
// rt_kprintf("%d",buf[0]);
return 2;
}
return 0;
}
/*****************************************************************
u8v_to_u16
u16
@@ -91,6 +91,15 @@ extern rt_uint16_t swap_u16 (rt_uint16_t x);
-
*****************************************************************/
extern rt_uint32_t swap_u32 (rt_uint32_t x);
/*****************************************************************
u16_to_u8v_com
u16
value: *buf:
-
-
-2026.7.1
*****************************************************************/
extern rt_uint8_t u16_to_u8v_com (rt_uint16_t value, rt_uint8_t *buf);
#endif
Binary file not shown.
+29 -20
View File
@@ -16,8 +16,8 @@
<TargetCommonOption>
<Device>STM32F405RG</Device>
<Vendor>STMicroelectronics</Vendor>
<PackID>Keil.STM32F4xx_DFP.2.16.0</PackID>
<PackURL>http://www.keil.com/pack/</PackURL>
<PackID>Keil.STM32F4xx_DFP.3.1.1</PackID>
<PackURL>https://www.keil.com/pack/</PackURL>
<Cpu>IRAM(0x20000000-0x2001FFFF) IRAM2(0x10000000-0x1000FFFF) IROM(0x8000000-0x80FFFFF) CLOCK(25000000) CPUTYPE("Cortex-M4") FPU2</Cpu>
<FlashUtilSpec></FlashUtilSpec>
<StartupFile>"Startup\ST\STM32F4xx\startup_stm32f40_41xxx.s" ("STM32F40/41xxx Startup Code")</StartupFile>
@@ -132,7 +132,7 @@
<UseTargetDll>1</UseTargetDll>
<UseExternalTool>0</UseExternalTool>
<RunIndependent>0</RunIndependent>
<UpdateFlashBeforeDebugging>1</UpdateFlashBeforeDebugging>
<UpdateFlashBeforeDebugging>0</UpdateFlashBeforeDebugging>
<Capability>1</Capability>
<DriverSelection>4096</DriverSelection>
</Flash1>
@@ -313,7 +313,7 @@
</ArmAdsMisc>
<Cads>
<interw>1</interw>
<Optim>2</Optim>
<Optim>4</Optim>
<oTime>0</oTime>
<SplitLS>0</SplitLS>
<OneElfS>1</OneElfS>
@@ -352,7 +352,7 @@
<NoWarn>0</NoWarn>
<uSurpInc>0</uSurpInc>
<useXO>0</useXO>
<ClangAsOpt>1</ClangAsOpt>
<ClangAsOpt>4</ClangAsOpt>
<VariousControls>
<MiscControls></MiscControls>
<Define></Define>
@@ -443,16 +443,16 @@
<Group>
<GroupName>Applications/thread</GroupName>
<Files>
<File>
<FileName>chrg_north.c</FileName>
<FileType>1</FileType>
<FilePath>applications\thread\chrg_north.c</FilePath>
</File>
<File>
<FileName>chrg_roll_nor.c</FileName>
<FileType>1</FileType>
<FilePath>applications\thread\chrg_roll_nor.c</FilePath>
</File>
<File>
<FileName>chrg_north.c</FileName>
<FileType>1</FileType>
<FilePath>applications\thread\chrg_north.c</FilePath>
</File>
<File>
<FileName>chrg_south.c</FileName>
<FileType>1</FileType>
@@ -468,16 +468,16 @@
<FileType>1</FileType>
<FilePath>applications\thread\chrg_roll_sou.c</FilePath>
</File>
<File>
<FileName>chrg_thread.c</FileName>
<FileType>1</FileType>
<FilePath>applications\thread\chrg_thread.c</FilePath>
</File>
<File>
<FileName>chrg_lcd.c</FileName>
<FileType>1</FileType>
<FilePath>applications\thread\chrg_lcd.c</FilePath>
</File>
<File>
<FileName>chrg_thread.c</FileName>
<FileType>1</FileType>
<FilePath>applications\thread\chrg_thread.c</FilePath>
</File>
</Files>
</Group>
<Group>
@@ -493,16 +493,16 @@
<FileType>1</FileType>
<FilePath>applications\utils\chrg_sink.c</FilePath>
</File>
<File>
<FileName>chrg_eload.c</FileName>
<FileType>1</FileType>
<FilePath>applications\utils\chrg_eload.c</FilePath>
</File>
<File>
<FileName>chrg_north_pkg.c</FileName>
<FileType>1</FileType>
<FilePath>applications\utils\chrg_north_pkg.c</FilePath>
</File>
<File>
<FileName>chrg_eload.c</FileName>
<FileType>1</FileType>
<FilePath>applications\utils\chrg_eload.c</FilePath>
</File>
<File>
<FileName>chrg_utils.c</FileName>
<FileType>1</FileType>
@@ -2559,4 +2559,13 @@
<files/>
</RTE>
<LayerInfo>
<Layers>
<Layer>
<LayName>chrg</LayName>
<LayPrjMark>1</LayPrjMark>
</Layer>
</Layers>
</LayerInfo>
</Project>
+1
View File
@@ -0,0 +1 @@
LOAD %L INCREMENTAL
+1 -1
View File
@@ -15,7 +15,7 @@
<TargetCommonOption>
<Device>STM32F405RG</Device>
<Vendor>STMicroelectronics</Vendor>
<PackID>Keil.STM32F4xx_DFP.3.1.0</PackID>
<PackID>Keil.STM32F4xx_DFP.3.1.1</PackID>
<PackURL>https://www.keil.com/pack/</PackURL>
<Cpu>IRAM(0x20000000-0x2001FFFF) IRAM2(0x10000000-0x1000FFFF) IROM(0x8000000-0x80FFFFF) CLOCK(25000000) CPUTYPE("Cortex-M4") FPU2</Cpu>
<FlashUtilSpec></FlashUtilSpec>