Files
BR_YKC/Doc/README.md

673 lines
25 KiB
Markdown
Raw Permalink Normal View History

2026-05-21 12:56:29 +08:00
# BR_YKC 充电桩网关
基于 STM32H743 + AIR724 4G模块 的充电桩网关方案,对接**云快充**平台,支持通过**4G TCP**和**以太网UDP**双通道通信。
2026-05-21 14:05:46 +08:00
stm32工程采用**EIDE**插件开发请在vscode中安装EIDE插件,然后在插件界面点击**打开项目**,选择`\Core\MDK-ARM\IPort.code-workspace`,即可编译下载项目。默认选择DAP下载。
2026-05-21 12:56:29 +08:00
---
## 目录
- [硬件架构](#硬件架构)
- [软件架构](#软件架构)
- [目录结构](#目录结构)
- [通信拓扑](#通信拓扑)
- [三层状态机](#三层状态机)
- [通信协议](#通信协议)
- [南向协议(网关 ↔ 桩)](#南向协议网关--桩)
- [上位机协议(网关 ↔ 上位机APP](#上位机协议网关--上位机app)
- [北向协议(网关 ↔ 云快充)](#北向协议网关--云快充)
- [4G链路协议STM32 ↔ AIR724](#4g链路协议stm32--air724)
- [上位机 C# 客户端](#上位机-c-客户端)
- [项目结构](#项目结构)
- [页面功能](#页面功能)
- [通信机制](#通信机制)
- [数据存储](#数据存储)
- [配置参数](#配置参数)
- [配置指南](#配置指南)
- [修改桩编码(序列号)](#修改桩编码序列号)
- [修改桩数量](#修改桩数量)
- [修改每桩枪数](#修改每桩枪数)
- [配置云快充服务器地址](#配置云快充服务器地址)
- [Flash组件使用说明](#flash组件使用说明)
- [框架层 drv_flash](#框架层-drv_flash)
- [应用层 flash_config](#应用层-flash_config)
- [使用示例](#使用示例)
- [任务列表](#任务列表)
- [日志格式](#日志格式)
---
## 硬件架构
```
┌──────────────────────────────────────────────┐
│ STM32H743 │
│ │
│ UART1 ─── 4G模块(AIR724) ──→ 云快充平台 (TCP)│
│ UART3 ─── RS485 │
│ ETH ──── LAN (UDP, 桩1~6 + 上位机) │
│ UART6 ─── 调试串口(printf) │
└──────────────────────────────────────────────┘
```
| 外设 | 用途 |
|------|------|
| UART1 (115200) | 与AIR724 4G模块通信 |
| UART3 | RS485接口 |
| ETH (LWIP) | 以太网桩1~6 UDP通信 + 上位机 |
| UART6 | printf调试输出 |
---
## 软件架构
```
Os/ 任务/队列/信号量/定时器管理
├─ os_task.c 5个任务的创建
├─ os_queue.c 3个消息队列
├─ os_timer.c 软件定时器
└─ os_semaphore.c 信号量/互斥量
App/ 应用层任务
├─ task_air724 4G下行数据解析任务
├─ task_udp UDP收发 + 解析任务
├─ task_ykc 云快充核心状态机任务
└─ task_sys 系统任务(心跳指示、喂狗)
Driver/ 驱动层
├─ drv_air724 AIR724命令收发 + 响应解析
├─ drv_usart 串口收发(含互斥锁)
├─ drv_flash 通用Flash读写框架
└─ flash_config 应用层Flash配置
Network/ 网络层
├─ udp_manager UDP报文发送
└─ udp_router UDP路由分发
Protocol/ 协议层
├─ Point/ 南向(充电桩JSON)
├─ Host Computer/ 上位机JSON通信
└─ Ykc/ 北向(云快充字节协议)
├─ charger_to_server 上行帧
├─ server_to_charger 下行帧
├─ server_common 公共(组包/解包/CRC)
└─ ykc_router 帧类型路由分发
Global/ 全局数据
├─ g_dcpile 桩/枪 结构体 + 管理器
├─ g_init 全局初始化
├─ g_runtime 运行时统计
└─ board_config 板级配置IP/端口)
4G/ 4G模块Lua固件
├─ core/main.lua 入口:初始化+串口+网络
├─ core/cmd.lua 命令解析+分发
└─ core/linksocket.lua 多路TCP socket管理
```
---
## 通信拓扑
```
云快充服务器(TCP)
│ 4G
AIR724模块
↑ UART1
┌─────────┴──────────┐
│ STM32H743 网关 │
│ (协议转换器) │
└─────────┬──────────┘
UDP │ 以太网
┌─────────────┼─────────────┐
│ │ │
桩1~6 上位机 RS485设备
(10.12.19.101~106) (107) (触摸屏等)
```
**数据路径:**
- **云快充 → 桩**云快充TCP → 4G → UART1 → STM32解析 → 填充数据到桩结构体
- **桩上报 → 云快充**:桩 → UDP → STM32 → 打包Ykc帧 → UART1 → 4G → TCP → 云快充
- **上位机查询**:上位机 → UDP → STM32 → 查询桩数据 → 回复
---
## 三层状态机
[task_ykc.c](file:///d:/公司项目/BR_YKC/Core/User/App/task_ykc.c) 实现了 **桩层 + 枪层** 两层非阻塞时间片状态机:
### 桩层初始化桩0~2通用只做一次
```
step 0 ── 等待桩UDP上电 → 连接4G通道(i+1)
↓ (socket_connected[i] == true)
step 1 ── 发送云快充登录(0x01)
↓ (is_online == true)
step 2 ── 发送计费模型验证(0x05) + 请求(0x09)
↓ (get_model == true)
step 3 ── 进入枪层运行态
```
### 枪层运行(每把枪独立)
```
gun_step 0 ── 每5秒上传实时数据(0x13) + 主动上报到上位机
如有账单(is_get_bill==true),上传交易记录(0x3B)
```
### 非阻塞机制
所有 `osDelay()` 已被替换为**时间戳轮询**
```c
now = HAL_GetTick();
if (now < pile->step_tick) // 时间没到,立即跳过,不阻塞
continue;
// 执行动作
pile->step_tick = now + 5000; // 设定5秒后的下次超时
```
6个桩每轮循环只需微秒级完成互不阻塞。
---
## 通信协议
### 南向协议(网关 ↔ 桩)
- **传输**:以太网 UDP
- **端口**Server=6001, Stake=6001, App=6002
- **桩IP**10.12.19.101 ~ 106
- **格式**JSON
**路由表** [udp_router.c](file:///d:/公司项目/BR_YKC/Core/User/Network/udp_router.c)
| cmd | 桩ID来源 | 处理函数 | 说明 |
|-----|---------|----------|------|
| `online` | 桩1~6 | `point_callback_power_on` | 上电,设置 is_udp_online |
| `heartbeat` | 桩1~6 | `point_callback_heartbeat` | 心跳 |
| `start charging` | 桩1~6 | `point_callback_start_charging` | 开始充电反馈 |
| `end charging` | 桩1~6 | `point_callback_end_charging` | 停止充电反馈 |
| `realtime data` | 桩1~6 | `point_callback_realtime_data` | 实时数据 |
| `settlement bill` | 桩1~6 | `point_callback_settlement_bill` | 结算账单 |
| `proactive end charging` | 桩1~6 | `point_callback_proactive_end_charging` | 桩主动停止 |
| `charge process real` | 桩1~6 | `point_callback_charge_process` | BMS需求 |
| `bms info real` | 桩1~6 | `point_callback_bms_info` | BMS信息 |
**桩未上电拦截**:除 `online` 外,所有桩指令都会检查 `is_udp_online`,未上电的桩指令将被静默丢弃。
### 上位机协议(网关 ↔ 上位机APP
- **传输**:以太网 UDP同一通道
- **端口**Server=6001, App=6002
- **上位机ID**7
- **格式**JSON`request_id` + `success`
**指令表** [host_computer_protocol.h](file:///d:/公司项目/BR_YKC/Core/User/Protocol/Host%20Computer/host_computer_protocol.h)
| cmd | 功能 | 处理函数 | 回复字段 |
|-----|------|----------|----------|
| `server_login` | 登录 | `host_computer_on_login` | success |
| `server_get_status` | 获取所有桩状态 | `host_computer_on_get_status` | piles[].serial/is_online/guns[].status |
| `server_reboot` | 重启网关 | `host_computer_on_reboot` | 无(立即重启) |
| `gateway_get_info` | 查询网关信息 | `host_computer_on_get_gw_info` | device_id, software_ver, hardware_ver, uptime |
| `gateway_get_4g_status` | 查询4G状态 | `host_computer_on_get_4g_status` | iccid, net_status, signal, isp |
| `gateway_get_cloud_config` | 查询云配置 | `host_computer_on_get_cloud_config` | host, port |
| `gateway_set_cloud_config` | 设置云配置 | `host_computer_on_set_cloud_config` | host, port触发重连 |
| `gateway_get_net_config` | 查询网络配置 | `host_computer_on_get_net_config` | ip, mask, gateway, dns |
| `gateway_set_net_config` | 设置网络配置 | `host_computer_on_set_net_config` | success重启生效 |
| `server_get_pile_info` | 查询单个桩信息 | `host_computer_on_get_pile_info` | serial, type, gun_num, protocol_ver, software_ver, sim |
### 北向协议(网关 ↔ 云快充)
- **传输**4G TCP
- **数据格式**字节流含CRC16校验
- **封装**`55 AA 01 socketId len [ykc_frame] AA 55`
#### YKC帧格式
```
┌────────┬──────┬────────┬─────────┬────────┬──────────┬──────┐
│ 0x68 │ len │ serial │encrypt │type │ data │ crc │
│ (起始) │(1字节)│ (2字节)│ (1字节) │(1字节) │ (n字节) │2字节│
└────────┴──────┴────────┴─────────┴────────┴──────────┴──────┘
```
#### 帧类型(上行 → 云快充)
| type | 函数 | 说明 |
|------|------|------|
| 0x01 | `charger_to_server_0X01` | 登录认证 |
| 0x03 | `charger_to_server_0X03` | 心跳 |
| 0x05 | `charger_to_server_0X05` | 计费模型验证 |
| 0x09 | `charger_to_server_0X09` | 计费模型请求 |
| 0x13 | `charger_to_server_0X13` | 实时监测数据 |
| 0x19 | `charger_to_server_0X19` | 充电结束 |
| 0x33 | `charger_to_server_0X33` | 远程启动回复 |
| 0x35 | `charger_to_server_0X35` | 远程停机回复 |
| 0x3B | `charger_to_server_0X3B` | 交易记录 |
| 0x57 | `charger_to_server_0x57` | 计费模型应答 |
#### 帧类型(下行 ← 云快充)
| type | 处理函数 | 说明 |
|------|----------|------|
| 0x02 | `on_cmd_frame_type_0X02` | 登录认证应答 |
| 0x04 | `on_cmd_frame_type_0X04` | 心跳应答 |
| 0x06 | `on_cmd_frame_type_0X06` | 计费模型验证应答 |
| 0x0A | `on_cmd_frame_type_0X0A` | 获取计费模型 |
| 0x58 | `on_cmd_frame_type_0X58` | 计费模型设置 |
| 0x34 | `on_cmd_frame_type_0X34` | 平台启动充电 |
| 0x36 | `on_cmd_frame_type_0X36` | 平台控制停止充电 |
| 0x40 | `on_cmd_frame_type_0X40` | 交易记录确认 |
### 4G链路协议STM32 ↔ AIR724
AIR724模块内部运行Lua脚本 [cmd.lua](file:///d:/公司项目/BR_YKC/4G/code/core/cmd.lua) + [linksocket.lua](file:///d:/公司项目/BR_YKC/4G/code/core/linksocket.lua)
```
55 AA mainCmd subCmd [payload] AA 55
```
| mainCmd | subCmd | 功能 |
|---------|--------|------|
| 0x01 | socketId | 数据发送到指定Socket |
| 0x02 | - | 系统重启 |
| 0x03 | 0x01/0x02 | 连接/断开Socket |
| 0x04 | 0x00 | 设置服务器地址 |
| 0x05 | 0x01~0x03 | 查询ICCID/IMSI/IMEI |
| 0x06 | 0x00 | 查询信号强度 |
| 0x07 | 0x00 | 查询链路状态 |
**上行响应4G → STM32**
| mainCmd | subCmd | 含义 |
|---------|--------|------|
| 0x83 | 0x01 | TCP已连接 |
| 0x83 | 0x02 | TCP已断开 |
| 0x83 | 0x03 | TCP连接失败 |
| 0x84 | 0x01~0x03 | SIM信息ICCID/IMSI/IMEI |
| 0x85 | - | 信号强度 |
| 0x86 | - | 链路状态 |
---
## 上位机 C# 客户端
C# 上位机客户端项目位于 `C:\Users\Administrator\PycharmProjects\PythonProject\C#\YKC`,基于 **.NET Framework 4.7.2** + **WPF** 框架开发,通过 **UDP** 与网关通信。
### 项目结构
```
YKC/
├── App.xaml(.cs) 程序入口
├── MainWindow.xaml(.cs) 主窗口(导航框架)
├── LoginWindow.xaml(.cs) 登录窗口
├── Config.cs 配置参数 + 指令字典
├── UdpClient.cs UDP通信客户端同步/异步)
├── PilesDataStore.cs 充电桩历史数据存储(含图表数据)
├── Pages/
│ ├── DashboardPage.xaml(.cs) 总览页面
│ ├── RealtimePage.xaml(.cs) 实时监控含OxyPlot图表
│ ├── ChargerPage.xaml(.cs) 充电桩管理
│ └── GatewayPage.xaml(.cs) 网关管理
├── bin/Debug/
│ ├── OxyPlot.dll 波形图库
│ ├── OxyPlot.Wpf.dll
│ ├── OxyPlot.Wpf.Shared.dll
│ └── Newtonsoft.Json.dll JSON库
└── Properties/ 项目属性
```
### 页面功能
#### 1. 登录页面 (LoginWindow)
- 用户名/密码认证
- 发送 `server_login` → 网关返回 `success: true/false`
- 默认账号:`admin` / `123456`
#### 2. 总览页面 (DashboardPage)
- **连接状态**:显示网关在线/离线
- **在线/充电统计**:在线桩数、充电中枪数
- **表格列表**:每桩的序列号、在线状态、每枪状态
-**5秒** 自动轮询 `server_get_status`
| 枪状态 | 含义 |
|--------|------|
| 0 | 离线 |
| 1 | 故障 |
| 2 | 空闲 |
| 3 | 充电中 |
#### 3. 实时监控页面 (RealtimePage)
- 选择桩号(1~N) + 枪号(1~N)
- 实时显示:电流(A)、电压(V)、功率(kW)、电量(kWh)、总金额、SOC、累计时间、剩余时间
- **OxyPlot 实时曲线**
- 电流/电压/功率 折线图含时间轴最多300个点
- 电费/服务费/总金额 柱状图
-**2秒** 自动轮询 `report_data` 主动上报数据来自PilesDataStore历史记录
#### 4. 充电桩管理页面 (ChargerPage)
**查询桩信息**
- 按桩索引查询
- 回复显示:序列号、类型(直流/交流)、枪数、协议版本、软件版本、SIM
**设置桩ID**
- 输入桩索引 + 14位HEX序列号
**重启网关**
- 发送 `server_reboot`(确认弹窗)
#### 5. 网关管理页面 (GatewayPage)
**网关信息卡片**
- 设备ID、软件版本、硬件版本、运行时长
- 调用 `gateway_get_info`
**4G状态卡片**
- ICCID、网络状态、信号强度(dBm)、运营商
- 调用 `gateway_get_4g_status`
**云平台配置卡片**
- 查询(`gateway_get_cloud_config`) / 保存(`gateway_set_cloud_config`)
- 保存时验证IP格式或域名格式端口 1~65535
**网络配置卡片**
- IP/掩码/网关/DNS 查询 + 设置
- 调用 `gateway_get_net_config` / `gateway_set_net_config`
- 支持IP地址格式校验
### 通信机制
UDP通信封装在 [UdpClient.cs](file:///C:/Users/Administrator/PycharmProjects/PythonProject/C%23/YKC/UdpClient.cs)
**消息格式**
```json
{
"id": 7, // 固定ID=7上位机
"cmd": "server_login",
"request_id": "server_login_1700000000000",
...其他参数...
}
```
**回复格式**
```json
{
"request_id": "server_login_...",
"success": true,
...其他数据...
}
```
**两种发送模式**
| 方法 | 说明 |
|------|------|
| `Send(payload, callback)` | 异步发送,通过回调接收回复 |
| `SendSync(payload, timeoutSec?)` | 同步发送阻塞等待回复或超时默认4秒 |
**超时机制**:异步请求启动定时器,超时后自动回调 `{ success: false, error: "timeout" }`
**主动上报接收**`OnActiveReport` 事件监听 `cmd == "report_data"` / `"pile_metrics"` / `"real_time_data"`,由 `PilesDataStore` 订阅存储。
**监听端口**`Config.LocalPort = 6002`,目标网关 `Config.TargetIp:Config.TargetPort`(默认 `10.12.19.100:6001`
### 数据存储
[PilesDataStore.cs](file:///C:/Users/Administrator/PycharmProjects/PythonProject/C%23/YKC/PilesDataStore.cs) 单例模式管理:
- **实时数据**`GetLatest(pile, gun)` → 最新一条 `JObject`
- **图表数据**`GetChartData(pile, gun)``GunData` 对象内含最多300个历史点的电流/电压/功率/电量/金额等序列
- **历史清理**超过300个点自动移除旧数据
### 配置参数
[Config.cs](file:///C:/Users/Administrator/PycharmProjects/PythonProject/C%23/YKC/Config.cs)
```csharp
TargetIp = "10.12.19.100"; // 网关IP
TargetPort = 6001; // 网关UDP端口
LocalPort = 6002; // 本机监听端口
UdpTimeout = 3; // 超时时间(秒)
```
**指令字典**(与网关 `udp_router.c` 路由表对应):
| 常量 | cmd | 对应网关处理函数 |
|------|-----|------------------|
| `LOGIN` | `server_login` | `host_computer_on_login` |
| `GET_STATUS` | `server_get_status` | `host_computer_on_get_status` |
| `REBOOT` | `server_reboot` | `host_computer_on_reboot` |
| `GET_PILE_INFO` | `server_get_pile_info` | `host_computer_on_get_pile_info` |
| `GET_GW_INFO` | `gateway_get_info` | `host_computer_on_get_gw_info` |
| `GET_4G_STATUS` | `gateway_get_4g_status` | `host_computer_on_get_4g_status` |
| `GET_CLOUD_CONFIG` | `gateway_get_cloud_config` | `host_computer_on_get_cloud_config` |
| `SET_CLOUD_CONFIG` | `gateway_set_cloud_config` | `host_computer_on_set_cloud_config` |
| `GET_NET_CONFIG` | `gateway_get_net_config` | `host_computer_on_get_net_config` |
| `SET_NET_CONFIG` | `gateway_set_net_config` | `host_computer_on_set_net_config` |
| `SET_PILE_ID` | `server_set_pile_id` | 待开发 |
| `REPORT_DATA` | `report_data` | 主动上报(南向) |
---
## 配置指南
### 修改桩编码(序列号)
修改 [g_dcpile.c](file:///d:/公司项目/BR_YKC/Core/User/Global/g_dcpile.c) 中的 `piles_serial` 数组每个桩编码为7字节十六进制
```c
/*充电桩序列号*/
const uint8_t piles_serial[6][7] = {
{0x32, 0x01, 0x06, 0x01, 0x16, 0x92, 0x45}, // 桩1
{0x32, 0x01, 0x06, 0x01, 0x16, 0x92, 0x44}, // 桩2
{0x32, 0x01, 0x06, 0x01, 0x16, 0x92, 0x43}, // 桩3
{0x32, 0x01, 0x06, 0x01, 0x16, 0x92, 0x42}, // 桩4
{0x32, 0x01, 0x06, 0x01, 0x11, 0x15, 0x58}, // 桩5
{0x32, 0x01, 0x06, 0x01, 0x11, 0x15, 0x54}, // 桩6
};
```
> `init_chargers()` 中通过 `memcpy(ctx->charger_serial, piles_serial[i], CHARGER_SERIAL_LENGTH)` 加载。
序列号转换为字符串显示时表现为14位HEX码例如 `32010601169244`
### 修改桩数量
**两步:**
**①** 修改 [g_dcpile.h](file:///d:/公司项目/BR_YKC/Core/User/Global/g_dcpile.h) 中的宏:
```c
#define MAX_CHARGER_COUNT 2 // ← 改为实际桩数量
```
**②** 确保 [g_dcpile.c](file:///d:/公司项目/BR_YKC/Core/User/Global/g_dcpile.c) 中的 `piles_serial` 数组有对应数量的序列号。
同时需要修改 [udp_router.c](file:///d:/公司项目/BR_YKC/Core/User/Network/udp_router.c) 中 `ROUTE_TABLE` 的路由数量(如果新增桩路由),以及 [task_ykc.c](file:///d:/公司项目/BR_YKC/Core/User/App/task_ykc.c) 中状态机的循环 `for (int i = 0; i < g_charger_manager.charger_count; i++)` 已自动适配。
> 桩1~6的UDP IP地址在 [udp_manager.c](file:///d:/公司项目/BR_YKC/Core/User/Network/udp_manager.c) 中硬编码:
> ```c
> static ip4_addr_t s_point_ip[6] = {
> IPADDR4_INIT_BYTES(10, 12, 19, 101), /* 桩1 */
> IPADDR4_INIT_BYTES(10, 12, 19, 102), /* 桩2 */
> ...
> };
> ```
> 如果桩数量变化,需要同步更新此数组。
### 修改每桩枪数
修改 [g_dcpile.h](file:///d:/公司项目/BR_YKC/Core/User/Global/g_dcpile.h)
```c
#define MAX_GUN_PER_CHARGER 2 // ← 改为实际枪数
```
状态机中的枪循环已自动适配:
```c
for (int g = 0; g < MAX_GUN_PER_CHARGER; g++)
```
### 配置云快充服务器地址
默认在 [linksocket.lua](file:///d:/公司项目/BR_YKC/4G/code/core/linksocket.lua) 中:
```lua
local server_config = {
ip = "129.211.170.245",
port = 9002
}
```
可通过上位机指令 `gateway_set_cloud_config` 动态修改 `s_cloud_host` / `s_cloud_port`,修改后调用 `drv_air724_set_server` 触发AIR724重新连接。
---
## Flash组件使用说明
Flash存储组件分为**两层**
### 框架层 drv_flash
[drv_flash.h](file:///d:/公司项目/BR_YKC/Core/User/Driver/drv_flash.h) / [drv_flash.c](file:///d:/公司项目/BR_YKC/Core/User/Driver/drv_flash.c)
提供通用Flash读写管理支持按帧类型存取、覆写模式、多帧管理。
#### 帧格式
```
┌──────┬──────┬──────┬──────┬──────────┬──────┐
│ HEAD │ size_low │size_high│type│ DATA │ TAIL │
│(0xA5)│ (2字节 小端) │(1字节)│(n字节) │(0x5A)│
└──────┴──────┴──────┴──────┴──────────┴──────┘
```
#### 核心API
| 函数 | 说明 |
|------|------|
| `flash_manage_init(flash_manage_t *fm)` | 初始化遍历Flash重建可读帧表 |
| `flash_manage_read(fm, *pbuf, frame_type)` | 读取指定类型的帧数据 |
| `flash_manage_write(fm, *pbuf, size, frame_type)` | 写入指定类型的帧数据 |
#### flash_manage_t 配置
```c
typedef struct {
uint8_t align_num; // 地址对齐数STM32H7一般为32
flash_write_read_mode_t flash_write_mode; // 写模式
flash_write_read_mode_t flash_read_mode; // 读模式
uint32_t flash_start_address; // 管理起始地址(按扇区对齐)
uint32_t manage_sector_num; // 管理的扇区数
uint32_t sector_size; // 扇区大小H743=128KB
void (*read_flash)(...); // 读函数指针
void (*write_flash)(...); // 写函数指针
uint8_t (*erase_sector)(...); // 擦除函数指针
} flash_manage_t;
```
### 应用层 flash_config
[flash_config.h](file:///d:/公司项目/BR_YKC/Core/User/Driver/flash_config.h) / [flash_config.c](file:///d:/公司项目/BR_YKC/Core/User/Driver/flash_config.c)
基于框架层的封装提供开箱即用的API
```c
// 单例,地址=0x081800001个Sector(128KB)32字节对齐
void stm_flash_init(void);
// 读取,传入缓冲区 + 帧类型成功返回1
int8_t stm_flash_read(uint8_t *pbuf, uint8_t frame_type);
// 写入,传入数据 + 大小 + 帧类型成功返回1
int8_t stm_flash_write(uint8_t *pbuf, uint16_t size, uint8_t frame_type);
```
> **注意**STM32H743 Bank2 的 Sector 擦除规则:
> - 起始地址 `0x08100000`每Sector = 128KB
> - 写入必须 **32字节对齐**不满32字节补 `0xFF`
> - `flash_config.c` 使用 `0x08180000`Bank2的第4个Sector
### 使用示例
```c
#include "flash_config.h"
// 初始化在main中调用一次
stm_flash_init();
// 写入配置数据
uint8_t config_data[] = {0x01, 0x02, 0x03, 0x04};
stm_flash_write(config_data, sizeof(config_data), 0x01); // 帧类型1
// 读取配置数据
uint8_t read_buf[64] = {0};
if (stm_flash_read(read_buf, 0x01) == 1) {
// 读取成功read_buf中为数据
} else {
// 无数据
}
```
**写模式**
| 模式 | 值 | 说明 |
|------|----|------|
| `FLASH_NO_OVERWRITING_MODE` | 0x00 | 只追加,不覆盖旧帧 |
| `FLASH_OVERWRITING_MODE` | 0x01 | 将旧帧头置为无效,写新帧(默认) |
**读模式**
| 模式 | 值 | 说明 |
|------|----|------|
| `FLASH_NO_CLEAR_MODE` | 0x02 | 读取后不清除(默认) |
| `FLASH_CLEAR_MODE` | 0x03 | 读取后将帧标记为无效 |
---
## 任务列表
| 任务 | 函数 | 栈大小 | 优先级 | 说明 |
|------|------|--------|--------|------|
| SysTask | `sys_task_function` | 128 | Low | 指示灯、蜂鸣器、喂狗 |
| Air724RecvTask | `air724_recv_task_function` | 1024 | AboveNormal | 解析4G下行数据 |
| UDPRecvTask | `udp_recv_task_function` | 1536 | High | UDP接收入队 |
| UDPParseTask | `udp_parse_task_function` | 2048 | AboveNormal | UDP数据解析+路由分发 |
| YkcTask | `ykc_task_function` | 1024 | AboveNormal | 云快充状态机+数据上报 |
### 消息队列
| 队列 | 长度 | 消息大小 | 用途 |
|------|------|----------|------|
| Air724_Message_Queue | 20 | 512 | 4G接收数据 |
| RS485_Message_Queue | 5 | 256 | RS485接收数据 |
| UDP_Message_Queue | 20 | sizeof(UdpMsg_t) | UDP接收数据 |
---
## 日志格式
```
[YKC Router] frame=0x02 │ stake=1 │ 登录认证应答 ← 4G下行路由
[ UDP 接收路由 ] 指令: realtime data │ 桩ID: 1 │ 实时数据 ← 南向UDP
[ UDP 路由拦截 ] 桩ID: 2 未上电,忽略指令: heartbeat ← 上电过滤
[ 北向 ] 对电桩 1 发送登录认证 ← 4G上行
[ 北向 ] 对电桩 1 枪 1 上传交易记录(0x3B)电量0.00金额0.00 ← 4G上行
[ 4G ] 通道 1 连接成功 ← 4G链路通知
[ 上位机 ] get_status 回复已发送 ← 上位机回复
```