From c820aad809ba84a2ee4259ac0d07833aa1a03ce8 Mon Sep 17 00:00:00 2001 From: yhf Date: Sat, 18 Jul 2026 15:32:54 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E5=A4=9A=E6=A8=A1=E5=9D=97=E5=8A=9F=E8=83=BD=E8=BF=AD=E4=BB=A3?= =?UTF-8?q?=E4=B8=8E=E9=85=8D=E7=BD=AE=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 新增sqlite文件、协议文档、调试截图、配置ini等各类辅助文件 2. 更新Keil开发包版本与工程配置,调整编译优化等级 3. 重构继电器控制逻辑、串口收发逻辑与线程优先级 4. 新增Modbus寄存器映射、校准结构体与Ymodem升级相关代码 5. 完善南北向协议解析、快充挡位配置与调试日志 6. 修复注释格式、数组越界与线程邮箱溢出问题 7. 新增屏幕控制、功率板调试与协议格式说明文档 --- .trae/rules/git-commit-message.md | 12 + AGENTS.md | 28 + apps/boot/application/main.c | 9 + apps/boot/board/bsp_uart_port.c | 20 +- apps/boot/boot.uvprojx | 4 +- apps/chrg/EventRecorderStub.scvd | 9 + apps/chrg/applications/bsp/chrg_rel.c | 5 +- apps/chrg/applications/bsp/chrg_rel.h | 3 +- apps/chrg/applications/bsp/chrg_tty.c | 6 +- apps/chrg/applications/bsp/chrg_tty.h | 7 +- apps/chrg/applications/main.c | 7 +- apps/chrg/applications/thread/chrg_comm.c | 1845 +++++++++++++++-- apps/chrg/applications/thread/chrg_comm.h | 109 +- apps/chrg/applications/thread/chrg_lcd.c | 469 +++-- apps/chrg/applications/thread/chrg_lcd.h | 12 +- apps/chrg/applications/thread/chrg_north.c | 400 +++- apps/chrg/applications/thread/chrg_north.h | 77 +- apps/chrg/applications/thread/chrg_roll_nor.c | 582 ++++-- apps/chrg/applications/thread/chrg_roll_nor.h | 29 +- apps/chrg/applications/thread/chrg_roll_sou.c | 547 ++++- apps/chrg/applications/thread/chrg_roll_sou.h | 44 +- apps/chrg/applications/thread/chrg_south.c | 21 +- apps/chrg/applications/thread/chrg_south.h | 5 +- apps/chrg/applications/thread/chrg_thread.c | 19 +- apps/chrg/applications/thread/chrg_thread.h | 13 +- apps/chrg/applications/utils/chrg_def.h | 35 +- apps/chrg/applications/utils/chrg_eload.c | 384 +++- apps/chrg/applications/utils/chrg_eload.h | 117 +- apps/chrg/applications/utils/chrg_north_pkg.c | 20 +- apps/chrg/applications/utils/chrg_north_pkg.h | 2 +- apps/chrg/applications/utils/chrg_regs.h | 288 +++ apps/chrg/applications/utils/chrg_sink.c | 464 ++++- apps/chrg/applications/utils/chrg_sink.h | 298 ++- apps/chrg/applications/utils/chrg_source.c | 824 +++++++- apps/chrg/applications/utils/chrg_source.h | 154 +- apps/chrg/applications/utils/chrg_utils.c | 32 +- apps/chrg/applications/utils/chrg_utils.h | 9 + apps/chrg/chrg.upk | Bin 0 -> 155816 bytes apps/chrg/chrg.uvprojx | 49 +- apps/chrg/debug_hot.ini | 1 + apps/chrg/template.uvprojx | 2 +- mintty.2025-11-24_21-33-55.png | Bin 0 -> 64119 bytes mintty.2025-11-24_21-34-04.png | Bin 0 -> 64119 bytes rt-thread/libcpu/arm/cortex-m4/context_rvds.S | 2 +- rt-thread/src/cpu_up.c | 2 +- sink调试.txt | 39 + source调试.txt | 9 + tp/2.sqlite | Bin 0 -> 516096 bytes tp/pd.sqlite | Bin 0 -> 204800 bytes 变电压协议设置格式(sink)_V1.1-20251125(1).txt | 107 + 变电压协议设置格式(source)_V1.2.txt | 91 + 屏幕控制逻辑.txt | 21 + 新建 文本文档.txt | 96 + 现有设备支持协议.xlsx | Bin 0 -> 11473 bytes 54 files changed, 6498 insertions(+), 830 deletions(-) create mode 100644 .trae/rules/git-commit-message.md create mode 100644 AGENTS.md create mode 100644 apps/chrg/EventRecorderStub.scvd create mode 100644 apps/chrg/applications/utils/chrg_regs.h create mode 100644 apps/chrg/chrg.upk create mode 100644 apps/chrg/debug_hot.ini create mode 100644 mintty.2025-11-24_21-33-55.png create mode 100644 mintty.2025-11-24_21-34-04.png create mode 100644 sink调试.txt create mode 100644 source调试.txt create mode 100644 tp/2.sqlite create mode 100644 tp/pd.sqlite create mode 100644 变电压协议设置格式(sink)_V1.1-20251125(1).txt create mode 100644 变电压协议设置格式(source)_V1.2.txt create mode 100644 屏幕控制逻辑.txt create mode 100644 新建 文本文档.txt create mode 100644 现有设备支持协议.xlsx diff --git a/.trae/rules/git-commit-message.md b/.trae/rules/git-commit-message.md new file mode 100644 index 0000000..bb3f38c --- /dev/null +++ b/.trae/rules/git-commit-message.md @@ -0,0 +1,12 @@ +--- +alwaysApply: true +scene: git_message +--- + +在此处编写规则,自定义 AI 生成提交信息的风格。 +使用中文描写本次提交内容。 +格式 +首行 简要描述 +空一行 +每行不超过80个描述一个修改/新增/删除的内容。 +具体到文件级,描述文件名、修改内容。 \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..ea2d80e --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,28 @@ +# Repository Guidelines + +## Project Structure & Module Organization + +`apps/chrg/` is the primary STM32F405 RT-Thread application: product code lives in `applications/`, board setup and linker scripts in `board/`, and build configuration beside them. Keep device-facing code in `applications/bsp/`, protocol and control helpers in `applications/utils/`, and long-running tasks in `applications/thread/`. `apps/boot/` is the standalone bootloader. Shared CMSIS and STM32 HAL sources are under `libs/`; `rt-thread/` is vendored upstream code. Hardware specifications and protocol references belong in `docs/`. Treat `build/`, Keil `Objects/`, maps, and firmware binaries as generated output. + +## Build, Test, and Development Commands + +Run charger commands from `apps/chrg/`: + +- `scons -j4` builds `chrg.elf` and `rtthread.bin` using the toolchain selected by `RTT_CC`/`RTT_EXEC_PATH` (GCC is the default in `rtconfig.py`). +- `scons --target=mdk5` regenerates the Keil MDK project when SCons configuration or source lists change. +- `C:\Keil_v5\UV4\UV4.exe -b chrg.uvprojx` performs a command-line Keil build. Build `apps/boot/boot.uvprojx` similarly for the bootloader. +- `keilkill.bat` removes Keil intermediates; review untracked files before running cleanup scripts. + +SCons and an ARM compiler are prerequisites and are not bundled on `PATH`. + +## Coding Style & Naming Conventions + +Use C99 and follow the surrounding file's indentation; new blocks should use four spaces. Place braces on the next line for functions and keep paired declarations/definitions in `.h`/`.c` files. Product symbols use lower snake case with the `chrg_` prefix, structs end in `_t`, and constants/macros use uppercase snake case. Use RT-Thread types and APIs (`rt_uint16_t`, `rt_thread_mdelay`) in application code and HAL APIs at the board boundary. Preserve existing file encodings when editing Chinese comments or documentation. + +## Testing Guidelines + +There is no product-level automated test suite or coverage threshold. Every firmware change must compile both affected targets and be exercised on STM32F405 hardware. Record checks for boot/upgrade flow, serial console, Modbus north/south communication, relay behavior, and LCD output as applicable. Tests in `rt-thread/tools/testcases/` cover vendored build tooling only; run them when modifying that tooling with `python -m unittest discover rt-thread/tools/testcases -p "test_*.py"`. + +## Commit & Pull Request Guidelines + +History uses short, lowercase, imperative summaries such as `fix south ch` and `add roll thread`; keep each commit focused and avoid generated artifacts. Pull requests should describe the affected target and behavior, link the issue, list build and hardware results, and include serial logs or LCD captures for user-visible or protocol changes. Call out changes to register maps, flash layout, linker scripts, or upgrade compatibility explicitly. diff --git a/apps/boot/application/main.c b/apps/boot/application/main.c index 5304dbe..8c11db6 100644 --- a/apps/boot/application/main.c +++ b/apps/boot/application/main.c @@ -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); + + } diff --git a/apps/boot/board/bsp_uart_port.c b/apps/boot/board/bsp_uart_port.c index a8b9eb1..3d409f5 100644 --- a/apps/boot/board/bsp_uart_port.c +++ b/apps/boot/board/bsp_uart_port.c @@ -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; + } } diff --git a/apps/boot/boot.uvprojx b/apps/boot/boot.uvprojx index b5ae971..d1a4e19 100644 --- a/apps/boot/boot.uvprojx +++ b/apps/boot/boot.uvprojx @@ -16,7 +16,7 @@ STM32F405RGTx STMicroelectronics - Keil.STM32F4xx_DFP.3.1.0 + Keil.STM32F4xx_DFP.3.1.1 https://www.keil.com/pack/ IRAM(0x20000000,0x00020000) IRAM2(0x10000000,0x00010000) IROM(0x08000000,0x00100000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE @@ -138,7 +138,7 @@ 1 BIN\UL2CM3.DLL - + "" () diff --git a/apps/chrg/EventRecorderStub.scvd b/apps/chrg/EventRecorderStub.scvd new file mode 100644 index 0000000..2956b29 --- /dev/null +++ b/apps/chrg/EventRecorderStub.scvd @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/apps/chrg/applications/bsp/chrg_rel.c b/apps/chrg/applications/bsp/chrg_rel.c index 5290732..087cc60 100644 --- a/apps/chrg/applications/bsp/chrg_rel.c +++ b/apps/chrg/applications/bsp/chrg_rel.c @@ -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 <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]); diff --git a/apps/chrg/applications/bsp/chrg_rel.h b/apps/chrg/applications/bsp/chrg_rel.h index 3030577..ecc6a40 100644 --- a/apps/chrg/applications/bsp/chrg_rel.h +++ b/apps/chrg/applications/bsp/chrg_rel.h @@ -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 diff --git a/apps/chrg/applications/bsp/chrg_tty.c b/apps/chrg/applications/bsp/chrg_tty.c index 0e99172..679066e 100644 --- a/apps/chrg/applications/bsp/chrg_tty.c +++ b/apps/chrg/applications/bsp/chrg_tty.c @@ -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; } diff --git a/apps/chrg/applications/bsp/chrg_tty.h b/apps/chrg/applications/bsp/chrg_tty.h index fbede12..e3c77d8 100644 --- a/apps/chrg/applications/bsp/chrg_tty.h +++ b/apps/chrg/applications/bsp/chrg_tty.h @@ -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 // 最小字节超时 diff --git a/apps/chrg/applications/main.c b/apps/chrg/applications/main.c index b825a15..1ee403f 100644 --- a/apps/chrg/applications/main.c +++ b/apps/chrg/applications/main.c @@ -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); } } diff --git a/apps/chrg/applications/thread/chrg_comm.c b/apps/chrg/applications/thread/chrg_comm.c index c87566a..402a739 100644 --- a/apps/chrg/applications/thread/chrg_comm.c +++ b/apps/chrg/applications/thread/chrg_comm.c @@ -9,29 +9,51 @@ #include #include - +#include "chrg_thread.h" +#include "chrg_north.h" #include "chrg_comm.h" #include "chrg_utils.h" - - +#include "chrg_south.h" +#include "chrg_roll_sou.h" +#include "chrg_eload.h" +#include "chrg_rel.h" +#include "chrg_roll_nor.h" #define LOG_TAG "chrg.comm" #define DBG_LEVEL DBG_LOG #include +#include "chrg_north_pkg.h" +#include "chrg_lcd.h" -rt_uint16_t usSDiscInStart = S_DISCRETE_INPUT_START; -rt_uint8_t ucSDiscInBuf[(S_DISCRETE_INPUT_NDISCRETES+BITS_UCHAR-1)/BITS_UCHAR]; - -rt_uint16_t usSCoilStart = S_COIL_START; -rt_uint8_t ucSCoilBuf[(S_COIL_NCOILS+BITS_UCHAR-1)/BITS_UCHAR]; - -rt_uint16_t usSRegInStart = S_REG_INPUT_START; -rt_uint16_t usSRegInBuf[S_REG_INPUT_NREGS]; - -rt_uint16_t usSRegHoldStart = S_REG_HOLDING_START; -rt_uint16_t usSRegHoldBuf[S_REG_HOLDING_NREGS]; +#include "stm32f4xx_hal.h" +rt_uint8_t ucDiscInBuf[(TOTAL_DISC_REGS+BITS_UCHAR-1)/BITS_UCHAR]; +rt_uint8_t ucCoilBuf[(TOTAL_COIL_REGS+BITS_UCHAR-1)/BITS_UCHAR]; +rt_uint16_t usRegInBuf[TOTAL_INPUT_REGS]; +rt_uint16_t usRegHoldBuf[TOTAL_HOLD_ALL_REGS] = {0}; //上位机Modbus 指令/数据保持器 +rt_uint16_t usRegProBuf[TOTAL_HOLD_ALL_REGS]; //北向protcal??? +//rt_uint16_t usRegTestBuf[TOTAL_TEST_REGS]; +rt_uint8_t g_proto_pData[80] = {0};//上位机协议指令,控制四个通道;二维 +rt_uint16_t g_proto_reqLen = 0; +rt_uint8_t mobude_ymodem_buf[MB_YMODEM_DATA_SIZE] = {0};//南向功率板升级缓冲区 +rt_uint8_t mobude_ymodem_buf_2[MB_YMODEM_DATA_SIZE] = {0};//南向功率板升级缓冲区 +/* Modbus 影子寄存器: 0x06/0x10 写操作暂存到此, PARAM_EFFECT 生效后复制到实际 pNOR->sw */ +static struct chrg_switch_t g_shadow_sw[TOTAL_NOR_CHS]; +static rt_uint8_t g_shadow_dirty[TOTAL_NOR_CHS] = {0}; /* 0=已生效 1=待生效,防止重复覆盖 */ +/* 首次写入影子寄存器前,从真实结构体同步,避免覆盖运行中的关键标志位 */ +static void chrg_shadow_sync(rt_uint8_t ch) +{ + if (g_shadow_dirty[ch] == 0) { + rt_memcpy(&g_shadow_sw[ch], &chrgnorth.sw[ch], sizeof(struct chrg_switch_t)); + } + g_shadow_dirty[ch] = 1; +} +static void chrg_shadow_init(void) +{ + rt_memcpy(g_shadow_sw, chrgnorth.sw, sizeof(g_shadow_sw)); + rt_memset(g_shadow_dirty, 0, sizeof(g_shadow_dirty)); +} struct chrg_comm_t chrgcomm = { .devname = DEV_NAME_COMM, .tty = RT_NULL, @@ -41,6 +63,9 @@ struct chrg_comm_t chrgcomm = { }; +static void chrg_mb_write_sink(rt_uint8_t ch, rt_uint16_t reg_offset, rt_uint16_t sou_value, struct chrg_switch_t *pSW); +static void chrg_mb_write_src(rt_uint8_t ch, rt_uint16_t reg_offset, rt_uint16_t sou_value, struct chrg_switch_t *pSW); +static void chrg_mb_write_sys(rt_uint8_t ch, rt_uint16_t reg_offset, rt_uint16_t sou_value, struct chrg_switch_t *pSW, struct chrg_north_t *pNOR, struct chrg_south_t *pSOU); /*! \brief Function to set bits in a byte buffer. * @@ -160,6 +185,16 @@ rt_uint8_t mb_get_bits (rt_uint8_t * ucByteBuf, rt_uint16_t usBitOffset, rt_uint return (rt_uint8_t)usWordBuf; } +static void set_ymodem_update_channel(struct chrg_north_t *pNOR,struct chrg_south_t *pSOU,eIDX_SOU_CH ch) +{ + for (int i = 0; i < 4; i++) { + pNOR->enable[i] = 0; + pSOU->enable[i] = 0; + } + pNOR->enable[ch] = 1; + pSOU->enable[ch] = 1; +} + static eMBException mb_error (eMBErrorCode eErrorCode) { eMBException eStatus; @@ -185,22 +220,18 @@ static eMBException mb_error (eMBErrorCode eErrorCode) return eStatus; } - +//extern eMBErrorCode Modbus_Protocal_Set(rt_uint16_t Role_value,rt_uint16_t src,rt_uint16_t pps,rt_uint16_t pro_value,rt_uint16_t volt_value,rt_uint16_t curr_value); eMBErrorCode mb_reg_input_cb (rt_uint8_t *pucRegBuffer, rt_uint16_t usAddress, rt_uint16_t usNRegs) { eMBErrorCode eStatus = MB_ENOERR; rt_uint16_t iRegIndex; - rt_uint16_t *pusRegInputBuf = usSRegInBuf; - rt_uint16_t REG_INPUT_START = S_REG_INPUT_START; - rt_uint16_t REG_INPUT_NREGS = S_REG_INPUT_NREGS; - rt_uint16_t usRegInStart = usSRegInStart; - if ((usAddress >= REG_INPUT_START) - && (usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS)) { - iRegIndex = usAddress - usRegInStart; + if ((usAddress >= INPUT_REG_START) + && (usAddress + usNRegs <= INPUT_REG_START + TOTAL_INPUT_REGS)) { + iRegIndex = usAddress - INPUT_REG_START; while (usNRegs > 0) { - *pucRegBuffer++ = (rt_uint8_t)(pusRegInputBuf[iRegIndex] >> BITS_UCHAR); - *pucRegBuffer++ = (rt_uint8_t)(pusRegInputBuf[iRegIndex] & 0xFF); + *pucRegBuffer++ = (rt_uint8_t)(usRegInBuf[iRegIndex] >> BITS_UCHAR); + *pucRegBuffer++ = (rt_uint8_t)(usRegInBuf[iRegIndex] & 0xFF); iRegIndex++; usNRegs--; } @@ -210,26 +241,39 @@ eMBErrorCode mb_reg_input_cb (rt_uint8_t *pucRegBuffer, rt_uint16_t usAddress, r return eStatus; } - +/***************************************************************** +函数名称: mb_reg_holding_cb +函数描述: Modbus保持寄存器读写回调函数 +输入参数: req: 写操作时指向待写入的Modbus帧数据缓冲区(高字节在前);读操作时无意义 + pucRegBuffer: 读操作时指向存储返回数据的缓冲区;写操作时无意义 + usAddress: 保持寄存器起始地址(16位,基于HOLD_REG_START的偏移) + usNRegs: 需要读写的保持寄存器数量(16位寄存器个数) + eMode: 寄存器操作模式(MB_REG_READ-读寄存器,MB_REG_WRITE-写寄存器) +输出参数: - +返回说明: eMBErrorCode枚举值,MB_ENOERR表示操作成功,MB_ENOREG表示地址越界 +其它说明: 1. 寄存器地址需满足HOLD_REG_START ≤ usAddress + usNRegs ≤ HOLD_REG_START + TOTAL_HOLD_ALL_REGS + 2. 字节序遵循Modbus RTU标准:高字节在前,低字节在后 + 3. usRegHoldBuf为全局保持寄存器缓冲区,存储所有可读写配置参数 +*****************************************************************/ eMBErrorCode mb_reg_holding_cb (rt_uint8_t *req, rt_uint8_t *pucRegBuffer, rt_uint16_t usAddress, rt_uint16_t usNRegs, eMBRegisterMode eMode) { eMBErrorCode eStatus = MB_ENOERR; rt_uint16_t iRegIndex; - rt_uint16_t *pusRegHoldingBuf = usSRegHoldBuf; - rt_uint16_t REG_HOLDING_START = S_REG_HOLDING_START; - rt_uint16_t REG_HOLDING_NREGS = S_REG_HOLDING_NREGS; - rt_uint16_t usRegHoldStart = usSRegHoldStart; - - if ((usAddress >= REG_HOLDING_START) - && (usAddress + usNRegs <= REG_HOLDING_START + REG_HOLDING_NREGS)) { - iRegIndex = usAddress - usRegHoldStart; + rt_uint8_t highByte, lowByte; // 定义字节变量用于打印 + if ((usAddress >= HOLD_REG_START) + && (usAddress + usNRegs <= HOLD_REG_START + TOTAL_HOLD_ALL_REGS)) { + iRegIndex = usAddress - HOLD_REG_START; switch (eMode) { /* read current register values from the protocol stack. */ case MB_REG_READ: while (usNRegs > 0) { - *pucRegBuffer++ = (rt_uint8_t)(pusRegHoldingBuf[iRegIndex] >> BITS_UCHAR); - *pucRegBuffer++ = (rt_uint8_t)(pusRegHoldingBuf[iRegIndex] & 0xFF); + *pucRegBuffer++ = (rt_uint8_t)(usRegHoldBuf[iRegIndex] >> BITS_UCHAR); + *pucRegBuffer++ = (rt_uint8_t)(usRegHoldBuf[iRegIndex] & 0xFF); + // highByte = (rt_uint8_t)(usRegHoldBuf[iRegIndex] >> BITS_UCHAR); + // lowByte = (rt_uint8_t)(usRegHoldBuf[iRegIndex] & 0xFF); + // rt_kprintf("Reg[%d] = 0x%04X, High:0x%02X, Low:0x%02X\r\n", + // iRegIndex, usRegHoldBuf[iRegIndex], highByte, lowByte); iRegIndex++; usNRegs--; } @@ -238,9 +282,9 @@ eMBErrorCode mb_reg_holding_cb (rt_uint8_t *req, rt_uint8_t *pucRegBuffer, rt_ui /* write current register values with new values from the protocol stack. */ case MB_REG_WRITE: while (usNRegs > 0) { - pusRegHoldingBuf[iRegIndex] = *req++ << BITS_UCHAR; - pusRegHoldingBuf[iRegIndex] |= *req++; - iRegIndex++; +// usRegHoldBuf[iRegIndex] = *req++ << BITS_UCHAR; +// usRegHoldBuf[iRegIndex] |= *req++; +// iRegIndex++; usNRegs--; } break; @@ -252,26 +296,93 @@ eMBErrorCode mb_reg_holding_cb (rt_uint8_t *req, rt_uint8_t *pucRegBuffer, rt_ui return eStatus; } +/***************************************************************** +函数名称: mb_reg_test_cb +函数描述: Modbus测试寄存器读写回调函数,实现16位保持寄存器与8位字节流的双向转换, + 支持读寄存器(返回配置参数)和写寄存器(存储主机下发的配置指令) +输入参数: req: 写操作时指向待写入的Modbus帧数据缓冲区(高字节在前);读操作时无意义 + pucRegBuffer: 读操作时指向存储返回数据的缓冲区;写操作时无意义 + usAddress: 保持寄存器起始地址(16位,基于HOLD_REG_START的偏移) + usNRegs: 需要读写的保持寄存器数量(16位寄存器个数) + eMode: 寄存器操作模式(MB_REG_READ-读寄存器,MB_REG_WRITE-写寄存器) +输出参数: - +返回说明: eMBErrorCode枚举值,MB_ENOERR表示操作成功,MB_ENOREG表示地址越界 +其它说明: 1. 寄存器地址需满足HOLD_REG_START ≤ usAddress + usNRegs ≤ HOLD_REG_START + TOTAL_HOLD_REGS + 2. 字节序遵循Modbus RTU标准:高字节在前,低字节在后 + 3. usRegHoldBuf为全局保持寄存器缓冲区,存储所有可读写配置参数 +*****************************************************************/ +eMBErrorCode mb_reg_test_cb (rt_uint8_t *req, rt_uint8_t *pucRegBuffer, rt_uint16_t usAddress, + rt_uint16_t usNRegs, eMBRegisterMode eMode) +{ + eMBErrorCode eStatus = MB_ENOERR; +// rt_uint16_t iRegIndex; + +// if ((usAddress >= TEST_REG_START) +// && (usAddress + usNRegs <= TEST_REG_START + TOTAL_TEST_REGS)) { +// iRegIndex = usAddress - TEST_REG_START; +// switch (eMode) { +// /* read current register values from the protocol stack. */ +// case MB_REG_READ: +// while (usNRegs > 0) { +// *pucRegBuffer++ = (rt_uint8_t)(usRegTestBuf[iRegIndex] >> BITS_UCHAR); +// *pucRegBuffer++ = (rt_uint8_t)(usRegTestBuf[iRegIndex] & 0xFF); +// iRegIndex++; +// usNRegs--; +// } +// break; +// /* write current register values with new values from the protocol stack. */ +// case MB_REG_WRITE: +// while (usNRegs > 0) { +// usRegTestBuf[iRegIndex] = *req++ << BITS_UCHAR; +// usRegTestBuf[iRegIndex] |= *req++; +// iRegIndex++; +// usNRegs--; +// } +// break; +// } +// } else { +// eStatus = MB_ENOREG; +// } + + return eStatus; +} +/***************************************************************** +函数名称: mb_ymodem_updata_cb +*****************************************************************/ +eMBErrorCode mb_ymodem_updata_cb (rt_uint8_t *state, rt_uint8_t *pucRegBuffer) +{ + eMBErrorCode eStatus = MB_ENOERR; + + switch (*state) { + /* read current register values from the protocol stack. */ + case 0: + /* 返回值反映实际ymodem升级状态: ACK_C=空闲, ACK=升级中 */ + pucRegBuffer[0] = (*state == Ymodem_No) ? ACK_C : ACK; + break; + case 1: + pucRegBuffer[0] = (*state == Ymodem_No) ? ACK_C : ACK; + break; + /* write current register values with new values from the protocol stack. */ + } + return eStatus; +} + eMBErrorCode mb_reg_coils_cb (rt_uint8_t *req, rt_uint8_t *pucRegBuffer, rt_uint16_t usAddress, rt_uint16_t usNCoils, eMBRegisterMode eMode) { eMBErrorCode eStatus = MB_ENOERR; rt_uint16_t iRegIndex = 0, iRegBitIndex = 0, iNReg = 0; - rt_uint8_t *pucCoilBuf = ucSCoilBuf; - rt_uint16_t COIL_START = S_COIL_START; - rt_uint16_t COIL_NCOILS = S_COIL_NCOILS; - rt_uint16_t usCoilStart = usSCoilStart; iNReg = (usNCoils+BITS_UCHAR-1)/BITS_UCHAR; - if ((usAddress >= COIL_START) && (usAddress + usNCoils <= COIL_START + COIL_NCOILS)) { - iRegIndex = (rt_uint16_t)(usAddress - usCoilStart) / BITS_UCHAR; - iRegBitIndex = (rt_uint16_t)(usAddress - usCoilStart) % BITS_UCHAR; + if ((usAddress >= COIL_REG_START) && (usAddress + usNCoils <= COIL_REG_START + TOTAL_COIL_REGS)) { + iRegIndex = (rt_uint16_t)(usAddress - COIL_REG_START) / BITS_UCHAR; + iRegBitIndex = (rt_uint16_t)(usAddress - COIL_REG_START) % BITS_UCHAR; switch (eMode) { /* read current coil values from the protocol stack. */ case MB_REG_READ: while (iNReg > 0) { - *pucRegBuffer++ = mb_get_bits(&pucCoilBuf[iRegIndex++], iRegBitIndex, BITS_UCHAR); + *pucRegBuffer++ = mb_get_bits(&ucCoilBuf[iRegIndex++], iRegBitIndex, BITS_UCHAR); iNReg--; } pucRegBuffer--; @@ -285,14 +396,14 @@ eMBErrorCode mb_reg_coils_cb (rt_uint8_t *req, rt_uint8_t *pucRegBuffer, rt_uint /* write current coil values with new values from the protocol stack. */ case MB_REG_WRITE: while (iNReg > 1) { - mb_set_bits(&pucCoilBuf[iRegIndex++], iRegBitIndex, BITS_UCHAR, *req++); + mb_set_bits(&ucCoilBuf[iRegIndex++], iRegBitIndex, BITS_UCHAR, *req++); iNReg--; } /* last coils */ usNCoils = usNCoils % BITS_UCHAR; /* mb_set_bits has bug when ucNBits is zero */ if (usNCoils != 0) { - mb_set_bits(&pucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils, *req++); + mb_set_bits(&ucCoilBuf[iRegIndex++], iRegBitIndex, usNCoils, *req++); } break; } @@ -307,19 +418,16 @@ eMBErrorCode mb_reg_discrete_cb (rt_uint8_t *pucRegBuffer, rt_uint16_t usAddress { eMBErrorCode eStatus = MB_ENOERR; rt_uint16_t iRegIndex , iRegBitIndex , iNReg; - rt_uint8_t *pucDiscreteInputBuf = ucSDiscInBuf; - rt_uint16_t DISCRETE_INPUT_START = S_DISCRETE_INPUT_START; - rt_uint16_t DISCRETE_INPUT_NDISCRETES = S_DISCRETE_INPUT_NDISCRETES; - rt_uint16_t usDiscreteInputStart = usSDiscInStart; + iNReg = (usNDiscrete+BITS_UCHAR-1) / BITS_UCHAR; - if ((usAddress >= DISCRETE_INPUT_START) - && ((usAddress + usNDiscrete) <= (DISCRETE_INPUT_START + DISCRETE_INPUT_NDISCRETES))) { - iRegIndex = (rt_uint16_t) (usAddress - usDiscreteInputStart) / BITS_UCHAR; - iRegBitIndex = (rt_uint16_t) (usAddress - usDiscreteInputStart) % BITS_UCHAR; + if ((usAddress >= DISC_REG_START) + && ((usAddress + usNDiscrete) <= (DISC_REG_START + TOTAL_DISC_REGS))) { + iRegIndex = (rt_uint16_t) (usAddress - DISC_REG_START) / BITS_UCHAR; + iRegBitIndex = (rt_uint16_t) (usAddress - DISC_REG_START) % BITS_UCHAR; while (iNReg > 0) { - *pucRegBuffer++ = mb_get_bits(&pucDiscreteInputBuf[iRegIndex++], iRegBitIndex, BITS_UCHAR); + *pucRegBuffer++ = mb_get_bits(&ucDiscInBuf[iRegIndex++], iRegBitIndex, BITS_UCHAR); iNReg--; } pucRegBuffer--; @@ -429,7 +537,8 @@ eMBException funcReadHoldingRegister (rt_uint8_t *reqFrame, rt_uint16_t reqLen, rt_uint8_t *resFrame, rt_uint16_t *resLen) { rt_uint16_t regAddress = 0, cntReg = 0; - + struct chrg_north_t *pNOR = &chrgnorth; + struct chrg_switch_t *pSW = &pNOR->sw[0]; eMBException eStatus = MB_EX_NONE; eMBErrorCode eRegStatus; @@ -439,21 +548,21 @@ eMBException funcReadHoldingRegister (rt_uint8_t *reqFrame, rt_uint16_t reqLen, regAddress = u8v_to_u16(&reqFrame[2]); cntReg = u8v_to_u16(&reqFrame[4]); - + if ((0 == cntReg)||(cntReg >= MB_PDU_FUNC_READ_REGCNT_MAX)) { return MB_EX_ILLEGAL_DATA_VALUE; } resFrame[1] = MB_READ_HOLDING_REGISTER; resFrame[2] = cntReg * 2; - + eRegStatus = mb_reg_holding_cb(RT_NULL, &resFrame[3], regAddress, cntReg, MB_REG_READ); if (eRegStatus != MB_ENOERR) { eStatus = mb_error(eRegStatus); } else { *resLen = 3+cntReg * 2; } - + rt_kprintf("------COM VOLT =%d -------\n------COM CURR =%d-------", pSW->Now_voltage,pSW->Now_current); return eStatus; } @@ -498,81 +607,374 @@ eMBException funcReadInputRegister (rt_uint8_t *reqFrame, rt_uint16_t reqLen, } /***************************************************************** -函数名称: funcWriteCoil -函数描述: 写单个保持继电器 +函数名称: funcReadTestRegister +函数描述: 读测试寄存器 输入参数: reqFrame: 请求数据 reqLen: 请求长度 resFrame:响应数据 resLen:响应长度 输出参数: - 返回说明: - 其它说明: - *****************************************************************/ +//eMBException funcReadTestRegister (rt_uint8_t *reqFrame, rt_uint16_t reqLen, +// rt_uint8_t *resFrame, rt_uint16_t *resLen) +//{ +// rt_uint16_t regAddress = 0,regCH=0, cntReg = 0; //读取的寄存器地址和寄存器数量 + +// eMBException eStatus = MB_EX_NONE; +// eMBErrorCode eRegStatus; + +// if (4+MB_PDU_FUNC_READ_SIZE != reqLen) { +// return MB_EX_ILLEGAL_DATA_VALUE; +// } +// regAddress = reqFrame[3]; +// regCH = reqFrame[4]; +// cntReg = reqFrame[5]; +// regAddress = (reqFrame[3]==1) ? 0 : 2; +// +// regAddress = regAddress+regCH*TOTAL_TEST_CH_REGS; +// +// +// if ((0 == cntReg)||(cntReg >= MB_PDU_FUNC_READ_REGCNT_MAX)) { +// return MB_EX_ILLEGAL_DATA_VALUE; +// } + +// resFrame[1] = MB_READ_TEST_REGISTER; +// resFrame[2] = cntReg * 2; + +// eRegStatus = mb_reg_test_cb(RT_NULL, &resFrame[3], regAddress, cntReg, MB_REG_READ); +// rt_kprintf(""); +// if (eRegStatus != MB_ENOERR) { +// eStatus = mb_error(eRegStatus); +// } else { +// *resLen = 3+cntReg*2; +// } + +// return eStatus; +//} + +// /***************************************************************** +// 函数名称: funcWriteCoil +// 函数描述: 写单个保持继电器 +// 输入参数: reqFrame: 请求数据 reqLen: 请求长度 resFrame:响应数据 resLen:响应长度 +// 输出参数: - +// 返回说明: - +// 其它说明: - +// *****************************************************************/ eMBException funcWriteCoil (rt_uint8_t *reqFrame, rt_uint16_t reqLen, rt_uint8_t *resFrame, rt_uint16_t *resLen) { - rt_uint16_t regAddress = 0, value = 0; - rt_uint8_t ucBuf[2] = {0}; +// rt_uint16_t regAddress = 0, value = 0; +// rt_uint8_t ucBuf[2] = {0}; - eMBException eStatus = MB_EX_NONE; - eMBErrorCode eRegStatus; +// eMBException eStatus = MB_EX_NONE; +// eMBErrorCode eRegStatus; - if (4+MB_PDU_FUNC_WRITE_SIZE != reqLen) { - return MB_EX_ILLEGAL_DATA_VALUE; - } +// if (4+MB_PDU_FUNC_WRITE_SIZE != reqLen) { +// return MB_EX_ILLEGAL_DATA_VALUE; +// } - regAddress = u8v_to_u16(&reqFrame[2]); - value = u8v_to_u16(&reqFrame[4]); +// regAddress = u8v_to_u16(&reqFrame[2]); +// value = u8v_to_u16(&reqFrame[4]); - if (0x0000 == value) { - ucBuf[0] = 0; - ucBuf[1] = 0; - } else if (0xFF00 == value) { - ucBuf[0] = 1; - ucBuf[1] = 0; - } else { - return MB_EX_ILLEGAL_DATA_VALUE; - } +// if (0x0000 == value) { +// ucBuf[0] = 0; +// ucBuf[1] = 0; +// } else if (0xFF00 == value) { +// ucBuf[0] = 1; +// ucBuf[1] = 0; +// } else { +// return MB_EX_ILLEGAL_DATA_VALUE; +// } +// //判断地址 +// rt_uint16_t reg_offset = regAddress-COIL_REG_START; +// //提取通道 +// eIDX_SOU_CH ch = (eIDX_SOU_CH)(reg_offset/TOTAL_COIL_CH_REGS); +// a = ch; +// //判断寄存器偏移量 +// rt_uint16_t sout_reg = reg_offset%TOTAL_COIL_CH_REGS; - rt_memcpy(resFrame, reqFrame, reqLen); - *resLen = reqLen-2; +// if (ch > IDX_SOU_CH4) { +// rt_kprintf("[funcWriteCoil] ch out of range! ch=%d, max=%d\n", ch, IDX_SOU_CH4); +// return MB_EX_ILLEGAL_DATA_ADDRESS; +// } +// // 校验sout_reg是否在合法线圈寄存器范围 +// if (sout_reg > MODBUS_COIL_SRC_CC) { +// rt_kprintf("[funcWriteCoil] sout_reg out of range! reg=%d\n", sout_reg); +// return MB_EX_ILLEGAL_DATA_ADDRESS; +// } + +// //功能实现 +// if(value==0x0000){ +// switch(sout_reg){ +// case MODBUS_COIL_PWR_SRC: +// chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_REL_ON, ALL_REL_OFF); +// rt_kprintf("THE_ALL_REL_OFF"); +// break; +// case MODBUS_COIL_PWR_SINK: +// chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_REL_ON, ALL_REL_OFF); +// rt_kprintf("THE_ALL_REL_OFF"); +// break; +// case MODBUS_COIL_PWR_ALL: +// chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_REL_ON, ALL_REL_OFF); +// rt_kprintf("THE_ALL_REL_OFF"); +// break; +// case MODBUS_COIL_SINK_CC: +// chrg_nor_sw_rel((eIDX_NOR_CH)ch,4); +// rt_kprintf("CC_SINK_OFF"); +// break; +// case MODBUS_COIL_SRC_CC: +// chrg_nor_sw_rel((eIDX_NOR_CH)ch,4); +// rt_kprintf("CC_SRC_OFF"); +// break; +// default: +// return MB_EX_ILLEGAL_DATA_ADDRESS; +// break; +// } +// } +// else{ +// switch(sout_reg){ +// case MODBUS_COIL_PWR_SRC: +// chrg_set_sou_reg(ch, REG_REL_ON, MAIN_REL_ON); +// rt_kprintf("THE_Main_REL_ON"); +// break; +// case MODBUS_COIL_PWR_SINK: +// chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_REL_ON, FU_REL_ON); +// rt_kprintf("THE_Main_REL_ON"); +// break; +// case MODBUS_COIL_PWR_ALL: +// chrg_set_sou_reg((eIDX_SOU_CH)ch, REG_REL_ON, ALL_REL_ON); +// rt_kprintf("THE_Main_REL_ON"); +// break; +// case MODBUS_COIL_SINK_CC: +// chrg_nor_sw_rel((eIDX_NOR_CH)ch,ID_SINK); +// rt_kprintf("CC_SINK_ON"); +// break; +// case MODBUS_COIL_SRC_CC: +// chrg_nor_sw_rel((eIDX_NOR_CH)ch,ID_SOURCE); +// rt_kprintf("CC_SRC_ON"); +// break; +// default: +// return MB_EX_ILLEGAL_DATA_ADDRESS; +// break; +// } +// } +// // rt_memcpy(resFrame, reqFrame, reqLen); +// *resLen = reqLen-2; - eRegStatus = mb_reg_coils_cb(RT_NULL, ucBuf, regAddress, 1, MB_REG_WRITE); - if (eRegStatus != MB_ENOERR) { - eStatus = mb_error(eRegStatus); - } - - return eStatus; +// eRegStatus = mb_reg_coils_cb(RT_NULL, ucBuf, regAddress, 1, MB_REG_WRITE); +// if (eRegStatus != MB_ENOERR) { +// eStatus = mb_error(eRegStatus); +// } + return 0; +// return eStatus; } +/***************************************************************** + * 负载协议映射表: Modbus寄存器值 → 内部负载协议枚举 + *****************************************************************/ +typedef struct { + rt_uint16_t reg_val; // Modbus寄存器写入值 + rt_uint16_t sink_pro; // 内部负载协议枚举 (eLOAD_PRO) + rt_uint8_t has_group; // 是否有组号 (PDO/PPS/PD3.1/UFCS/AVS) +} SinkProtoMap_t; + +static const SinkProtoMap_t sink_proto_map[] = { + {0x10, LOAD_PRO_NONE, 0}, // 无协议 + {0x11, LOAD_PRO_QC20, 0}, // QC2.0 + {0x12, LOAD_PRO_QC30, 0}, // QC3.0 + {0x13, LOAD_PRO_FCP, 0}, // FCP + {0x14, LOAD_PRO_AFC, 0}, // AFC + {0x15, LOAD_PRO_SCP, 0}, // SCP + {0x16, LOAD_PRO_VIVO, 0}, // VIVO + {0x17, LOAD_PRO_TFC_RFC, 0}, // TFC(传音) + {0x19, LOAD_PRO_PDO_AUTO, 1}, // PDO自动 + {0x1B, LOAD_PRO_PPS_AUTO, 1}, // PPS自动 + {0x1C, LOAD_PRO_PD31AVS, 1}, // PD3.1 + {0x1D, LOAD_PRO_UFCS, 1}, // UFCS + {0x1F, LOAD_PRO_AVS, 1}, // AVS +}; +#define SINK_PROTO_MAP_NUM (sizeof(sink_proto_map) / sizeof(sink_proto_map[0])) + +/***************************************************************** + * 电源协议映射表: Modbus寄存器值 → 内部电源协议枚举 + *****************************************************************/ +typedef struct { + rt_uint16_t reg_val; + rt_uint16_t src_pro; // 内部电源协议枚举 (eSRC_PRO) +} SrcProtoMap_t; + +static const SrcProtoMap_t src_proto_map[] = { + {0x2A, PRO_PD0PSS}, // PD + {0x22, PRO_FCP}, // FCP + {0x23, PRO_SCPB}, // SCPB + {0x27, PRO_QC30}, // QC3.0 + {0x28, PRO_QC20}, // QC2.0 + {0x29, PRO_AFC}, // AFC + {0x2C, PRO_UFCS}, // UFCS +}; +#define SRC_PROTO_MAP_NUM (sizeof(src_proto_map) / sizeof(src_proto_map[0])) + +/***************************************************************** + * 查找负载协议映射 + *****************************************************************/ +static rt_uint16_t sink_proto_lookup(rt_uint16_t reg_val, rt_uint8_t *has_group) +{ + for (int i = 0; i < SINK_PROTO_MAP_NUM; i++) { + if (sink_proto_map[i].reg_val == reg_val) { + *has_group = sink_proto_map[i].has_group; + return sink_proto_map[i].sink_pro; + } + } + return LOAD_PRO_NONE; // 默认无协议 + +} + +/***************************************************************** + * 查找电源协议映射 + *****************************************************************/ +static rt_uint16_t src_proto_lookup(rt_uint16_t reg_val) +{ + for (int i = 0; i < SRC_PROTO_MAP_NUM; i++) { + if (src_proto_map[i].reg_val == reg_val) { + return src_proto_map[i].src_pro; + } + } + return PRO_NONE; // 默认无协议 +} + +/***************************************************************** + * 查找电源类型 + *****************************************************************/ +static rt_uint16_t src_type_lookup(rt_uint16_t reg_val,struct chrg_switch_t *pSW) +{ + switch(reg_val){ + case 0: + pSW->source.src = 0; + pSW->source.pps = 0; + break; + case 1: + pSW->source.src = 0; + pSW->source.pps = 1; + break; + case 2: + pSW->source.src = 3; + pSW->source.pps = 0; + break; + case 3: + pSW->source.src = 3; + pSW->source.pps = 1; + break; + default: + return 1; + break; + } + return 0; +} /***************************************************************** 函数名称: funcWriteHoldingRegister -函数描述: 写多个保持继电器 +函数描述: 写单个保持寄存器(0x06功能码) + 根据寄存器地址自动识别负载/电源/系统区块,直接操作对应通道结构体 输入参数: reqFrame: 请求数据 reqLen: 请求长度 resFrame:响应数据 resLen:响应长度 输出参数: - -返回说明: - -其它说明: - +返回说明: MB_EX_NONE=成功, 其他=Modbus异常码 +其它说明: 新协议采用标准0x06功能码,寄存器地址区分功能区块: + 0x0000~0x0073 负载, 0x0080~0x0097 电源, 0x00A0~0x00A7 系统 *****************************************************************/ eMBException funcWriteHoldingRegister (rt_uint8_t *reqFrame, rt_uint16_t reqLen, - rt_uint8_t *resFrame, rt_uint16_t *resLen) + rt_uint8_t *resFrame, rt_uint16_t *resLen) { - rt_uint16_t regAddress = 0; + struct chrg_north_t *pNOR = &chrgnorth; + struct chrg_south_t *pSOU = &chrgsouth; + struct chrg_switch_t *pSW = RT_NULL; + rt_uint8_t regAddress = 0; + rt_uint8_t regAddress_H = 0; + rt_uint16_t sou_value = 0; + /* ---- 提取通道号和区块内偏移 ---- */ + eIDX_SOU_CH ch; + rt_uint16_t reg_offset; // 区块内寄存器偏移 + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; - eMBException eStatus = MB_EX_NONE; - eMBErrorCode eRegStatus; + if (4 + MB_PDU_FUNC_WRITE_SIZE != reqLen) { + return MB_EX_ILLEGAL_DATA_VALUE; + } - if (4+MB_PDU_FUNC_WRITE_SIZE != reqLen) { - return MB_EX_ILLEGAL_DATA_VALUE; - } + regAddress_H = reqFrame[2]; + regAddress = reqFrame[3]; + sou_value = u8v_to_u16(&reqFrame[4]); - regAddress = u8v_to_u16(&reqFrame[2]); + /* ---- 特殊地址: 系统复位 ---- */ + if (regAddress_H == RESET_NORTH_ADDR && sou_value == RESET_NORTH_VALUE) { + __asm__ __volatile__("cpsid i"); + __asm__ __volatile__("ldr r0, =0xE000ED0C"); + __asm__ __volatile__("ldr r1, =0x05FA0004"); + __asm__ __volatile__("str r1, [r0]"); + while (1); + } - rt_memcpy(resFrame, reqFrame, reqLen); - *resLen = reqLen-2; + /* ---- 特殊地址: 南向板复位 ---- */ + if (regAddress_H == RESET_SOUTH_ADDR) { + if (sou_value < 4) { + chrg_set_sou_reg((eIDX_SOU_CH)sou_value, RESET_SOUTH_VALUE, 0x01); + } else { + rt_kprintf("Value_Error\n"); + return MB_EX_ILLEGAL_DATA_VALUE; + } + goto build_response; + } - eRegStatus = mb_reg_holding_cb(&reqFrame[4], &resFrame[3], regAddress, 1, MB_REG_WRITE); - if (eRegStatus != MB_ENOERR) { - eStatus = mb_error(eRegStatus); - } + /* ---- 地址范围校验 ---- */ + if(regAddress_H == HOLD_REG_SINK_BASE){ + if (REG_IS_SINK(regAddress)) { + ch = (eIDX_SOU_CH)REG_GET_SINK_CH(regAddress); + reg_offset = REG_GET_SINK_OFFSET(regAddress); + } + }else if (regAddress_H == HOLD_REG_SRC_BASE) { + if (REG_IS_SRC(regAddress)) { + ch = (eIDX_SOU_CH)REG_GET_SRC_CH(regAddress); + reg_offset = REG_GET_SRC_OFFSET(regAddress); + } + } else if (regAddress_H == HOLD_REG_SYS_BASE) { + if (REG_IS_SYS(regAddress)) { + ch = (eIDX_SOU_CH)REG_GET_SYS_CH(regAddress); + reg_offset = REG_GET_SYS_OFFSET(regAddress); + } + } else { + return MB_EX_ILLEGAL_DATA_ADDRESS; + } - return eStatus; + if (ch > IDX_SOU_CH4) { + return MB_EX_ILLEGAL_DATA_ADDRESS; + } + + pSW = &g_shadow_sw[ch]; // 写入影子寄存器, 等待 PARAM_EFFECT 生效 + chrg_shadow_sync(ch); // 首次写同步真实状态,防止覆盖运行标志位 + /* ===== 直接根据高字节分发到对应业务函数 ===== */ + if (regAddress_H == HOLD_REG_SINK_BASE) + { + chrg_mb_write_sink(ch, reg_offset, sou_value, pSW); + } + else if (regAddress_H == HOLD_REG_SRC_BASE) + { + chrg_mb_write_src(ch, reg_offset, sou_value, pSW); + } + else if (regAddress_H == HOLD_REG_SYS_BASE) + { + chrg_mb_write_sys(ch, reg_offset, sou_value, pSW, pNOR, pSOU); + } + +build_response: + /* ---- 构建响应帧 ---- */ + rt_memcpy(resFrame, reqFrame, reqLen); + *resLen = reqLen - 2; + + /* ---- 写入保持寄存器镜像 ---- */ + eRegStatus = mb_reg_holding_cb(&reqFrame[4], &resFrame[3], regAddress, 1, MB_REG_WRITE); + if (eRegStatus != MB_ENOERR) { + eStatus = mb_error(eRegStatus); + } + + return eStatus; } /***************************************************************** @@ -619,60 +1021,704 @@ eMBException funcWriteMultipleCoils (rt_uint8_t *reqFrame, rt_uint16_t reqLen, return eStatus; } +static void parse_load_no_group(rt_uint8_t protoCmd, rt_uint8_t *pData, rt_uint16_t reqLen, struct chrg_switch_t *pSW) +{ + rt_uint16_t volt_mv = 0; // 协议请求电压(mV) + rt_uint16_t curr_ma = 0; // 负载电流(mA) + + // 数据区索引:0=状态+通道,1=CC线,2,选择恒压恒流模式3-4=电压,5-6=电流,6-7=保留 + volt_mv = u8v_to_u16(&pData[3]); // 电压(mV,大端) + curr_ma = u8v_to_u16(&pData[5]); // 电流(mA,大端) + + // 按协议命令码赋值 + switch (protoCmd) + { + case 0x11: // QC2.0 + pSW->sink.protocol = LOAD_PRO_QC20; + break; + case 0x12: // QC3.0 + pSW->sink.protocol = LOAD_PRO_QC30; + break; + case 0x13: // FCP + pSW->sink.protocol = LOAD_PRO_FCP; + break; + case 0x14: // AFC + pSW->sink.protocol = LOAD_PRO_AFC; + break; + case 0x15: // SCP + pSW->sink.protocol = LOAD_PRO_SCP; + break; + case 0x16: // VIVO + pSW->sink.protocol = LOAD_PRO_VIVO; + break; + case 0x17: // TFC + pSW->sink.protocol = LOAD_PRO_TFC_RFC; + break; + default: + rt_kprintf("无组号负载协议不支持:0x%02X\n", protoCmd); + return; + } + + // 赋值通用参数 + pSW->sink.loadv = volt_mv; + pSW->sink.loadc = curr_ma; + pSW->sink.Pro_Group = 0; // 无组号 + rt_kprintf("pro=%d,volt_mv=%d,curr=%d",pSW->sink.protocol,volt_mv,curr_ma); +} + +static void parse_load_with_group(rt_uint8_t protoCmd, rt_uint8_t *pData, rt_uint16_t reqLen, struct chrg_switch_t *pSW) +{ + rt_uint8_t group_num = 0; // 组号 + rt_uint16_t volt_mv = 0; // 协议请求电压(mV) + rt_uint16_t curr_ma = 0; // 负载电流(mA) + + // 数据区索引:0=状态+通道,1=CC线,2=恒压恒流模式,3=组号 + group_num = pData[3]; + pSW->sink.Pro_Group = group_num; + + // 按协议命令码分支 + switch (protoCmd) + { + case CMD_LOAD_PD0_MAN: // PD0(手动) + pSW->sink.protocol = LOAD_PRO_PDO_MANUAL; + // PD0特殊:组号后为3个保留2字节,无电压电流 + volt_mv = 0; + curr_ma = 0; + break; + case CMD_LOAD_PD0_AUTO: // PDO自动 + pSW->sink.protocol = LOAD_PRO_PDO_AUTO; + volt_mv = u8v_to_u16(&pData[4]); // 4-5=电压 + curr_ma = u8v_to_u16(&pData[6]); // 6-7=电流 + break; + case CMD_LOAD_PPS_MAN: // PPS(手动) + pSW->sink.protocol = LOAD_PRO_PPS_MANUAL; + volt_mv = u8v_to_u16(&pData[4]); + curr_ma = u8v_to_u16(&pData[6]); + break; + case CMD_LOAD_PPS_AUTO: // PPS(自动) + pSW->sink.protocol = LOAD_PRO_PPS_AUTO; + volt_mv = u8v_to_u16(&pData[4]); + curr_ma = u8v_to_u16(&pData[6]); + break; + case CMD_LOAD_PD31: // PD3.1 + pSW->sink.protocol = LOAD_PRO_PD31AVS; + volt_mv = u8v_to_u16(&pData[4]); + curr_ma = u8v_to_u16(&pData[6]); + break; + case CMD_LOAD_UFCS: // UFCS + pSW->sink.protocol = LOAD_PRO_UFCS; + volt_mv = u8v_to_u16(&pData[4]); + curr_ma = u8v_to_u16(&pData[6]); + break; + case CMD_LOAD_VOOC: // VOOC + pSW->sink.protocol = LOAD_PRO_VOOC; + volt_mv = 0; + curr_ma = 0; + break; + case CMD_LOAD_AVS: // AVS + pSW->sink.protocol = LOAD_PRO_AVS; + volt_mv = u8v_to_u16(&pData[4]); + curr_ma = u8v_to_u16(&pData[6]); + break; + default: + rt_kprintf("有组号负载协议不支持:0x%02X\n", protoCmd); + return; + } + rt_kprintf("volt_mv=%d,curr_ma=%d\n",volt_mv,curr_ma); + // 赋值通用参数 + pSW->sink.loadv = volt_mv; + pSW->sink.loadc = curr_ma; + +} + +// //sink开机函数 +// rt_uint8_t chrg_com_sink_on(rt_uint8_t ch, struct chrg_switch_t *pSW, rt_uint8_t *enable){ + +// *enable = 1; +// pSW->id = ID_SINK; +// pSW->sub = IDX_SET_SINK_CURR; +// pSW->change_flag = 0x01; +// pSW->sink.work_on_step = 0; +// return 0; +// } + +//source开机函数 +rt_uint8_t chrg_com_source_on(rt_uint8_t ch, rt_uint8_t protoCmd, struct chrg_switch_t *pSW, rt_uint8_t *enable){ + *enable = 1; + pSW->id = ID_SOURCE; + pSW->source.LCD_Set_Pro_Flag=3; + pSW->sub = IDX_SET_SOURCE_ID; + pSW->change_flag = 0x01; + pSW->continue_flag = 1; + return 0; +} + /***************************************************************** -函数名称: funcWriteMultipleHoldingRegister -函数描述: 写多个寄存器 +函数名称: funcWriteProtoCal +函数描述: 写入协议 输入参数: reqFrame: 请求数据 reqLen: 请求长度 resFrame:响应数据 resLen:响应长度 输出参数: - 返回说明: - 其它说明: - *****************************************************************/ +eMBException funcWriteProtoCal (rt_uint8_t *reqFrame, rt_uint16_t reqLen, + rt_uint8_t *resFrame, rt_uint16_t *resLen) +{ + /************ 局部变量定义 ************/ + struct chrg_north_t *pNOR = &chrgnorth; + struct chrg_south_t *pSOU = &chrgsouth; + struct chrg_switch_t *pSW = RT_NULL; + + rt_uint8_t slaveAddr = 0; // 从机地址(0x01~0xFF) + rt_uint8_t protoCmd = 0; // 协议命令码(0x11~0x1F/0x22~0x2C/0x2F) + rt_uint16_t regAddress = 0; // 寄存器起始地址 + rt_uint8_t *pData = RT_NULL; // 协议数据区起始指针(状态+通道字段开始) + rt_uint8_t statusChByte = 0;// 状态+通道字节(reqFrame[5]) + eIDX_SOU_CH ch = IDX_SOU_CH1;// 通道号(1~4) + rt_uint8_t chNum = 0; // 通道号数值(1~4) + rt_uint8_t devStatus = 0; // 设备状态(0=不变,1=开机,2=关机) + rt_uint8_t ccSel = 0; // CC线选择(0=CC1+CC2,1=CC1,2=CC2,3=断开) +// *g_proto_pData = RT_NULL; + g_proto_reqLen = 0; + // Modbus异常码 + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + rt_uint16_t reg_offset = 0; + rt_uint16_t sout_reg = 0; + rt_uint16_t sou_value = 0; + + /************ 校验 ************/ + // 最小帧长度:地址(1)+命令码(1)+寄存器(2)+数据区(至少1)+校验(2) = 7字节 + if (reqLen < 7) { + rt_kprintf("The long error:%d must more 7\n", reqLen); + return MB_EX_ILLEGAL_DATA_VALUE; + } + + /************ 解析帧 ************/ + slaveAddr = reqFrame[0]; // 从机地址(0x01~0xFF) + protoCmd = reqFrame[3]; // 协议命令码(负载0x11~0x1F,电源0x22~0x2C/0x2F) + rt_kprintf("pro=%04x\n",protoCmd); + pData = &reqFrame[4]; // 数据区起始(跳过地址+命令码+寄存器) + statusChByte = pData[0]; // 状态+通道字节(数据区第1字节) + + /************ 地址校验 ************/ + if (protoCmd < PRO_REG_START || protoCmd >= TOTAL_PROTOCAL_CNT) { + rt_kprintf("Address error:0x%04X\n", protoCmd); + return MB_EX_ILLEGAL_DATA_ADDRESS; + } + + /************ 提取通道号和状态 ************/ + // bit0-3:状态(0=不变,1=开机,2=关机) + devStatus = statusChByte & 0x0F; + rt_kprintf("status=%d",devStatus); + // bit4-7:通道号(1=CH1,2=CH2,3=CH3,4=CH4) + chNum = (statusChByte >> 4) & 0x0F; + ccSel = pData[1]; + rt_uint8_t cv_mode = pData[2]; + // 通道号合法性校验 + if (chNum < 1 || chNum > 4) { + rt_kprintf("通道号非法:%d(仅支持1~4)\n", chNum); + return MB_EX_ILLEGAL_DATA_ADDRESS; + } + ch = (eIDX_SOU_CH)(chNum - 1); // 转换为枚举类型(IDX_SOU_CH1=0) + /************ 硬件结构体绑定 ************/ + if (pNOR == RT_NULL) { + rt_kprintf("ERROR: pNOR is NULL!\n"); + return MB_EX_SLAVE_DEVICE_FAILURE; + } + pSW = &pNOR->sw[ch]; // 绑定当前通道的协议配置结构体 + pSW->protoCmd = protoCmd; //com端协议命令码 + pSW->CV_mode = cv_mode; //恒压恒流模式选择 + + rt_memcpy(g_proto_pData, pData, reqLen - 4); + g_proto_reqLen = reqLen; + rt_kprintf("com_recitive\n"); + /************ 按「负载/电源」分支解析 ************/ + // ========== 负载协议解析 (0x11~0x1F) ========== + if (protoCmd >= 0x11 && protoCmd <= 0x1F) { + pSW->sink.cc_set = ccSel; //负载CC线选择 + if(pSW->source.On_Flag){ //负载切电源 + pSW->source.change_sink_Flag = 1; + chrg_sou_stop(ch,pSW,pNOR); + }else{ + if(devStatus==2){ //负载关机 + chrg_sou_stop(ch,pSW,pNOR); + } + else if(devStatus==1){ //负载开机 + //chrg_com_sink_on(ch,pSW,&pNOR->enable[ch]); + } + } + } + // ==========电源协议解析 (0x22~0x2C/0x2F) ========== + else if ((protoCmd >= 0x22 && protoCmd <= 0x2C) || protoCmd == 0x2F) { + pSW->source.cc_set = ccSel; //电源CC线选择 + if(pSW->sink.On_work){ //电源切负载 + pSW->sink.change_source_flag = 1; + chrg_sou_stop(ch,pSW,pNOR); + }else{ + if(devStatus==2){ //电源关机 + chrg_sou_stop(ch,pSW,pNOR); + }else if(devStatus==1){ //电源开机 + chrg_com_source_on(ch,pSW->protoCmd,pSW,&pNOR->enable[ch]); + } + } + } + // ========== 非法命令码 ========== + else { + rt_kprintf("非法协议命令码:0x%02X\n", protoCmd); + return MB_EX_ILLEGAL_FUNCTION; + } + + // /************ 配置参数写入保持寄存器 ************/ + eRegStatus = mb_reg_holding_cb(&reqFrame[4], &resFrame[3], regAddress, 1, MB_REG_WRITE); + if (eRegStatus != MB_ENOERR) { + eStatus = mb_error(eRegStatus); + rt_kprintf("寄存器写入失败:%d\n", eRegStatus); + } + + /************ 构建响应帧 ************/ + rt_memcpy(resFrame, reqFrame, reqLen); + *resLen = reqLen - 2; // 去掉CRC校验位 + + /************ 调试输出 ************/ +// rt_kprintf("Pro Set OK:Ch=%d,Pro0x%02X,Status%d,CC Set%d\n", +// chNum, protoCmd, devStatus, ccSel); + return eStatus; +} + +/***************************************************************** +函数名称: funcSinkTest +函数描述: 负载测试 +输入参数: reqFrame: 请求数据 reqLen: 请求长度 resFrame:响应数据 resLen:响应长度 +输出参数: - +返回说明: - +其它说明: - +*****************************************************************/ +eMBException funcSinkTest (rt_uint8_t *reqFrame, rt_uint16_t reqLen, + rt_uint8_t *resFrame, rt_uint16_t *resLen) +{ + /************ 局部变量定义 ************/ + struct chrg_north_t *pNOR = &chrgnorth; + struct chrg_south_t *pSOU = &chrgsouth; + struct chrg_switch_t *pSW = RT_NULL; + + rt_uint8_t slaveAddr = 0; // 从机地址 + rt_uint8_t test_mode = 0; // 测试模式 0x01/0x02/0x03 + rt_uint16_t regAddress = 0; // 寄存器地址 + rt_uint8_t *pData = RT_NULL; // 数据区指针 + rt_uint8_t statusChByte = 0; // 状态+通道字节 + eIDX_SOU_CH ch = IDX_SOU_CH1; // 通道枚举 + rt_uint8_t chNum = 0; // 通道号 1~4 + rt_uint8_t devStatus = 0; // 设备状态 0=启动 1=停止,2=继续,3=结束 + + // Modbus异常 + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + +// /************ 长度校验 ************/ +// if (reqLen < 11) { +// rt_kprintf("Len error:%d <11\n", reqLen); +// return MB_EX_ILLEGAL_DATA_VALUE; +// } + + /************ 解析帧 ************/ + slaveAddr = reqFrame[0]; + test_mode = reqFrame[3]; // 测试命令:0x01短路 0x02OCP 0x03动态 + pData = &reqFrame[4]; // 数据起始 + statusChByte= pData[0]; // 状态通道字节 + + /************ 地址校验 ************/ + if (test_mode < 0x01 || test_mode > 0x03) { + rt_kprintf("Test mode err:0x%02X\n", test_mode); + return MB_EX_ILLEGAL_DATA_ADDRESS; + } + + /************ 解析状态 & 通道 ************/ + devStatus = statusChByte & 0x0F; // 低4位:状态 + chNum = (statusChByte >> 4) & 0x0F; // 高4位:通道 + + /************ 通道校验 ************/ + if (chNum <1 || chNum>4) { + rt_kprintf("Ch err:%d\n", chNum); + return MB_EX_ILLEGAL_DATA_ADDRESS; + } + ch = (eIDX_SOU_CH)(chNum -1); + + /************ 绑定结构体 ************/ + pSW = &pNOR->sw[ch]; + pSW->sink.test.test_mode = test_mode; //测试模式 + pSW->sink.test.run_flag = devStatus; //设备状态 + pSW->change_flag = 0x01; + struct test *pTset = &pSW->sink.test; + #if SINK_TEST_DEBUG + rt_kprintf("test_mode=%d\n",test_mode); + rt_kprintf("test_flag=%d\n",pTset->test_mode); + #endif + /*********************************************************/ + switch(test_mode) + { + case 0x01: + // 短路测试(OCPC) + sink_test_short_set(pSW, pData, devStatus); + break; + case 0x02: + // OCP 测试 + sink_test_ocp_set(pSW, pData, devStatus); + break; + case 0x03: + // 动态测试 + sink_test_dynamic_set(pSW, pData, devStatus); + break; + default: + return MB_EX_ILLEGAL_FUNCTION; + } + /************ 启动 / 停止控制 ************/ + if(devStatus == 0) //启动 + { + pNOR->enable[ch] = 1; + pSW->id = ID_SINK; + pSW->sink.test.work_step = 0; + pSOU->online[ch] = 1; + } + else if(devStatus == 1) //停止 + { + pSW->id = ID_SINK; + pSW->sink.test.stop_step = 0; + rt_kprintf("Sink Test Stop CH%d\n", chNum); + } + + /************ 响应帧 ************/ + rt_memcpy(resFrame, reqFrame, reqLen-2); + *resLen = reqLen -2; + + return eStatus; +} +/***************************************************************** +函数名称: funcWriteMultipleHoldingRegister +函数描述: 写多个保持寄存器(0x10) + 规则:reqFrame[2] = 分区高字节(SINK/SRC/SYS),reqFrame[3] = 分区内起始偏移 + 不再做全局保持寄存器地址越界判断,仅做通道合法校验,写入影子寄存器 +输入参数: reqFrame: 请求数据 reqLen: 请求长度 resFrame:响应数据 resLen:响应长度 +输出参数: - +返回说明: - +*****************************************************************/ eMBException funcWriteMultipleHoldingRegister (rt_uint8_t *reqFrame, rt_uint16_t reqLen, rt_uint8_t *resFrame, rt_uint16_t *resLen) { - rt_uint16_t regAddress = 0, cntReg = 0; + struct chrg_north_t *pNOR = &chrgnorth; + struct chrg_south_t *pSOU = &chrgsouth; + struct chrg_switch_t *pSW = RT_NULL; + + // 公共变量(两种模式共用) + rt_uint16_t cntReg = 0; rt_uint8_t ucRegByteCount; + rt_uint8_t *pWriteData = RT_NULL; + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + // 模式私有变量 +#if TRIM_NORTH + rt_uint16_t regAddress = 0; +#else + rt_uint8_t regAddress_H = 0; + rt_uint16_t regBaseOffset = 0; +#endif + + // ========== 公共校验逻辑(只写一遍)========== + if (4 + MB_PDU_FUNC_WRITE_MUL_SIZE_MIN > reqLen) { + rt_kprintf("LEN ERROR"); + return MB_EX_ILLEGAL_DATA_VALUE; + } + cntReg = u8v_to_u16(&reqFrame[4]); + ucRegByteCount = reqFrame[6]; + if ((0 == cntReg) + || (cntReg > MB_PDU_FUNC_WRITE_MUL_COILCNT_MAX) + || (ucRegByteCount != cntReg * 2)) + { + rt_kprintf("DATA ERROR"); + return MB_EX_ILLEGAL_DATA_VALUE; + } + pWriteData = &reqFrame[7]; + + // ========== 分支业务逻辑 ========== +#if TRIM_NORTH + // 校准模式:旧连续地址逻辑 + regAddress = u8v_to_u16(&reqFrame[2]); + if (regAddress < HOLD_REG_START || (regAddress + cntReg - 1) >= (HOLD_REG_START + TOTAL_HOLD_ALL_REGS)) { + rt_kprintf("ADDRESS ERROR"); + return MB_EX_ILLEGAL_DATA_ADDRESS; + } + + for (int i = 0; i < cntReg; i++) + { + rt_uint16_t Curr_reg_addr = regAddress + i; + rt_uint16_t Curr_reg_offset = Curr_reg_addr - HOLD_REG_START; + eIDX_SOU_CH ch = (eIDX_SOU_CH)(Curr_reg_offset / TOTAL_HOLD_CH_REGS); + + if (ch > IDX_SOU_CH4) { + rt_kprintf("WRITE MULTI REG: CH ERROR, ch=%d (reg=0x%04X)\n", ch, Curr_reg_addr); + return MB_EX_ILLEGAL_DATA_ADDRESS; + } + if (pNOR == RT_NULL) { + rt_kprintf("WRITE MULTI REG: ERROR: pNOR is NULL! (reg=0x%04X)\n", Curr_reg_addr); + return MB_EX_SLAVE_DEVICE_FAILURE; + } + pSW = &pNOR->sw[ch]; + rt_uint16_t sou_value = u8v_to_u16(&pWriteData[i * 2]); + rt_uint16_t sout_reg = Curr_reg_offset % TOTAL_HOLD_CH_REGS; + + switch (sout_reg) + { + case REG_VOLTAGE_OUT + 1: + pSW->source.max_vol = sou_value; + pSW->sink.loadv = sou_value; + chrg_set_sou_reg(ch, sout_reg, sou_value); + rt_kprintf("voltage=%d", sou_value); + break; + case REG_CURRENT_OUT + 1: + pSW->source.protective_curr = sou_value; + pSW->sink.loadc = sou_value; + chrg_set_sou_reg(ch, sout_reg, sou_value); + break; + default: + rt_kprintf("THE SOUT_REG=%d", sout_reg); + break; + } + rt_kprintf("ch=:%d,reg=%02x,value=%02x", ch, sout_reg, sou_value); + } +#else + // 正常产品模式:分区地址逻辑 + regAddress_H = reqFrame[2]; + regBaseOffset = reqFrame[3]; + + for (int i = 0; i < cntReg; i++) + { + rt_uint16_t curr_part_offset = regBaseOffset + i; + eIDX_SOU_CH ch = (eIDX_SOU_CH)(curr_part_offset / TOTAL_HOLD_CH_REGS); + rt_uint16_t ch_reg_offset = curr_part_offset % TOTAL_HOLD_CH_REGS; + + if (ch > IDX_SOU_CH4) { + //rt_kprintf("WRITE MULTI REG: CH ERROR, ch=%d (part offset=%d)\n", ch, curr_part_offset); + return MB_EX_ILLEGAL_DATA_ADDRESS; + } + pSW = &g_shadow_sw[ch]; + chrg_shadow_sync(ch); // 首次写同步真实状态 + rt_uint16_t sou_value = u8v_to_u16(&pWriteData[i * 2]); + + if (regAddress_H == HOLD_REG_SINK_BASE) + { + chrg_mb_write_sink(ch, ch_reg_offset, sou_value, pSW); + } + else if (regAddress_H == HOLD_REG_SRC_BASE) + { + chrg_mb_write_src(ch, ch_reg_offset, sou_value, pSW); + } + else if (regAddress_H == HOLD_REG_SYS_BASE) + { + chrg_mb_write_sys(ch, ch_reg_offset, sou_value, pSW, pNOR, pSOU); + } + else + { + //rt_kprintf("WRITE MULTI REG: INVALID PARTITION 0x%02X\n", regAddress_H); + return MB_EX_ILLEGAL_DATA_ADDRESS; + } +// rt_kprintf("ch:%d, part_offset:%d, ch_reg:%d, val:%d\n", ch, curr_part_offset, ch_reg_offset, sou_value); + } +#endif + + // ========== 公共应答帧组装、回调(只写一遍)========== + rt_memcpy(resFrame, reqFrame, reqLen); + *resLen = 6; + +#if TRIM_NORTH + eRegStatus = mb_reg_holding_cb(&reqFrame[7], &resFrame[3], regAddress, cntReg, MB_REG_WRITE); +#else + eRegStatus = mb_reg_holding_cb(&reqFrame[7], &resFrame[3], regBaseOffset, cntReg, MB_REG_WRITE); +#endif + + if (eRegStatus != MB_ENOERR) { + eStatus = mb_error(eRegStatus); + } + return eStatus; +} + +/***************************************************************** +函数名称: funcTrimELoad +函数描述: 校准源载 +输入参数: reqFrame: 请求数据 reqLen: 请求长度 resFrame:响应数据 resLen:响应长度 +输出参数: - +返回说明: - +其它说明: -只支持协议寄存器 +*****************************************************************/ +eMBException funcTrimELoad (rt_uint8_t *reqFrame, rt_uint16_t reqLen, + rt_uint8_t *resFrame, rt_uint16_t *resLen) +{ + struct chrg_north_t *pNOR = &chrgnorth; + struct chrg_south_t *pSOU = &chrgsouth; + struct chrg_switch_t *pSW = RT_NULL; + rt_uint16_t regAddress = 0, cntReg = 0; + rt_uint8_t RegCount; eMBException eStatus = MB_EX_NONE; eMBErrorCode eRegStatus; if (4+MB_PDU_FUNC_WRITE_MUL_SIZE_MIN > reqLen) { + rt_kprintf("LEN ERROR"); return MB_EX_ILLEGAL_DATA_VALUE; } - - regAddress = u8v_to_u16(&reqFrame[2]); - cntReg = u8v_to_u16(&reqFrame[4]); - ucRegByteCount = reqFrame[6]; - - if ((0 == cntReg) - ||(cntReg > MB_PDU_FUNC_WRITE_MUL_COILCNT_MAX) - ||(ucRegByteCount != cntReg*2)) { + //计算寄存器地址,数量和字节 + eIDX_SOU_CH ch = reqFrame[2]&0x0F; + rt_uint8_t enable_flag = (reqFrame[2]>>4)&0x0F; + regAddress = reqFrame[3]; + RegCount = u8v_to_u16(&reqFrame[4]); + rt_kprintf("ch=%d,enable=%d,reg=0x%02x,count=%d\n",ch+1,enable_flag,regAddress,RegCount); + if(ch<0||ch>3){ + rt_kprintf("CH ERROR"); return MB_EX_ILLEGAL_DATA_VALUE; } - + if(enable_flag == 0x00 || enable_flag == 0x01){ + }else{ + rt_kprintf("Enable Flag ERROR"); + return MB_EX_ILLEGAL_DATA_VALUE; + } + set_ymodem_update_channel(pNOR, pSOU, ch); //关掉除选定通道外的其他通道使能 + //提取首指针 + struct chrg_trim *pTrim = &pNOR->trim[ch]; + rt_uint8_t *pWriteData = &reqFrame[7]; + pNOR->north_mode = 1; + pTrim->trim_enable_flag = enable_flag; + pTrim->trim_step = 0; + //多寄存器控制操作 + for(int i =0;itrim_mode = MODE_VOLT_CAL; + pTrim->trim_volt_k_H = Curr_write_value; + break; + case ModbusRTU_Volt_CAL_K_L: + pTrim->trim_volt_k_L = Curr_write_value; + break; + case ModbusRTU_Volt_CAL_B: + pTrim->trim_volt_b = Curr_write_value; + break; + case ModbusRTU_Current_CAL_K_H: + pTrim->trim_mode = MODE_CURR_CAL; + pTrim->trim_curr_k_H = Curr_write_value; + break; + case ModbusRTU_Current_CAL_K_L: + pTrim->trim_curr_k_L = Curr_write_value; + break; + case ModbusRTU_Current_CAL_B: + pTrim->trim_curr_b = Curr_write_value; + break; + case ModbusRTU_SourceCurrent_CAL_K_H: + pTrim->trim_mode = MODE_SOURCE_CURR_CAL; + pTrim->trim_source_curr_k_H = Curr_write_value; + break; + case ModbusRTU_SourceCurrent_CAL_K_L: + pTrim->trim_source_curr_k_L = Curr_write_value; + break; + case ModbusRTU_SourceCurrent_CAL_B: + pTrim->trim_source_curr_b = Curr_write_value; + break; + case ModbusRTU_Trim_Zero_CAL: + pTrim->trim_mode = MODE_ZERO_CAL; + pTrim->trim_zero = Curr_write_value; + break; + default: + rt_kprintf("THE CAL REG=%d",Curr_reg_addr); + break; + } + //寄存器操作 + rt_kprintf("com ch=:%d,reg=%02x,value=%d\n",ch,Curr_reg_addr,Curr_write_value); + } rt_memcpy(resFrame, reqFrame, reqLen); *resLen = 6; - eRegStatus = mb_reg_holding_cb(reqFrame, &resFrame[3], regAddress, cntReg, MB_REG_WRITE); + //eRegStatus = mb_reg_holding_cb(&reqFrame[7], &resFrame[3], regAddress, cntReg, MB_REG_WRITE); if (eRegStatus != MB_ENOERR) { eStatus = mb_error(eRegStatus); } - return eStatus; } +/***************************************************************** +函数名称: funYmodemUpadata +函数描述: 南向功率板升级函数 +输入参数: reqFrame: 请求数据 reqLen: 请求长度 resFrame:响应数据 resLen:响应长度 +输出参数: - +返回说明: - +其它说明: - +*****************************************************************/ +Ymodem_state ystate = Ymodem_No; +rt_uint8_t s_first_soh_rcvd = 0; +eMBException funYmodemUpadata (rt_uint8_t *reqFrame, rt_uint16_t reqLen, + rt_uint8_t *resFrame, rt_uint16_t *resLen) +{ + rt_uint8_t test_mode = 0; // 测试模式 0x01/0x02/0x03 + eIDX_SOU_CH ch = IDX_SOU_CH1; // 通道枚举 + rt_uint8_t chNum = 0; // 通道号 1~4 + chNum = reqFrame[4]; + ch = (eIDX_SOU_CH)(chNum); + struct chrg_north_t *pNOR = &chrgnorth; + struct chrg_south_t *pSOU = &chrgsouth; + struct chrg_rollsou_t *pROLL = &chrgrollsou; + // Modbus异常 + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + if(chNum<0||chNum>3){ + return 0; + } + rt_kprintf("ch = %d",ch); + //解析上位机的帧头判断状态 + if(reqLen==8){ + if(reqFrame[5] == 0xff){ + pROLL->mode = 1; + set_ymodem_update_channel(pNOR, pSOU, ch); + ystate = Ymodem_Wait; + pROLL->ch = ch; + s_first_soh_rcvd = 0; + chrg_eload_clear_ymodem_resp(); /* 进入升级时清除残留应答 */ + } + if(reqFrame[5] == 0x00){ + pROLL->mode = 0; + ystate = Ymodem_No; + set_ymodem_update_channel(pNOR, pSOU, ch); + s_first_soh_rcvd = 0; + chrg_eload_clear_ymodem_resp(); /* 退出升级时清除残留应答 */ + } + } + + #if SINK_TEST_DEBUG + rt_kprintf("test_mode=%d\n",test_mode); + //rt_kprintf("test_flag=%d\n",pTset->test_mode); + #endif + + eRegStatus = mb_ymodem_updata_cb(&ystate,resFrame); + /************ 响应帧 ************/ + // rt_memcpy(resFrame, reqFrame, reqLen-2); + *resLen = 1;//reqLen -2; + + return eStatus; +} static struct code_func_t funcHandlers[MB_HANDLERS_MAX] = { - {MB_READ_COILS, funcReadCoils}, - {MB_READ_DISCRETE_INPUTS, funcReadDiscreteInputs}, - {MB_READ_HOLDING_REGISTER, funcReadHoldingRegister}, - {MB_READ_INPUT_REGISTER, funcReadInputRegister}, - {MB_WRITE_SINGLE_COIL, funcWriteCoil}, - {MB_WRITE_REGISTER, funcWriteHoldingRegister}, - {MB_WRITE_MULTIPLE_COILS, funcWriteMultipleCoils}, - {MB_WRITE_MULTIPLE_REGISTERS, funcWriteMultipleHoldingRegister}, -}; + {MB_READ_COILS, funcReadCoils}, + {MB_READ_DISCRETE_INPUTS, funcReadDiscreteInputs}, + {MB_READ_HOLDING_REGISTER, funcReadHoldingRegister}, + {MB_READ_INPUT_REGISTER, funcReadInputRegister}, + {MB_WRITE_SINGLE_COIL, funcWriteCoil}, + {MB_WRITE_REGISTER, funcWriteHoldingRegister}, // 0x06 + {MB_WRITE_MULTIPLE_COILS, funcWriteMultipleCoils}, + {MB_WRITE_MULTIPLE_REGISTERS, funcWriteMultipleHoldingRegister}, // 0x10 + {MB_YMODEM_UPDATAE, funYmodemUpadata}, // 0x20 Ymodem升级 + {MB_TRIM_ELOAD, funcTrimELoad}, // 0x21 校准 +}; /***************************************************************** 函数名称: chrg_comm_parse_msg @@ -691,9 +1737,11 @@ static int chrg_comm_parse_msg (struct chrg_comm_t *pCOMM) if (pCOMM->rx_len < 8) { return -2; } - +//校验 if (0 != mb_crc16(pCOMM->rx_buf, pCOMM->rx_len)) { - rt_kprintf("crc %04X ", mb_crc16(pCOMM->rx_buf, pCOMM->rx_len-2)); + rt_uint16_t crc = mb_crc16(pCOMM->rx_buf, pCOMM->rx_len-2); + rt_uint16_t crc_r = u8v_to_u16(&pCOMM->rx_buf[pCOMM->rx_len-2]); + rt_kprintf("crc %04X vs %04X\r\n", swap_u16(crc), crc_r); return -3; } @@ -703,7 +1751,7 @@ static int chrg_comm_parse_msg (struct chrg_comm_t *pCOMM) rt_uint8_t address = 0, functionCode = 0x00; address = pCOMM->rx_buf[0]; functionCode = pCOMM->rx_buf[1]; - +//判断地址 if ((address != pCOMM->addr)&&(MB_ADDRESS_BROADCAST != address)) { return ret; } @@ -714,7 +1762,7 @@ static int chrg_comm_parse_msg (struct chrg_comm_t *pCOMM) if (RT_NULL == pFunc) { break; } - + //匹配功能码和处理函数 if ((functionCode == pFunc->code)&&(RT_NULL != pFunc->func)) { eStatus = pFunc->func(pCOMM->rx_buf, pCOMM->rx_len, pCOMM->tx_buf, &pCOMM->tx_len); @@ -724,6 +1772,7 @@ static int chrg_comm_parse_msg (struct chrg_comm_t *pCOMM) if (MB_ADDRESS_BROADCAST != address) { pCOMM->tx_buf[0] = address; + //异常响应 if (MB_EX_NONE != eStatus) { pCOMM->tx_buf[1] = (functionCode | MB_FUNC_ERROR); pCOMM->tx_buf[2] = eStatus; @@ -731,7 +1780,7 @@ static int chrg_comm_parse_msg (struct chrg_comm_t *pCOMM) } crc = mb_crc16(pCOMM->tx_buf, pCOMM->tx_len); - u16_to_u8v(crc, &pCOMM->tx_buf[pCOMM->tx_len]); + u16_to_u8v_com(crc, &pCOMM->tx_buf[pCOMM->tx_len]); pCOMM->tx_len += 2; ret = chrg_tty_send(pCOMM->tty, pCOMM->tx_buf, pCOMM->tx_len); @@ -740,6 +1789,172 @@ static int chrg_comm_parse_msg (struct chrg_comm_t *pCOMM) return ret; } +///***************************************************************** +//函数名称: ymodem_send +//函数描述: 每隔一秒发一次0x43告诉上位机准备数据 +//输入参数: pCOMM: 消息结构 +//输出参数: - +//返回说明: - +//其它说明: 分命令处理对应消息。地址为广播时不应答 +//*****************************************************************/ +////返回1:需要发送数据;返回0:无需发送 +//uint8_t y_time = 0; +//uint8_t ymodem_send(struct chrg_comm_t *pCOMM,uint8_t state){ +// +// struct chrg_rollsou_t *pROLL = &chrgrollsou; +// static rt_uint8_t number = 4; +// uint8_t need_tx = 0; +// if(pROLL->send_flag==0)y_time++; +// pCOMM->tx_len = 0; //每次进来先清空发送长度 + +// /* ======== 尚未收到上位机第一个数据包: 定时发送'C'握手 ======== */ +// if (!s_first_soh_rcvd) { +// if (y_time > 20) { +// pCOMM->tx_buf[0] = ACK_C; +// pCOMM->tx_len = 1; +// need_tx = 1; +// y_time = 0; +// } +// return need_tx; +// } +// if(state == Ymodem_Rec_End){ +// //if (y_time > 20) { +// pCOMM->tx_buf[0] = ACK; +// pCOMM->tx_buf[1] = ACK_C; +// pCOMM->tx_len = 2; +// need_tx = 1; +// y_time = 0; +// number--; +// if(number == 0) +// { +// state = Ymodem_Wait; +// number = 4; +// } +// state = Ymodem_Wait; +// //} +// } +// /* ======== 已收到上位机数据包: 南向有应答立刻转发给上位机 ======== */ +// uint8_t south_resp = chrg_eload_get_ymodem_resp(); +// if (south_resp != 0) { +// switch (south_resp) { +// case ACK: +// memset(mobude_ymodem_buf_2,0,sizeof(mobude_ymodem_buf)); +// switch(state){ +// case Ymodem_Rec_End: +// case Ymodem_Rec_Start: +// pCOMM->tx_buf[0] = ACK; +// pCOMM->tx_buf[1] = ACK_C; +// pCOMM->tx_len = 2; +// break; +// case Ymodem_Rec_1024: +// pCOMM->tx_buf[0] = ACK; +// pCOMM->tx_len = 1; +// } +// need_tx = 1; +// /* Rec_End收到ACK → 南向已完成2次EOT握手,切到收尾阶段 */ +// break; +// case NAK: +// chrg_send_sou_upadata_data(mobude_ymodem_buf_2,1029); +// break; +// default: +// break; +// } +// y_time = 0; +// rt_kprintf("REC DATA = %02x\n",south_resp); +// } +// +// return need_tx; +//} + +///***************************************************************** +//函数名称: Ymodem_Process +//函数描述: 处理ymodem协议数据 +//输入参数: pCOMM: 消息结构 +//输出参数: - +//返回说明: - +//其它说明: 分命令处理对应消息。地址为广播时不应答 +//*****************************************************************/ +//uint16_t len = 0; +//eMBException Ymodem_Process(rt_uint8_t *reqFrame, rt_uint16_t reqLen, +// rt_uint8_t *resFrame, rt_uint16_t *resLen) +//{ +// eMBException eStatus = MB_EX_NONE; +// struct chrg_rollsou_t *pROLL = &chrgrollsou; +// rt_kprintf("TX_LEN = %d\n",reqLen); +//// for(int i=0;isend_flag = 1; +// s_first_soh_rcvd = 1; +// break; +// case STX: +// ystate = Ymodem_Rec_1024; +// memset(mobude_ymodem_buf,0,sizeof(mobude_ymodem_buf)); +// memcpy(mobude_ymodem_buf,reqFrame,reqLen); +// memcpy(mobude_ymodem_buf_2,reqFrame,reqLen); +// chrg_send_sou_upadata_data(mobude_ymodem_buf,reqLen); +// pROLL->send_flag = 1; +// break; +// case EOT: +// ystate = Ymodem_Rec_End; +// memset(mobude_ymodem_buf,0,sizeof(mobude_ymodem_buf)); +// memcpy(mobude_ymodem_buf,reqFrame,reqLen); +// memcpy(mobude_ymodem_buf_2,reqFrame,reqLen); +// chrg_send_sou_upadata_data(mobude_ymodem_buf,reqLen); +// pROLL->send_flag = 1; +// break; +// } +// return eStatus; +//} + +/***************************************************************** +函数名称: chrg_comm_updata_north +函数描述: 解析南向程序数据包 +输入参数: pCOMM: 消息结构 +输出参数: - +返回说明: - +其它说明: 分命令处理对应消息。地址为广播时不应答 +*****************************************************************/ +static int chrg_comm_updata_north (struct chrg_comm_t *pCOMM) +{ +// if (RT_NULL == pCOMM) { +// return -1; +// } + int ret = 0; +// uint8_t need_tx = 0; +// pCOMM->tx_len = 0; //进来先清空发送缓冲区 +// eMBException eStatus = MB_EX_NONE; +// //收到有效数据才解析Ymodem + +// if(pCOMM->rx_len == 8 && pCOMM->rx_buf[1]==0x20){ +// eStatus = funYmodemUpadata(pCOMM->rx_buf, pCOMM->rx_len, pCOMM->tx_buf, &pCOMM->tx_len); +// } +// else if(pCOMM->rx_len == 8 && pCOMM->rx_buf[1]==0x06){ +// eStatus = funcWriteHoldingRegister(pCOMM->rx_buf, pCOMM->rx_len, pCOMM->tx_buf, &pCOMM->tx_len); +// } +// else if(pCOMM->rx_len != 0){ +// rt_kprintf("len = %d\n",pCOMM->rx_len); +// Ymodem_Process(pCOMM->rx_buf, pCOMM->rx_len, pCOMM->tx_buf, &pCOMM->tx_len); +// } + +// //统一调用定时应答生成 +// need_tx = ymodem_send(pCOMM,ystate); + +// //只有标志为1且长度有效才发送 +// if(need_tx && pCOMM->tx_len > 0){ +// ret = chrg_tty_send(pCOMM->tty, pCOMM->tx_buf, pCOMM->tx_len); +// } + return ret; +} /***************************************************************** 函数名称: chrg_comm_thread_entry 函数描述: 对外RS485通信线程体 @@ -759,13 +1974,12 @@ void chrg_comm_thread_entry (void *data) int len = 0; struct chrg_tty_t *pTTY = RT_NULL; struct chrg_comm_t *pCOMM = &chrgcomm; - + struct chrg_rollsou_t *pROLL = &chrgrollsou; pTTY = chrg_tty_create(pCOMM->devname, BAUD_RATE_115200, 0, 8, 1); if (RT_NULL == pTTY) { LOG_E("tty can't create."); return ; } - chrg_tty_set_recv_tmo(pTTY, 8); if (chrg_tty_connect(pTTY) != RT_EOK) { chrg_tty_destory(pTTY); @@ -775,24 +1989,371 @@ void chrg_comm_thread_entry (void *data) pCOMM->tty = pTTY; + /* 初始化影子寄存器, 与当前 chrgnorth.sw 同步 */ + chrg_shadow_init(); + while (1) { rt_memset(pCOMM->rx_buf, 0, sizeof(pCOMM->rx_buf)); len = chrg_tty_recv(pTTY, pCOMM->rx_buf, sizeof(pCOMM->rx_buf)); +// LOG_HEX("Num=", len, pCOMM->rx_buf, len); + if(pROLL->mode==0x01){ //升级模式走单独协议 + pCOMM->rx_len = len; + pCOMM->tx_len = 0; + chrg_comm_updata_north(pCOMM); + }else{ if (len <= 0) { rt_thread_mdelay(1); continue; } - pCOMM->rx_len = len; pCOMM->tx_len = 0; - chrg_comm_parse_msg(pCOMM); + + chrg_comm_parse_msg(pCOMM); + } + } +} + + +#if 0 + +int rs485snd (int argc, char **argv) +{ + struct chrg_comm_t *pCOMM = &chrgcomm; + rt_uint8_t test[16] = { + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46}; + + if (RT_NULL != pCOMM->tty) { + chrg_tty_send(pCOMM->tty, test, 16); } + return 0; +} + +MSH_CMD_EXPORT(rs485snd, rs485 test send); + +#endif + +static void chrg_mb_write_sink(rt_uint8_t ch, rt_uint16_t reg_offset, rt_uint16_t sou_value, struct chrg_switch_t *pSW) +{ + switch (reg_offset) + { + case SINK_REG_PROTOCOL: // 0x00: 协议类型 + { + rt_uint8_t has_group = 0; + pSW->sink.protocol = sink_proto_lookup(sou_value, &has_group); + pSW->protoCmd = (rt_uint8_t)sou_value; + // rt_kprintf("[SINK CH%d] Protocol=0x%02X\n", ch + 1, pSW->sink.protocol); + } + break; + + case SINK_REG_PRO_GEAR: // 0x01: 协议挡位(组号) + pSW->sink.Pro_Group = sou_value; + // rt_kprintf("[SINK CH%d] Gear=%d\n", ch + 1, sou_value); + break; + + case SINK_REG_PRO_VOLT: // 0x02: 协议电压 (mV) + pSW->sink.pro_loadv = sou_value; + // rt_kprintf("[SINK CH%d] ProVolt=%d mV\n", ch + 1, sou_value); + break; + + case SINK_REG_PRO_CURR: // 0x03: 协议电流 (mA) + pSW->sink.pro_loadc = sou_value; + // rt_kprintf("[SINK CH%d] ProCurr=%d mA\n", ch + 1, sou_value); + break; + + case SINK_REG_CC_SEL: // 0x04: CC选择 + pSW->sink.cc_set = (rt_uint8_t)sou_value; + // rt_kprintf("[SINK CH%d] CC_SEL=%d\n", ch + 1, sou_value); + break; + + case SINK_REG_EMARK: // 0x05: E-Mark控制(预留) + break; + + case SINK_REG_LOAD_MODE: // 0x06: 负载模式 (1=恒压, 2=恒流) + pSW->CV_mode = (rt_uint8_t)sou_value; + // rt_kprintf("[SINK CH%d] LoadMode=%d\n", ch + 1, sou_value); + break; + + case SINK_REG_LOAD_VOLT: // 0x07: 负载电压 (mV) + pSW->sink.loadv = sou_value; + // rt_kprintf("[SINK CH%d] LoadVolt=%d mV\n", ch + 1, sou_value); + break; + + case SINK_REG_LOAD_CURR: // 0x08: 负载电流 (mA) + pSW->sink.loadc = sou_value; + // rt_kprintf("[SINK CH%d] LoadCurr=%d mA\n", ch + 1, sou_value); + break; + + case SINK_REG_TEST_MODE: // 0x09: 测试模式 + pSW->sink.test.test_mode = (rt_uint8_t)sou_value; + // rt_kprintf("[SINK CH%d] TestMode=%d\n", ch + 1, sou_value); + break; + + case SINK_REG_LOAD_STATUS: // 0x0A: 负载状态 (1=运行, 2=停止) + pSW->sink.Now_State = sou_value; + // rt_kprintf("[SINK CH%d] STATUS=%d\n", ch + 1, sou_value); + break; + + case SINK_REG_VON_VOLT: // 0x0B: Von电压 + pSW->sink.volt_on = sou_value; + // rt_kprintf("[SINK CH%d] VonVolt=%d mV\n", ch + 1, sou_value); + break; + + case SINK_REG_RISE_SLOPE: // 0x0C: 加载斜率(预留) + case SINK_REG_FALL_SLOPE: // 0x0D: 卸载斜率(预留) + break; + case SINK_REG_SHORT_HOLD_TIME: // 0x0E: 保持时间(ms) + pSW->sink.test.short_test.hold_time = sou_value; + break; + case SINK_REG_SHORT_SET_MODE: // 0x0F: 设置模式 + pSW->sink.test.short_test.set_mode = (rt_uint8_t)sou_value; + break; + case SINK_REG_SHORT_HAVE_CURR: // 0x10:设置是否带载 + pSW->sink.test.short_test.have_curr_flag = (rt_uint8_t)sou_value; + break; + case SINK_REG_OCP_START_CURR: // 0x11: 起始电流 + pSW->sink.test.OCP_test.start_curr = sou_value; + break; + case SINK_REG_OCP_END_CURR: // 0x12: 终点电流 + pSW->sink.test.OCP_test.end_curr = sou_value; + break; + case SINK_REG_OCP_STEP_CURR: // 0x13: 步进电流 + pSW->sink.test.OCP_test.change_curr = sou_value; + break; + case SINK_REG_OCP_STEP_TIME: // 0x14: 步进保持时间 + pSW->sink.test.OCP_test.change_keep_time = sou_value; + break; + case SINK_REG_OCP_RECOV_TIME: // 0x15: 恢复时间 + pSW->sink.test.OCP_test.hold_time = sou_value; + break; + case SINK_REG_OCP_STOP_VOLT: // 0x16: 截止电压 + pSW->sink.test.OCP_test.stop_volt = sou_value; + break; + case SINK_REG_OCP_RECOV_LOAD: // 0x17: 恢复后带载 + pSW->sink.test.OCP_test.hold_curr = (rt_uint8_t)sou_value; + break; + case SINK_REG_OCP_SET_MODE: // 0x18: 设置模式 + pSW->sink.test.OCP_test.set_mode = (rt_uint8_t)sou_value; + break; + case SINK_REG_DYNA_LOAD1: // 0x19: 动态负载1 + pSW->sink.test.change_test.curr1_set = sou_value; + break; + case SINK_REG_DYNA_TIME1: // 0x1A: 负载1保持时间 + pSW->sink.test.change_test.time1_set = sou_value; + break; + case SINK_REG_DYNA_LOAD2: // 0x1B: 动态负载2 + pSW->sink.test.change_test.curr2_set = sou_value; + break; + case SINK_REG_DYNA_TIME2: // 0x1C: 负载2保持时间 + pSW->sink.test.change_test.time2_set = sou_value; + break; + case SINK_REG_DYNA_SLOPE: // 0x1D: 加载斜率 + pSW->sink.test.change_test.k_Rise = sou_value; + break; + case SINK_REG_DYNA_UNLOAD: // 0x1E: 卸载斜率 + pSW->sink.test.change_test.k_Fall = sou_value; + break; + default: + rt_kprintf("[SINK CH%d] Unknown reg offset=0x%02X\n", ch + 1, reg_offset); + break; + } +} + +static void chrg_mb_write_src(rt_uint8_t ch, rt_uint16_t reg_offset, rt_uint16_t sou_value, struct chrg_switch_t *pSW) +{ + switch (reg_offset) + { + case SRC_REG_PROTOCOL: // 0x00: 协议 + pSW->source.protocol = src_proto_lookup(sou_value); + pSW->source.Set_Pro_Flag = 1; + pSW->protoCmd = (rt_uint8_t)sou_value; + // rt_kprintf("[SRC CH%d] Protocol=0x%02X -> 0x%02X\n", ch + 1, sou_value, pSW->source.protocol); + break; + + case SRC_REG_PRO_GEAR: // 0x01: 协议类型 + src_type_lookup(sou_value,pSW); + //rt_kprintf("[SRC CH%d] Gear=%d\n", ch + 1, sou_value); + break; + case SRC_REG_PRO_MODE: // 0x02: 输出模式 (1=恒压, 2=恒流) + pSW->CV_mode = (rt_uint8_t)sou_value; + // rt_kprintf("[SRC CH%d] Mode=%d\n", ch + 1, sou_value); + break; + case SRC_REG_MIN_VOLT: // 0x03: 最小电压 (mV) + pSW->source.min_vol = sou_value; + //rt_kprintf("[SRC CH%d] MinVolt=%d mV\n", ch + 1, sou_value); + break; + case SRC_REG_MAX_VOLT: // 0x04: 最大电压 (mV) + pSW->source.max_vol = sou_value; + // rt_kprintf("[SRC CH%d] MaxVolt=%d mV\n", ch + 1, sou_value); + break; + + case SRC_REG_MAX_CURR: // 0x05: 最大电流 (mA) + pSW->source.protective_curr = sou_value; + pSW->source.vc.set_current = sou_value; + //rt_kprintf("[SRC CH%d] MaxCurr=%d mA\n", ch + 1, sou_value); + break; + + case SRC_REG_CC_SEL: // 0x06: CC选择 + pSW->source.cc_set = (rt_uint8_t)sou_value; + //rt_kprintf("[SRC CH%d] CC_SEL=%d\n", ch + 1, sou_value); + break; + + case SRC_REG_OUTPUT_STATUS: // 0x07: 输出状态 (1=运行, 2=停止) + pSW->source.Now_State = sou_value; + break; + + default: + rt_kprintf("[SRC CH%d] Unknown reg offset=0x%02X\n", ch + 1, reg_offset); + break; + } + //rt_kprintf("ret_offset = %d, value = %d",reg_offset,sou_value); +} + +static void chrg_mb_write_sys(rt_uint8_t ch, rt_uint16_t reg_offset, rt_uint16_t sou_value, + struct chrg_switch_t *pSW, struct chrg_north_t *pNOR, struct chrg_south_t *pSOU) +{ + struct chrg_comm_t *pCOMM = &chrgcomm; + switch (reg_offset) + { + case SYS_REG_ROLE_SWITCH: // 0x00: 源/载状态切换 + if (sou_value == 0x01) + { + pSW->id = ID_SINK; + } + else if (sou_value == 0x02) + { + pSW->id = ID_SOURCE; + pSW->source.Set_Pro_Flag = 1; + } + break; + + case SYS_REG_PARAM_EFFECT: // 0x01: 参数生效标志 + if (sou_value == 0x01) + { + g_shadow_dirty[ch] = 0; // 标记已生效 + + struct chrg_switch_t *pReal = &pNOR->sw[ch]; + rt_uint8_t pro_change = 0; + sink_proto_diff_t diff_info; + chrg_sink_get_proto_diff(pReal, pSW, &diff_info, &pro_change); + eIDX_ID old_id = pReal->id; + eIDX_ID new_id = pReal->id; + rt_uint16_t sink_work = pSW->sink.Now_State; + rt_uint16_t source_work = pSW->source.Now_State; + //rt_uint8_t old_sink_test = pReal->sink.test.test_mode; + struct chrg_thread_t *pTHR_NOR = &chrgthr[IDX_THR_ROLL_NOR]; + rt_mutex_take(pTHR_NOR->mutex, RT_WAITING_FOREVER); + rt_memcpy(pReal, &g_shadow_sw[ch], sizeof(struct chrg_switch_t)); + if (new_id == ID_SINK) + { + if (sink_work == 0x01) // 负载启动 + { + rt_uint8_t curr_test = pReal->sink.test.test_mode; + rt_uint8_t curr_test_old = pReal->sink.test.test_mode_old; + // 测试模式状态发生切换:0<->非0 + if ((curr_test_old == 0 && curr_test != 0) || (curr_test == 0 && curr_test_old != 0)) + { + if (curr_test_old == 0) + { + // 从正常模式进入测试模式 + pReal->sink.work_mode = (curr_test == 3) ? SINK_WORK_ON_TEST_CHANGE : SINK_WORK_ON_TEST_SHOUT; + pReal->sink.test.test_mode_old = curr_test; + } + else + { + // 从测试模式切回正常模式 + pReal->sub = IDX_SET_SINK_CCLINE; + pReal->sink.work_mode = SINK_WORK_INIT; + } + } + else + { + // 测试模式无变化,处理负载初始化/参数更新 + if (pReal->sink.On_work == 0) + { + // 负载首次启动硬件初始化 + pReal->sink.On_work = 1; + pReal->sub = IDX_SET_SINK_CCLINE; + pReal->sink.work_mode = SINK_WORK_INIT; + } + else + { + if (pro_change) + { + // 协议参数变更,重新初始化链路 + pReal->sub = IDX_SET_SINK_CCLINE; + pReal->sink.work_mode = SINK_WORK_WAIT; + } + else + { + // 仅下发差异寄存器 + chrg_sink_diff_send_reg((eIDX_SOU_CH)ch, &diff_info, pReal); + } + } + } + } + else // sink_work == 0x00 负载停止 + { + pReal->sink.On_work = 0; + pReal->sink.work_mode = SINK_WORK_STOP; + } + chrg_sink_work(ch, pReal); + } + else if (new_id == ID_SOURCE && source_work == 0x01) + { + chrg_com_source_on(ch, pReal->protoCmd, pReal, &pNOR->enable[ch]); + } + else if (new_id == ID_SOURCE && source_work == 0x00) + { + chrg_sou_stop(ch, pReal, pNOR); + } + rt_mutex_release(pTHR_NOR->mutex); + } + break; + default: + rt_kprintf("[SYS CH%d] Unknown reg offset=0x%02X\n", ch + 1, reg_offset); + break; + } +} +void chrg_sink_get_proto_diff(struct chrg_switch_t *pReal, + struct chrg_switch_t *pShadow, + sink_proto_diff_t *pDiff, + rt_uint8_t *pChange) +{ + pDiff->proto_changed = (pReal->sink.protocol != pShadow->sink.protocol) ? 1 : 0; + pDiff->group_changed = (pReal->sink.Pro_Group != pShadow->sink.Pro_Group) ? 1 : 0; + pDiff->ccset_changed = (pReal->sink.cc_set != pShadow->sink.cc_set) ? 1 : 0; + pDiff->pro_volt_changed = (pReal->sink.pro_loadv != pShadow->sink.pro_loadv) ? 1 : 0; + pDiff->pro_curr_changed = (pReal->sink.pro_loadc != pShadow->sink.pro_loadc) ? 1 : 0; + pDiff->volt_changed = (pReal->sink.loadv != pShadow->sink.loadv) ? 1 : 0; + pDiff->curr_changed = (pReal->sink.loadc != pShadow->sink.loadc) ? 1 : 0; + pDiff->cvmode_changed = (pReal->CV_mode != pShadow->CV_mode) ? 1 : 0; + // 任意一项变更则 pro_change = 0,全部不变 = 1 + *pChange = (!pDiff->proto_changed && !pDiff->group_changed && + !pDiff->pro_volt_changed && !pDiff->pro_curr_changed && + !pDiff->ccset_changed && !pDiff->cvmode_changed) ? 0 : 1; + +} +void chrg_sink_diff_send_reg(eIDX_SOU_CH ch, sink_proto_diff_t *pDiff, struct chrg_switch_t *pReal) +{ + chrg_sou_com_sou_set(); + if(pReal->CV_mode == 0x01){ + if (pDiff->volt_changed) + { + chrg_sou_com_batch_add_reg(ch, REG_VOLTAGE_OUT+1, pReal->sink.loadv); + } + }else{ + if (pDiff->curr_changed) + { + chrg_sou_com_batch_add_reg(ch, REG_CURRENT_OUT+1, pReal->sink.loadc); + } + } + if(pDiff->cvmode_changed){ + chrg_sou_com_batch_add_reg(ch, REG_MODE, pReal->CV_mode); + } } - - - diff --git a/apps/chrg/applications/thread/chrg_comm.h b/apps/chrg/applications/thread/chrg_comm.h index df7e666..0754c9a 100644 --- a/apps/chrg/applications/thread/chrg_comm.h +++ b/apps/chrg/applications/thread/chrg_comm.h @@ -13,23 +13,30 @@ #include #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 - diff --git a/apps/chrg/applications/thread/chrg_lcd.c b/apps/chrg/applications/thread/chrg_lcd.c index e43db0a..ba22ca7 100644 --- a/apps/chrg/applications/thread/chrg_lcd.c +++ b/apps/chrg/applications/thread/chrg_lcd.c @@ -11,26 +11,25 @@ #include #include #include - - +#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 - +#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 1,set 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 1,set 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 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); + } } - } diff --git a/apps/chrg/applications/thread/chrg_lcd.h b/apps/chrg/applications/thread/chrg_lcd.h index 38e51d8..b229c12 100644 --- a/apps/chrg/applications/thread/chrg_lcd.h +++ b/apps/chrg/applications/thread/chrg_lcd.h @@ -13,7 +13,8 @@ #include #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 diff --git a/apps/chrg/applications/thread/chrg_north.c b/apps/chrg/applications/thread/chrg_north.c index bb334f1..39bdd49 100644 --- a/apps/chrg/applications/thread/chrg_north.c +++ b/apps/chrg/applications/thread/chrg_north.c @@ -10,7 +10,7 @@ #include #include #include - +#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 +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, + // 通道1(IDX_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, + } + }, + // 通道2(IDX_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, + } + }, + // 通道3(IDX_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, + } + }, + // 通道4(IDX_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 - diff --git a/apps/chrg/applications/thread/chrg_north.h b/apps/chrg/applications/thread/chrg_north.h index 71b401c..9004694 100644 --- a/apps/chrg/applications/thread/chrg_north.h +++ b/apps/chrg/applications/thread/chrg_north.h @@ -11,9 +11,8 @@ #define __CHRG_NORTH_H__ #include - -#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 diff --git a/apps/chrg/applications/thread/chrg_roll_nor.c b/apps/chrg/applications/thread/chrg_roll_nor.c index 0f2005e..52e1f01 100644 --- a/apps/chrg/applications/thread/chrg_roll_nor.c +++ b/apps/chrg/applications/thread/chrg_roll_nor.c @@ -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 - - 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: 电压值(mV,16位) + pd_curr: 电流值(mA,16位) + 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; // 转成V(5000mV→5V) + volt_hex = volt_v - 5; // 5V对应0,20V对应15(0xF) + } 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; // 步长150mA(0.75→1.5→...→3.0) + curr_hex = curr_ma_step; // 0.75A对应0,3.0A对应15(0xF) + 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; + } +} + + diff --git a/apps/chrg/applications/thread/chrg_roll_nor.h b/apps/chrg/applications/thread/chrg_roll_nor.h index 8c0f710..8fbc669 100644 --- a/apps/chrg/applications/thread/chrg_roll_nor.h +++ b/apps/chrg/applications/thread/chrg_roll_nor.h @@ -13,19 +13,34 @@ #include #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 diff --git a/apps/chrg/applications/thread/chrg_roll_sou.c b/apps/chrg/applications/thread/chrg_roll_sou.c index a50299e..94be810 100644 --- a/apps/chrg/applications/thread/chrg_roll_sou.c +++ b/apps/chrg/applications/thread/chrg_roll_sou.c @@ -1,3 +1,373 @@ +// /**************************************************************************** +// 文件名称 : chrg_roll_sou.c +// 完成日期 : +// 当前版本号 : V1.0 +// 主要功能 : 实现南向通信轮巡请求命令。以独立线程处理。 +// 版本历史 : 创建原始版本 +// 说明 : +// ******************************************************************************/ + +// #include +// #include +// #include + +// #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 + +// 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 +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 diff --git a/apps/chrg/applications/thread/chrg_roll_sou.h b/apps/chrg/applications/thread/chrg_roll_sou.h index 7ecaee1..b707c96 100644 --- a/apps/chrg/applications/thread/chrg_roll_sou.h +++ b/apps/chrg/applications/thread/chrg_roll_sou.h @@ -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 diff --git a/apps/chrg/applications/thread/chrg_south.c b/apps/chrg/applications/thread/chrg_south.c index 8450882..2fb6463 100644 --- a/apps/chrg/applications/thread/chrg_south.c +++ b/apps/chrg/applications/thread/chrg_south.c @@ -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) diff --git a/apps/chrg/applications/thread/chrg_south.h b/apps/chrg/applications/thread/chrg_south.h index 8bab9bc..ae74c37 100644 --- a/apps/chrg/applications/thread/chrg_south.h +++ b/apps/chrg/applications/thread/chrg_south.h @@ -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; diff --git a/apps/chrg/applications/thread/chrg_thread.c b/apps/chrg/applications/thread/chrg_thread.c index 0eff63f..d15de89 100644 --- a/apps/chrg/applications/thread/chrg_thread.c +++ b/apps/chrg/applications/thread/chrg_thread.c @@ -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; diff --git a/apps/chrg/applications/thread/chrg_thread.h b/apps/chrg/applications/thread/chrg_thread.h index 19f0570..e3caebb 100644 --- a/apps/chrg/applications/thread/chrg_thread.h +++ b/apps/chrg/applications/thread/chrg_thread.h @@ -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]; /***************************************************************** diff --git a/apps/chrg/applications/utils/chrg_def.h b/apps/chrg/applications/utils/chrg_def.h index a150716..3ed8388 100644 --- a/apps/chrg/applications/utils/chrg_def.h +++ b/apps/chrg/applications/utils/chrg_def.h @@ -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]; // 电压电流极值 diff --git a/apps/chrg/applications/utils/chrg_eload.c b/apps/chrg/applications/utils/chrg_eload.c index 25198aa..d5986ef 100644 --- a/apps/chrg/applications/utils/chrg_eload.c +++ b/apps/chrg/applications/utils/chrg_eload.c @@ -11,11 +11,68 @@ #include #include #include - -#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;isink.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;isource.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); +} \ No newline at end of file diff --git a/apps/chrg/applications/utils/chrg_eload.h b/apps/chrg/applications/utils/chrg_eload.h index 4cb1056..ceaa267 100644 --- a/apps/chrg/applications/utils/chrg_eload.h +++ b/apps/chrg/applications/utils/chrg_eload.h @@ -6,21 +6,69 @@ 版本历史 : 创建原始版本 说明 : ******************************************************************************/ - #ifndef __CHRG_ELOAD_H__ #define __CHRG_ELOAD_H__ #include +#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 diff --git a/apps/chrg/applications/utils/chrg_north_pkg.c b/apps/chrg/applications/utils/chrg_north_pkg.c index 4d3d78a..b442e14 100644 --- a/apps/chrg/applications/utils/chrg_north_pkg.c +++ b/apps/chrg/applications/utils/chrg_north_pkg.c @@ -9,13 +9,13 @@ #include #include - +#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; } diff --git a/apps/chrg/applications/utils/chrg_north_pkg.h b/apps/chrg/applications/utils/chrg_north_pkg.h index f0aad6c..52faed6 100644 --- a/apps/chrg/applications/utils/chrg_north_pkg.h +++ b/apps/chrg/applications/utils/chrg_north_pkg.h @@ -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 diff --git a/apps/chrg/applications/utils/chrg_regs.h b/apps/chrg/applications/utils/chrg_regs.h new file mode 100644 index 0000000..635a128 --- /dev/null +++ b/apps/chrg/applications/utils/chrg_regs.h @@ -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 { + // ==================== ͨ1CH16̵ ==================== + 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-Ԥ̵14 + COIL_REG_CH1_RESERVE2, // CH1-Ԥ̵25 + + // ==================== ͨ2CH26̵ ==================== + 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-Ԥ̵110 + COIL_REG_CH2_RESERVE2, // CH2-Ԥ̵211 + + // ==================== ͨ3CH36̵ ==================== + 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-Ԥ̵116 + COIL_REG_CH3_RESERVE2, // CH3-Ԥ̵217 + + // ==================== ͨ4CH46̵ ==================== + 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-Ԥ̵122 + COIL_REG_CH4_RESERVE2, // CH4-Ԥ̵223 + + 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 + + diff --git a/apps/chrg/applications/utils/chrg_sink.c b/apps/chrg/applications/utils/chrg_sink.c index 946a78b..64b705d 100644 --- a/apps/chrg/applications/utils/chrg_sink.c +++ b/apps/chrg/applications/utils/chrg_sink.c @@ -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; +} + diff --git a/apps/chrg/applications/utils/chrg_sink.h b/apps/chrg/applications/utils/chrg_sink.h index 08abb84..6eba83d 100644 --- a/apps/chrg/applications/utils/chrg_sink.h +++ b/apps/chrg/applications/utils/chrg_sink.h @@ -11,20 +11,63 @@ #define __CHRG_SINK_H__ #include - +struct chrg_switch_t; #include "chrg_def.h" - +#include "chrg_south.h" // 冠达快充板(SINK)通讯协议 // SINK的ID为1,波特率200K,TTL +#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、Toggle;LSB8 BIT7 短路测试时候的电流:保持/归零;bit1 过流; bit0 成功/失败 + #define ModbusRTU_DYNA_L1 0x4C //动态测试电流1 + #define ModbusRTU_DYNA_L2 0x4D //动态测试电流2 + #define ModbusRTU_DYNA_T1 0x4E //动态测试电流1的时间 + #define ModbusRTU_DYNA_T2 0x4F //动态测试电流2的时间 + #define ModbusRTU_DYNA_Rise_Slew_Rate 0x50 //动态测试上升斜率 + #define ModbusRTU_DYNA_Fall_Slew_Rate 0x51 //动态测试下降斜率 + //动态测试步骤 + #define 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 diff --git a/apps/chrg/applications/utils/chrg_source.c b/apps/chrg/applications/utils/chrg_source.c index ecc324c..76ebabf 100644 --- a/apps/chrg/applications/utils/chrg_source.c +++ b/apps/chrg/applications/utils/chrg_source.c @@ -8,13 +8,14 @@ ******************************************************************************/ #include -#include "chrg_source.h" - -#include "chrg_north.h" +#include #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> 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: 11组PDO数据缓冲区(小端序,44字节) + pdo_group_num: 实际PDO组数 + pSW: 通道协议配置结构体指针(仅校验) +输出参数: - +返回说明: - +其它说明: 1. type映射:0→src=0/pps=0;1→src=03/pps=00;2→src=03/pps=00;3→src=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组数+11组PDO+保留+保护电流+补偿电压) + reqLen: 帧总长度 + pSW: 通道协议配置结构体指针 +输出参数: - +返回说明: - +其它说明: 数据格式:状态+通道(1)+CC线(1)+PDO组数(1)+11组PDO(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 + src(2字节) + 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 + pps(2字节) + 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 + pps(2字节) + 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 + pps(2字节) + 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 + pps(2字节) + 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 + pps(2字节) + 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 + pps(2字节) + 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 + pps(2字节) + 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;isource.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 - +#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+2,1代表cc1,2代表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 0代表1+2,1代表cc1,2代表cc2 +输出参数: - +返回说明: <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}, // 0:5V挡位 + {0x00, 0x00, 0x2328, 0x2328, 0x0bb8}, // 1:9V挡位 + {0x00, 0x00, 0x2ee0, 0x2ee0, 0x0bb8}, // 2:12V挡位 + {0x00, 0x00, 0x4e20, 0x4e20, 0x0bb8}, // 3:20V挡位 + {0x00, 0x00, 0xBB80, 0xBB80, 0X0bb8} // 4:48V +// {0x03, 0x00, 0x1388, 0x4e20, 0x1388} // 4:PPS挡位 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 diff --git a/apps/chrg/applications/utils/chrg_utils.c b/apps/chrg/applications/utils/chrg_utils.c index f87c3fd..0ebcb1c 100644 --- a/apps/chrg/applications/utils/chrg_utils.c +++ b/apps/chrg/applications/utils/chrg_utils.c @@ -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>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 diff --git a/apps/chrg/applications/utils/chrg_utils.h b/apps/chrg/applications/utils/chrg_utils.h index a6a3149..2e2697f 100644 --- a/apps/chrg/applications/utils/chrg_utils.h +++ b/apps/chrg/applications/utils/chrg_utils.h @@ -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 diff --git a/apps/chrg/chrg.upk b/apps/chrg/chrg.upk new file mode 100644 index 0000000000000000000000000000000000000000..9918460fb53567c05d4dd9f025e318b6f4cc9418 GIT binary patch literal 155816 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 z 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 literal 0 HcmV?d00001 diff --git a/apps/chrg/chrg.uvprojx b/apps/chrg/chrg.uvprojx index 99c5125..fa7ac00 100644 --- a/apps/chrg/chrg.uvprojx +++ b/apps/chrg/chrg.uvprojx @@ -16,8 +16,8 @@ STM32F405RG STMicroelectronics - Keil.STM32F4xx_DFP.2.16.0 - http://www.keil.com/pack/ + Keil.STM32F4xx_DFP.3.1.1 + https://www.keil.com/pack/ IRAM(0x20000000-0x2001FFFF) IRAM2(0x10000000-0x1000FFFF) IROM(0x8000000-0x80FFFFF) CLOCK(25000000) CPUTYPE("Cortex-M4") FPU2 "Startup\ST\STM32F4xx\startup_stm32f40_41xxx.s" ("STM32F40/41xxx Startup Code") @@ -132,7 +132,7 @@ 1 0 0 - 1 + 0 1 4096 @@ -313,7 +313,7 @@ 1 - 2 + 4 0 0 1 @@ -352,7 +352,7 @@ 0 0 0 - 1 + 4 @@ -443,16 +443,16 @@ Applications/thread - - chrg_north.c - 1 - applications\thread\chrg_north.c - chrg_roll_nor.c 1 applications\thread\chrg_roll_nor.c + + chrg_north.c + 1 + applications\thread\chrg_north.c + chrg_south.c 1 @@ -468,16 +468,16 @@ 1 applications\thread\chrg_roll_sou.c - - chrg_thread.c - 1 - applications\thread\chrg_thread.c - chrg_lcd.c 1 applications\thread\chrg_lcd.c + + chrg_thread.c + 1 + applications\thread\chrg_thread.c + @@ -493,16 +493,16 @@ 1 applications\utils\chrg_sink.c - - chrg_eload.c - 1 - applications\utils\chrg_eload.c - chrg_north_pkg.c 1 applications\utils\chrg_north_pkg.c + + chrg_eload.c + 1 + applications\utils\chrg_eload.c + chrg_utils.c 1 @@ -2559,4 +2559,13 @@ + + + + chrg + 1 + + + + diff --git a/apps/chrg/debug_hot.ini b/apps/chrg/debug_hot.ini new file mode 100644 index 0000000..bccb64e --- /dev/null +++ b/apps/chrg/debug_hot.ini @@ -0,0 +1 @@ +LOAD %L INCREMENTAL \ No newline at end of file diff --git a/apps/chrg/template.uvprojx b/apps/chrg/template.uvprojx index 0244c23..f79357b 100644 --- a/apps/chrg/template.uvprojx +++ b/apps/chrg/template.uvprojx @@ -15,7 +15,7 @@ STM32F405RG STMicroelectronics - Keil.STM32F4xx_DFP.3.1.0 + Keil.STM32F4xx_DFP.3.1.1 https://www.keil.com/pack/ IRAM(0x20000000-0x2001FFFF) IRAM2(0x10000000-0x1000FFFF) IROM(0x8000000-0x80FFFFF) CLOCK(25000000) CPUTYPE("Cortex-M4") FPU2 diff --git a/mintty.2025-11-24_21-33-55.png b/mintty.2025-11-24_21-33-55.png new file mode 100644 index 0000000000000000000000000000000000000000..9826945f17348ecd483dcaf85e31135d291a828d GIT binary patch literal 64119 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 literal 0 HcmV?d00001 diff --git a/mintty.2025-11-24_21-34-04.png b/mintty.2025-11-24_21-34-04.png new file mode 100644 index 0000000000000000000000000000000000000000..9826945f17348ecd483dcaf85e31135d291a828d GIT binary patch literal 64119 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 literal 0 HcmV?d00001 diff --git a/rt-thread/libcpu/arm/cortex-m4/context_rvds.S b/rt-thread/libcpu/arm/cortex-m4/context_rvds.S index de7d713..81da34e 100644 --- a/rt-thread/libcpu/arm/cortex-m4/context_rvds.S +++ b/rt-thread/libcpu/arm/cortex-m4/context_rvds.S @@ -238,7 +238,7 @@ HardFault_Handler PROC IF {FPU} != "SoftVFP" TST lr, #0x10 ; if(!EXC_RETURN[4]) - VSTMFDEQ r0!, {d8 - d15} ; push FPU register s16~s31 + VSTMFDEQ r0!, {d8 - d15} ; push FPU register s16~s31 ENDIF STMFD r0!, {r4 - r11} ; push r4 - r11 register diff --git a/rt-thread/src/cpu_up.c b/rt-thread/src/cpu_up.c index b2531b0..0652bc1 100644 --- a/rt-thread/src/cpu_up.c +++ b/rt-thread/src/cpu_up.c @@ -101,7 +101,7 @@ struct rt_cpu *rt_cpu_self(void) /** * @brief This fucntion will return the cpu object corresponding to index. - * + *f * @param index is the index of target cpu object. * * @return Return a pointer to the cpu object corresponding to index. diff --git a/sink调试.txt b/sink调试.txt new file mode 100644 index 0000000..0790166 --- /dev/null +++ b/sink调试.txt @@ -0,0 +1,39 @@ +北桥通过405向南桥( 原载功率板)发送 + +原载功能切换通过P0 P1 P2设置 +空闲时P0=0,P1=0; P2 = 1 +负载时P0=1,P1=0,P2=0 +电源时P0=0,P1=1,P2=1 +通过rel_test set切换原载 + + +south_run stop停止 +停止后功率板会死机 +诱骗步骤: +1.设置通道 +north_ch 0 //通道0 +north_ch 1 //通道1 +north_ch 2 //通道2 +north_ch 3 //通道3 + +2.设置原载 +rel_test set 0 1 //设置通道0为sink协议模式 +rel_test set 1 1 //设置通道1为sink协议模式 +rel_test set 2 1 //设置通道2为sink协议模式 +rel_test set 3 1 //设置通道3为sink协议模式 +rel_test get 0 //检查0 +rel_test get 1 //检查1 +rel_test get 2 //检查2 +rel_test get 3 //检查3 +返回值 +rel connect [ch] : p0=1, p1=0, p2=0 //继电器切换成sink协议的信号 + +3.设置变电协议 +负载时为: +sink set 0 pd 9 //设置通道0为9V OK +sink set 1 pd 9 //设置通道1为9V OK +sink set 2 pd 9 //设置通道2为9V OK +sink set 3 pd 9 //设置通道3为9V OK +//发送指令D/sendN: 0000-000A: 0A 00 01 09 00 00 00 00 00 C1 +//回复指令05 00 01 F8 AA +诱骗不成功,检查原载接口板有没有插对通道 diff --git a/source调试.txt b/source调试.txt new file mode 100644 index 0000000..359ff95 --- /dev/null +++ b/source调试.txt @@ -0,0 +1,9 @@ +PD协议 +4c 01 02 D0 //帧头 +0a //协议 +00 00 1388 1388 0bb8 000000000000 //五V挡位(必须有) +00 00 2328 2328 0bb8 000000000000 //9V挡位 +00 00 2EE0 2EE0 0bb8 000000000000 //12V挡位 +00 00 4E20 4E20 0bb8 000000000000 //20V挡位 +03 00 1388 4E20 1388 000000000000 //PPS挡位 5-20V +2a //帧尾 \ No newline at end of file diff --git a/tp/2.sqlite b/tp/2.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..26ce862c67eb29bcf57e495a7a95fdb4e81b0838 GIT binary patch literal 516096 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 literal 0 HcmV?d00001 diff --git a/tp/pd.sqlite b/tp/pd.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..61a296e2c07c0d44406d9d8487e37ed102a78a21 GIT binary patch literal 204800 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�b&3gO8w|jr3z8&WK$*Q?9 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
    c1A+8bC4$ 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// + else{res>>=1;} + dat>>=1; + } + return res; +} \ No newline at end of file diff --git a/变电压协议设置格式(source)_V1.2.txt b/变电压协议设置格式(source)_V1.2.txt new file mode 100644 index 0000000..df72a50 --- /dev/null +++ b/变电压协议设置格式(source)_V1.2.txt @@ -0,0 +1,91 @@ +冠达快充板(SOURCE)通讯协议 + +2025.11.07 + +SOURCE的ID为2,波特率230400,TTL + +1.读取数据 +发送: +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 IH IL setvh setvl setch setcl verh verl ERR NC NC NC NC NC CRC8 +//长度+nc+ID+指令+2字节读取的电压(mV)+2字节读取的电流(mA)+2字节source设置电压(mV)+2字节source设置电流(mA)+2字节版本号+1字节错误码+5字节预留+CRC8校验 + + +2.读取source的PD协议数据(当前为PD协议时有效,不需要一直读,暂未实现) +发送:05 00 02 13 2A +回复: +XX 00 02 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字节,mA) + 最大电流/功率(2字节,mA/W,EPR_AVS时为功率) + 预留(6字节,当协议类型为02时有效,意义与前6字节一致) +00 00 VMINH VMINL VMAXH VMAXL CURH/PORH CURL/PORL NC NC NC NC NC NC +...... +CRC8 + + +3.设置CC线电平 +发送: +06 00 02 16 00 2A //长度+nc+id+指令+电平等级(0xff为根据当前电流自动设置,否则为手动设定,设置方法待定)+CRC8校验 +回复: +05 00 02 16 2A //长度+nc+id+指令+CRC8校验 + + +4.设置支持的快充协议 +(PD, FCP, AFC, SCPA中固定电压档位的最大电压和最小电压设为一样) +(QC2.0,QC3.0,SCPB仅支持1档设定,其余协议支持多档设定,pd最多11档,ufcs最多3档,其余最多4档) +发送: +XX 00 02 D0 //长度(根据实际计算)+NC+ID+指令 +00 //协议(1字节) +00 00 VMINH VMINL VMAXH VMAXL CURH CURL NC NC NC NC NC NC +//源类型(1字节,PD协议有效,00为PDO,03为APDO) ++PD类型(1字节,PD协议有效,源类型为0和3时有效,当源类型为0时,0为FPDO,1为EPRPDO,当源类型为3时,00为SPR PPS,01为EPR AVS) + 最小电压(2字节,mV) + 最大电压(2字节,mV) + 最大电流(2字节,mA) + 预留(6字节) +00 00 VMINH VMINL VMAXH VMAXL CURH CURL NC NC NC NC NC NC +...... +CRC8 +回复: +05 00 02 D0 CRC8 + +协议字节含义如下: +00 无快充 +01 VIFC(暂不支持) + +02 FCP 22 01 02 D0 02 00 00 13 88 13 88 0B B8 00 00 00 00 00 00 00 00 23 28 23 28 0B B8 00 00 00 00 00 2A + +03 SCPB +04 预留 +05 预留 +06 RFC(暂不支持) +07 QC3.0 14 01 02 D0 07 00 00 13 88 13 88 0B B8 00 00 00 00 00 00 2A +08 QC2.0 14 01 02 D0 08 00 00 13 88 13 88 0B B8 00 00 00 00 00 00 2A 没有 +09 AFC +0A PD +0B 预留 +0C UFCS +0D 预留 +0E VOOC(暂不支持) +0F SCPA + + +CRC8校验算法如下: + +u8 get_crc(u8 *dat,u8 k) +{ + u8 i,res; + res=0x55; + for(i=0;i>=1;res|=0x80;}// + else{res>>=1;} + dat>>=1; + } + return res; +} \ No newline at end of file diff --git a/屏幕控制逻辑.txt b/屏幕控制逻辑.txt new file mode 100644 index 0000000..992308a --- /dev/null +++ b/屏幕控制逻辑.txt @@ -0,0 +1,21 @@ +通过LCD发送指令改变chrg-rollnor-t结构体PD(协议),curr,volt +改变chrg_roll_nor的SET_SINK_PD的buf(实际传入值) +通过chrg_roll_nor的SET_SINK_PD对sink_set_pd函数进行传参 +通过sink_set_pd调用chrg_north_pkg_encode函数 +通过chrg_north_pkg_encode函数对指令进行编码 +最后在sink_set_pd向北桥发送指令 + + + + +电源充电协议流程: +1.设定协议,如QC2.0 此时Volt,Curr为0 +2.继电器吸合,插入检测 +3.cpu3221(source)设置Volt为5V +4.与sink握手协议 +5.source输出相应电压 +指令如下: +屏幕设置电压电流协议 +上位机输入 source set 0 pd 0 发送协议 +上位机输入rel_test set 0 2 吸合继电器 +轮询输入读取数据指令 \ No newline at end of file diff --git a/新建 文本文档.txt b/新建 文本文档.txt new file mode 100644 index 0000000..ec1aa24 --- /dev/null +++ b/新建 文本文档.txt @@ -0,0 +1,96 @@ + +14 01 02 D0 +08 +00 00 1388 2328 0bb8 000000000000 +2a + +14 01 02 D0 +07 +00 00 1388 2328 0bb8 000000000000 +2a + + +14 01 02 D0 +03 +00 00 1388 4e20 0bb8 000000000000 +2a + +14 01 02 D0 +02 +00 00 1388 2ee0 03E8 000000000000 +2a + + +14 01 02 D0 +03 +00 00 0ce4 2710 0bb8 000000000000 +2a + + +3e 01 02 D0 +09 +00 00 1388 1388 03e8 000000000000 +00 00 2328 2328 07d0 000000000000 +00 00 2ee0 2ee0 0bb8 000000000000 +00 00 4e20 4e20 0bb8 000000000000 +2a + +22 01 02 D0 +09 +00 00 1388 1388 03e8 000000000000 +00 00 2328 2328 07d0 000000000000 +2a + + +22 01 02 D0 +0c +00 00 1388 2710 03e8 000000000000 +00 00 2328 4e20 07d0 000000000000 +2a + +4c 01 02 D0 +0a +00 00 1388 1388 0bb8 000000000000 +00 00 2328 2328 0bb8 000000000000 +03 00 1388 4e20 1388 000000000000 +00 01 6d60 6d60 1388 000000000000 +03 01 3a98 6d60 1388 000000000000 +2a + +4c 01 02 D0 +0a +00 00 1388 1388 0bb8 000000000000 +00 00 2328 2328 0bb8 000000000000 +00 00 2ee0 2ee0 0bb8 000000000000 +00 00 4e20 4e20 1388 000000000000 +03 00 1388 4e20 1388 000000000000 +2a + +14 01 02 D0 +00 +00 00 1388 1388 0bb8 000000000000 +2a + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/现有设备支持协议.xlsx b/现有设备支持协议.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..d9b619d456531ad98438217298573d0147541a91 GIT binary patch literal 11473 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 literal 0 HcmV?d00001