linux_learn/learn/CAN/README.md

228 lines
8.9 KiB
Markdown
Raw Permalink 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.

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