C.Can.Core
0.0.1
dotnet add package C.Can.Core --version 0.0.1
NuGet\Install-Package C.Can.Core -Version 0.0.1
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="C.Can.Core" Version="0.0.1" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="C.Can.Core" Version="0.0.1" />
<PackageReference Include="C.Can.Core" />
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add C.Can.Core --version 0.0.1
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: C.Can.Core, 0.0.1"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package C.Can.Core@0.0.1
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=C.Can.Core&version=0.0.1
#tool nuget:?package=C.Can.Core&version=0.0.1
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
Can.Core - CAN总线通信库
CAN总线通信库,基于观察者模式设计,支持 .NET 8.0 和 .NET 10.0。
安装
NuGet
dotnet add package C.Can.Core
项目引用
<ProjectReference Include="..\Can.Core\Can.Core.csproj" />
核心概念
架构设计
Can.Core 使用观察者模式 (Observer Pattern) 实现 CAN 帧的接收和分发:
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ CanPortBase │──────│ CanObserver │──────│ 业务逻辑 │
│ (被观察者) │ │ (观察者) │ │ (事件处理) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │
│ ProcessReceive() │ OnReceive事件
│───────────────────────>│
主要组件
| 组件 | 说明 |
|---|---|
CanFrame |
CAN数据帧,包含ID、数据缓冲区、是否扩展帧 |
CanGuid |
CAN端口唯一标识符(系统类型/系统编号/板卡ID/端口ID) |
CanFilter |
CAN帧过滤器,支持ID过滤和帧类型过滤 |
ICanPort |
CAN端口接口 |
CanPortBase |
CAN端口抽象基类,管理观察者列表 |
CanObserver |
CAN观察者实现类,通过事件通知接收帧 |
CanPortManager |
CAN端口管理器(单例),管理所有端口 |
使用示例
1. 创建自定义CAN端口
using Can.Core;
// 继承 CanPortBase 实现自定义端口
public class UsbCanPort : CanPortBase
{
private readonly UsbCanDevice _device;
public UsbCanPort(int systemClassId, int systemId, int cardId, int portId)
{
PortGuid = new CanGuid(systemClassId, systemId, cardId, portId);
Description = "USB-CAN Device";
_device = new UsbCanDevice();
}
public override bool Open()
{
return _device.Open();
}
public override bool Close()
{
return _device.Close();
}
public override void Send(CanFrame frame)
{
_device.Send(frame.CanId, frame.Buf, frame.IsExFrame);
}
// 在接收到数据时调用 ProcessReceive
private void OnDeviceReceive(int canId, byte[] data, bool isExFrame)
{
var frame = new CanFrame
{
CanId = canId,
Buf = data,
IsExFrame = isExFrame
};
ProcessReceive(frame); // 分发给所有观察者
}
}
2. 创建观察者接收数据
using Can.Core;
// 创建观察者
var observer = new CanObserver();
// 设置过滤器 - 只接收ID为0x123的标准帧
observer.CanFilter = new CanFilter
{
ExframeFilterFlag = ExframeFilterFlag.Can20A, // 只接收标准帧
Mask = 0x7FF, // 检查全部11位
Filter = 0x123 // ID为0x123
};
// 注册接收事件
observer.OnReceive += (port, frame) =>
{
Console.WriteLine($"收到CAN帧: ID={frame.CanId:X}, 数据={BitConverter.ToString(frame.Buf)}");
};
// 添加观察者到端口
port.AddObserver(observer);
3. 使用端口管理器
using Can.Core;
// 获取单例实例
var manager = CanPortManager.Instance;
// 创建并添加端口
var port1 = new UsbCanPort(0, 0, 0, 0);
var port2 = new UsbCanPort(0, 0, 0, 1);
manager.AddPort(port1);
manager.AddPort(port2);
// 通过名称获取端口
var foundPort = manager["Can0/0/0/0"];
// 获取所有端口
var allPorts = manager.GetPorts();
// 移除端口
manager.RemovePort(port1);
// 清空所有端口
manager.Clear();
4. 发送CAN帧
using Can.Core;
// 创建CAN帧
var frame = new CanFrame
{
CanId = 0x123,
IsExFrame = false, // 标准帧
Buf = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }
};
// 发送
port.Send(frame);
过滤器详解
帧类型过滤
// 接收所有帧(默认)
filter.ExframeFilterFlag = ExframeFilterFlag.All;
// 只接收标准帧 (CAN 2.0A)
filter.ExframeFilterFlag = ExframeFilterFlag.Can20A;
// 只接收扩展帧 (CAN 2.0B)
filter.ExframeFilterFlag = ExframeFilterFlag.Can20B;
ID过滤原理
过滤器使用掩码+匹配值的方式:
// 公式: ((CanId ^ Filter) & Mask) == 0 表示匹配
// 示例1: 精确匹配ID=0x123
filter.Mask = 0x7FF; // 检查全部11位
filter.Filter = 0x123; // 匹配值
// 示例2: 接收ID范围0x100-0x10F
filter.Mask = 0x7F0; // 只检查高7位
filter.Filter = 0x100; // 高7位必须为0x10
// 示例3: 接收所有帧(不检查ID)
filter.Mask = 0; // 不检查任何位
filter.Filter = 0; // 匹配值(无意义)
多观察者不同过滤
// 观察者1: 只接收标准帧
var observer1 = new CanObserver();
observer1.CanFilter = new CanFilter { ExframeFilterFlag = ExframeFilterFlag.Can20A };
observer1.OnReceive += (p, f) => Console.WriteLine($"标准帧: {f.CanId:X}");
// 观察者2: 只接收扩展帧,ID范围0x100-0x1FF
var observer2 = new CanObserver();
observer2.CanFilter = new CanFilter
{
ExframeFilterFlag = ExframeFilterFlag.Can20B,
Mask = 0xF00,
Filter = 0x100
};
observer2.OnReceive += (p, f) => Console.WriteLine($"扩展帧: {f.CanId:X}");
// 添加到同一端口
port.AddObserver(observer1);
port.AddObserver(observer2);
CanGuid 唯一标识
// 格式: Can{SystemClassId}/{SystemId}/{CardId}/{PortId}
// PC自带CAN口
var guid1 = new CanGuid(0, 0, 0, 0); // "Can0/0/0/0"
// 第1台通信分机,第2块板卡,第3个端口
var guid2 = new CanGuid(1, 1, 2, 3); // "Can1/1/2/3"
// 属性说明:
// - SystemClassId: 系统类型(PC=0, 通信分机=1)
// - SystemId: 系统编号
// - CardId: 板卡编号
// - PortId: 端口编号(可修改)
API 参考
CanFrame
| 属性 | 类型 | 说明 |
|---|---|---|
IsExFrame |
bool | 是否扩展帧(默认false) |
CanId |
int | CAN标识符(默认0) |
Buf |
byte[]? | 数据缓冲区(默认null) |
CanGuid
| 属性 | 类型 | 说明 |
|---|---|---|
SystemClassId |
int | 系统类型ID(只读) |
SystemId |
int | 系统编号(只读) |
CardId |
int | 板卡ID(只读) |
PortId |
int | 端口编号(可写) |
CanFilter
| 属性 | 类型 | 说明 |
|---|---|---|
ExframeFilterFlag |
enum | 帧类型过滤标志(默认All) |
Mask |
int | 过滤掩码(默认0) |
Filter |
int | 匹配值(默认0) |
| 方法 | 说明 |
|---|---|
IsValid(CanFrame) |
检查帧是否匹配过滤条件 |
ICanPort
| 属性 | 说明 |
|---|---|
PortGuid |
端口唯一标识 |
Description |
端口描述信息 |
| 方法 | 说明 |
|---|---|
Send(CanFrame) |
发送CAN帧 |
AddObserver(CanObserverBase) |
添加观察者 |
RemoveObserver(CanObserverBase) |
移除观察者 |
Open() |
打开端口 |
Close() |
关闭端口 |
CanObserver
| 属性 | 说明 |
|---|---|
CanFilter |
帧过滤器 |
OnReceive |
接收事件 |
CanPortManager (单例)
| 属性/方法 | 说明 |
|---|---|
Instance |
单例实例 |
GetPorts() |
获取所有端口列表 |
AddPort(ICanPort) |
添加端口 |
RemovePort(ICanPort) |
移除端口 |
this[string name] |
通过名称获取端口 |
Clear() |
清空所有端口 |
运行测试
# 运行所有测试
dotnet test
# 运行特定测试
dotnet test --filter "FullyQualifiedName~CanFilterTests"
项目结构
Can.Core/
├── src/ # 源码目录
│ ├── Can.Core.csproj # 主项目
│ ├── Models/ # 数据模型
│ │ ├── CanFrame.cs # CAN帧数据结构
│ │ └── CanGuid.cs # 端口唯一标识
│ ├── Filtering/ # 过滤器
│ │ ├── CanFilter.cs # 帧过滤器
│ │ └── ExframeFilterFlag.cs # 帧类型枚举
│ ├── Ports/ # 端口
│ │ ├── ICanPort.cs # CAN端口接口
│ │ ├── CanPortBase.cs # CAN端口基类
│ │ └── CanPortManager.cs # 端口管理器
│ └── Observers/ # 观察者
│ ├── CanObserverBase.cs # 观察者基类
│ └── CanObserver.cs # 观察者实现
├── tests/ # 测试目录
│ └── Can.Core.Tests/ # 单元测试项目
│ ├── Can.Core.Tests.csproj
│ ├── CanFilterTests.cs
│ ├── CanGuidTests.cs
│ ├── CanPortBaseTests.cs
│ └── CanPortManagerTests.cs
├── docs/ # 文档目录
│ └── 需求.md # 需求文档
└── README.md # 使用文档
版本历史
- 1.0.0: 初始版本,从 CanSharp 移植,支持 .NET 8.0/10.0
许可证
MIT License
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net10.0
- No dependencies.
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.0.1 | 84 | 5/11/2026 |