Files
BR_YKC/Doc/README.md

672 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# BR_YKC 充电桩网关
基于 STM32H743 + AIR724 4G模块 的充电桩网关方案,对接**云快充**平台,支持通过**4G TCP**和**以太网UDP**双通道通信。
---
## 目录
- [硬件架构](#硬件架构)
- [软件架构](#软件架构)
- [目录结构](#目录结构)
- [通信拓扑](#通信拓扑)
- [三层状态机](#三层状态机)
- [通信协议](#通信协议)
- [南向协议(网关 ↔ 桩)](#南向协议网关--桩)
- [上位机协议(网关 ↔ 上位机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 回复已发送 ← 上位机回复
```