- docs/: 学习资料索引(7份, 涵盖驱动/DTS/AMP/应用层/实时性/STM32/硬件) - learn/CAN/: 电力二次设备CAN协议栈(v2.0, 含帧编解码/XML配置/突发队列) - learn/NPU/: NPU波形故障识别部署指南(5份, 含训练/转换/推理/CAN整合) - learn/AMP-vs-LinuxRT/: 实时方案对比分析 - memory/: Claude Code 记忆文件 - CLAUDE.md: 仓库指导文件 Co-Authored-By: Claude <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| app | ||
| config | ||
| include | ||
| src | ||
| Makefile | ||
| README.md | ||
README.md
电力二次保护设备 CAN 自定义协议栈 v2.0
一、v2.0 变更说明
基于 v1.0 方案,吸收了以下核心改进:
| # | 改进项 | v1.0 | v2.0 |
|---|---|---|---|
| 1 | 遥信编码 | 1-bit (0/1) | 2-bit DPS (IEC 61850 双位置: 中间态/分/合/无效) |
| 2 | 遥测编码 | uint16 定点数 | IEEE 754 float (通用,无需转换系数) |
| 3 | ID 优先级 | 目标地址在最高位 | 优先级类别(PRIO)在 bit28-26,紧急报文优先胜出 |
| 4 | 定时 vs 突发 | 同一帧类型 | 分离: PRIO_PERIODIC(周期) vs PRIO_BURST(突发) |
| 5 | 突发机制 | 直接发送 | 队列模式: 应用层 push → 协议栈 drain → FD 批量打包 |
| 6 | 批次号 | 帧序号 | bit7-0 批次号: 接收方去重、检测丢帧 |
| 7 | 命令序列号 | 无 | bit7-0 序列号: 匹配请求与应答 |
二、v2.0 ID 编码方案
CAN 仲裁规则:ID 值越小,优先级越高。bit28 最先发送,权重最大。
28 27 26 | 25 24 23 22 21 20 19 | 18 17 16 15 14 13 12 | 11 10 9 8 | 7 6 5 4 3 2 1 0
┌─────────────┬─────────────────────────────┬─────────────────────────────┬─────────────────┬─────────────────────────────────┐
│ PRIO (3bit) │ 目标设备 DST_ADDR (7-bit) │ 源设备 SRC_ADDR (7-bit) │ MSG_TYPE (4bit) │ 批次号/序列号 SEQ (8-bit) │
│ bit28-26 │ bit25-19 │ bit18-12 │ bit11-8 │ bit7-0 │
└─────────────┴─────────────────────────────┴─────────────────────────────┴─────────────────┴─────────────────────────────────┘
优先级类别 PRIO (bit28-26)
| PRIO | 名称 | 最小 ID 范围 | 用途 |
|---|---|---|---|
| 000 | 紧急 | 0x00000000 | 保护动作信号、遥控直跳 — 最高优先级 |
| 001 | 突发 | 0x04000000 | 遥信变位(COS)、遥测越限 — 事件驱动 |
| 010 | 命令 | 0x08000000 | 遥控选择/执行、定值读写、遥调 |
| 011 | 对时 | 0x0C000000 | 广播对时、PTP 辅助 |
| 100 | 周期 | 0x10000000 | 定时遥信/遥测上送(主动总召) |
| 101 | 文件 | 0x14000000 | 文件传输/固件升级 — 最低业务优先级 |
| 110 | 管理 | 0x18000000 | 心跳、链路测试、版本查询 |
| 111 | 保留 | 0x1C000000 | 用户扩展 |
报文类型 MSG_TYPE (bit11-8) — 与 PRIO 组合使用
过程数据类 (PRIO=周期 或 PRIO=突发):
| MSG_TYPE | 含义 |
|---|---|
| 0x0 | 遥信-定时 |
| 0x1 | 遥测-定时 |
| 0x2 | 遥信-突发 (COS/SOE) |
| 0x3 | 遥测-突发 (越限) |
命令类 (PRIO=命令):
| MSG_TYPE | 含义 |
|---|---|
| 0x0 | 遥控-选择 |
| 0x1 | 遥控-执行 |
| 0x3 | 定值-写入 |
| 0x4 | 定值-召唤 (读取当前定值, addr=0xFFFF=召唤全部) |
| 0x6 | 命令ACK |
| 0x7 | 命令NAK |
文件类 (PRIO=文件):
| MSG_TYPE | 含义 |
|---|---|
| 0x0 | 首帧 (含文件名/总段数/总长度) |
| 0x1 | 续帧 |
| 0x2 | 尾帧 (含 CRC32) |
| 0x5 | 文件召唤请求 (主站→从站: 请求上传文件) |
| 0x6 | 文件召唤就绪 (从站→主站: 文件存在, 即将发送) |
| 0x7 | 文件召唤拒绝 (从站→主站: 文件不存在等) |
批次号/序列号 SEQ (bit7-0)
- 过程数据: 批次号,每次发送递增 (0-255 循环),接收方用于去重和检测丢帧
- 命令帧: 序列号,匹配 Request ↔ ACK/NAK
- 文件帧: 帧序号
三、数据域格式 v2.0
3.1 遥信双位置 (2-bit DPS)
每字节打包 4 个遥信点:
Byte N: [点3.bit1][点3.bit0][点2.bit1][点2.bit0][点1.bit1][点1.bit0][点0.bit1][点0.bit0]
DPS 编码:
00 = 中间态/不确定 01 = 分(OFF)
10 = 合(ON) 11 = 无效/故障
定时遥信帧: [起始地址(2B)] [位对数据(N字节)] — FD 模式下可携带 248 个遥信点
3.2 遥测浮点 (IEEE 754)
每个遥测值 4 字节,IEEE 754 single-precision,大端序。
定时遥测帧: [起始地址(2B)] [float(4B) × N] — FD 模式下可携带 15 个遥测量
3.3 突发打包帧
突发遥信: [点数(1B)] [地址(2B)+状态(1B)+时标ms(4B)] × N — FD 模式每帧最多 9 个点
突发遥测: [点数(1B)] [地址(2B)+浮点值(4B)+时标ms(4B)] × N — FD 模式每帧最多 6 个点
3.4 定值帧 (浮点)
[定值地址(2B)] [float值(4B)] — 与遥测同样的 IEEE 754 格式
四、通讯机制
4.1 定时上送 (主动总召)
定时器触发 (每 500ms 扫描)
│
├── 遍历 XML 配置,检查每个信号的 period_ms 是否到期
├── 到期信号通过回调获取当前值
├── 打包为 PRIO_PERIODIC 帧(低优先级,不抢占总线)
└── 批次号递增,接收方可据此检测丢帧
4.2 突发上送 (事件驱动 + 队列打包)
应用层/中断:
│ 检测到遥信变位或遥测越限
│ can_protocol_push_yx_burst(addr, state, timestamp)
│ can_protocol_push_yc_burst(addr, value, timestamp)
▼
突发队列 (lock-free SPSC, 256 深度)
协议栈主循环 (每 5ms):
│ can_protocol_flush_burst()
├── 从队列批量 pop
├── FD 模式: 尽可能打包多个点 (遥信9个/帧, 遥测6个/帧)
├── PRIO_BURST (高优先级,仅次于紧急)
└── 短时间内排空队列
4.3 遥控 (选择-返校-执行)
不变,但使用 PRIO_COMMAND + MSG_CMD_YK_* 编码,命令序列号匹配请求和应答。
4.4 定值读写 (双向)
定值写入 (主站→从站):
主站 从站
│── PRIO=CMD, MSG=DZ_WRITE ──────► │
│ [定值地址(2B) + float值(4B)] ├── 校验范围 → 写入 Flash
│◄── MSG=ACK/NAK ──────────────── │
定值召唤 (主站→从站):
主站 从站
│── PRIO=CMD, MSG=DZ_READ ───────► │
│ [定值地址(2B), 0xFFFF=全部] ├── 读取当前定值
│◄── MSG=ACK [addr+float值] ─────── │ (逐条返回)
4.5 文件传输 (双向: 下发 + 召唤)
文件下发 (主站→从站, 如固件升级):
主站 从站
│── FIRST(文件ID, 总段数, 大小) ──► │
│◄── ACK(就绪) ─────────────────── │
│── CONT/LAST(段数据, [CRC32]) ──► │
│◄── ACK(完成) ─────────────────── │
文件召唤 (主站→从站, 如录波文件/日志):
主站 从站
│── READ_REQ(file_id, 文件路径) ──► │
│ ├── 检查文件是否存在
│◄── READ_ACK(大小, 段数, 文件名) ── │ (存在→就绪)
│◄── READ_NAK(ERR_FILE_NOT_FOUND) ── │ (不存在→拒绝)
│◄── FIRST/CONT/LAST... ─────────── │ (自动开始上传)
五、CAN FD 效率 v2.0
突发打包效率
| 场景 | CAN 2.0 (单点/帧) | CAN FD (打包) | 效率提升 |
|---|---|---|---|
| 遥信突发 10 个变位 | 10 帧 | 2 帧 (9+1) | 5× |
| 遥测突发 12 个越限 | 12 帧 | 2 帧 (6+6) | 6× |
定时数据效率
| 场景 | CAN 2.0 | CAN FD | 提升 |
|---|---|---|---|
| 16 个遥测量上送 | 6 帧 | 2 帧 | 3× |
| 50 个遥信点上送 | 7 帧 | 1 帧 | 7× |
六、文件结构
learn/CAN/
├── README.md ← 本文件
├── Makefile
├── include/
│ ├── can_id.h ← v2.0 ID 编码 (PRIO + MSG_TYPE)
│ ├── can_frame.h ← v2.0 数据格式 (2-bit YX / float YC / burst)
│ ├── can_protocol.h ← v2.0 协议栈接口 (burst queue API)
│ └── can_xml_parser.h ← XML 解析 (支持浮点定值)
├── src/
│ ├── can_id.c
│ ├── can_frame.c ← 含突发队列实现
│ ├── can_protocol.c ← 含 burst drain + batch 机制
│ └── can_xml_parser.c
├── config/
│ ├── protection_relay.xml ← 浮点定值示例
│ ├── data_center.xml
│ └── bay_controller.xml
└── app/
└── test_protocol.c