# 电力二次保护设备 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 ```