一套面向电池管理系统的上位机软件,支持 CAN / CAN FD 通讯、UDS 诊断、固件刷写与标定,用于 BMS 研发测试阶段的实时监控、参数配置、故障诊断和程序更新。
提供 WPF 和 Avalonia 双版本,兼容周立功、Vector、PCAN、同星等主流 CAN 卡。
整体架构#
系统采用分层设计,从 UI 到硬件驱动逐层解耦:
flowchart TB
subgraph UI["UI 层"]
WPF["WPF 版本"]
AVA["Avalonia 版本"]
WPF ~~~ AVA
end
subgraph VM["ViewModel 层"]
MVVM["CommonUtility.Wpf / CommonUtility.Avalonia"]
end
subgraph BLL["业务逻辑层"]
Parser["数据解析"]
Protocol["协议处理"]
Diag["诊断服务"]
Flash["刷写流程"]
Calib["标定管理"]
Parser ~~~ Protocol ~~~ Diag ~~~ Flash ~~~ Calib
end
subgraph HAL["通讯抽象层"]
ICAN["LibCAN · ICANDevice 接口"]
end
subgraph Driver["硬件驱动层"]
PCAN["LibPCAN"]
Vector["LibVectorCAN"]
ZLG["LibZLGCAN"]
ToSun["LibToSunCAN"]
PCAN ~~~ Vector ~~~ ZLG ~~~ ToSun
end
UI --> VM --> BLL --> HAL --> Driver分层职责#
| 层级 | 职责 |
|---|---|
| UI 层 | 界面展示与用户交互,WPF / Avalonia 双版本 |
| ViewModel 层 | 绑定与命令,基于 CommonUtility.Wpf / CommonUtility.Avalonia |
| 业务逻辑层 | 数据解析、协议处理、诊断、刷写、标定 |
| 通讯抽象层 | 定义 ICANDevice 接口,隔离硬件差异 |
| 硬件驱动层 | 封装各厂商 SDK,提供统一调用方式 |
硬件驱动层设计#
不同厂商的 CAN 卡配置界面差异很大(波特率设置、通道选择、终端电阻开关等),因此驱动层按厂商拆分为独立 NuGet 包,每个包再分为 核心库 + WPF UI + Avalonia UI 三层。
| 硬件厂商 | 核心库 | WPF UI | Avalonia UI |
|---|---|---|---|
| 通用抽象 | LibCAN |
— | — |
| UDS 协议 | LibUDS |
— | — |
| CAN 日志 | LibCANLogging |
— | — |
| PCAN | LibPCAN |
LibPCAN.WPF |
LibPCAN.Avalonia |
| 同星 | LibToSunCAN |
LibToSunCAN.WPF |
LibToSunCAN.Avalonia |
| Vector | LibVectorCAN |
LibVectorCAN.WPF |
LibVectorCAN.Avalonia |
| 周立功 | LibZLGCAN |
LibZLGCAN.WPF |
LibZLGCAN.Avalonia |
设计思路#
核心库#
封装厂商 SDK,实现 ICANDevice 接口,不含 UI
WPF UI#
提供该硬件的 WPF 配置面板(继承自 UserControl)
Avalonia UI#
提供该硬件的 Avalonia 配置面板(跨平台复用)
CAN 日志#
LibCANLogging 采用装饰器模式,实现 ICANDevice 接口,并且持有同样实现了 ICANDevice 接口的厂商驱动对象,增加日志功能
支持三种日志格式: .asc、.csv、.blf,并于后续分析
总结#
-
新增一家硬件,只需实现三件套(核心库 + 两个 UI 包)
-
主程序根据当前使用的硬件,动态加载对应的 UI 包
-
业务逻辑和主界面完全不感知硬件差异
截图#
| – | PCAN | 同星 | Vector | 周立功 |
|---|---|---|---|---|
| WPF | ![]() |
![]() |
![]() |
![]() |
| Avalonia | ![]() |
![]() |
![]() |
![]() |
功能模块#
CAN / CANFD 通讯#
支持标准帧、扩展帧、CAN FD 长帧。接收与发送通过 ICANDevice 接口统一处理:
sequenceDiagram
participant App as 应用层
participant ICAN as ICANDevice
participant Driver as 厂商驱动
participant Bus as CAN 总线
App->>ICAN: Send(CanFrame)
ICAN->>Driver: 调用厂商 SDK
Driver->>Bus: 写入 CAN 帧
Bus->>Driver: 接收 CAN 帧
Driver->>ICAN: 触发 FrameReceived
ICAN->>App: 回调 CanFrameUDS 诊断#
支持 0x10 / 0x22 / 0x27 / 0x2E / 0x31 / 0x3E 等常用服务,基于 ISO-TP 处理多帧传输。
flowchart LR
A["发送 UDS 请求"] --> B{"单帧?"}
B -- 是 --> C["直接发送"]
B -- 否 --> D["ISO-TP 分包"]
D --> E["流控帧交互"]
E --> F["连续帧传输"]
C --> G["等待响应"]
F --> G
G --> H{"响应有效?"}
H -- 是 --> I["解析响应"]
H -- 否 --> J["错误处理"]安全访问流程(0x27):
sequenceDiagram
participant Tester as 上位机
participant ECU as BMS
Tester->>ECU: 0x27 请求种子
ECU-->>Tester: 返回种子
Tester->>Tester: 计算密钥
Tester->>ECU: 0x27 发送密钥
ECU-->>Tester: 解锁成功固件刷写#
基于 UDS 的 Bootloader 刷写流程:
flowchart TB
A["进入编程会话 0x10 0x02"] --> B["安全访问 0x27"]
B --> C["请求下载 0x34"]
C --> D["传输数据 0x36"]
D --> E{"传输完成?"}
E -- 否 --> D
E -- 是 --> F["退出传输 0x37"]
F --> G["校验完整性 0x31"]
G --> H["复位 ECU 0x11"]支持 .hex / .s19 文件解析、分块传输进度显示、失败重试。

标定#
通过 UDS 0x2E 写入标定数据标识符(DID),提供参数读取、修改、写入和回读校验。

多通道与总控联动#
多通道版本通过 Socket 与总控系统通信,充当 CAN 总线与总控系统之间的协议网关:
sequenceDiagram
participant Master as 总控系统
participant HMI as 上位机
participant CAN as CAN 总线
participant ECU as 下位机
Master->>HMI: Socket 下发指令
HMI->>HMI: 解析指令,转换为 UDS 请求
HMI->>CAN: 发送 UDS 命令
CAN->>ECU: 传输
ECU-->>CAN: 响应
CAN-->>HMI: 接收响应
HMI->>HMI: 解析响应
HMI->>Master: Socket 回传结果







