当前位置: 首页 > ai >正文

拒绝造轮子(C#篇)ZLG CAN卡驱动封装应用

拒绝造轮子(C#篇)ZLG CAN卡驱动封装应用

今天给大家介绍一个封装完善的CAN卡类。

背景

在面对常规开发场景,开发者对复杂SDK进行封装和测试。阅读相关开发资料和理解SDK的DEMO程序。

开篇

如果你也有同样的烦恼,那就来看看今天跟大家分享的库。

Gycylm.Tools.Devices.Cans.Zlg (获取方法放在文末尾)

该库文件提供一个非常好用的类CanCommService,提供了我们想要访问设备的所有操作,精巧的封装到3个事件、和4个方法中。如下所示:

        /// <summary>/// 当通道断开了,通知外部/// </summary>event Action<ChannelConfig> ChannelDisconned;/// <summary>/// 当数据收到了,通知外部/// </summary>event Action<ICanChannelService, List<UniversalCanMessage>> CanDataComed;/// <summary>/// 当有数据发送出去时,通知外部/// </summary>event Action<ICanChannelService, List<UniversalCanMessage>> CanDataSent;/// <summary>/// 发生数据/// </summary>/// <param name="ccc"></param>/// <param name="protocolId"></param>/// <param name="data"></param>/// <returns></returns>Boolean Send(ChannelConfig ccc, UInt32 protocolId, Byte[] data);/// <summary>/// 打开指定通道/// </summary>/// <param name="ccc">通道配置信息</param>/// <returns></returns>Boolean Open(ChannelConfig ccc);/// <summary>/// 关闭指定 <see cref="ChannelConfig.Id"/> 的通道/// </summary>/// <param name="id">通道配置信息的<see cref="ChannelConfig.Id"/></param>/// <returns></returns>Boolean Close(UInt32 id);/// <summary>/// 关闭所有通道/// </summary>void CloseAll();

该方法是针对所有的基础CAN卡通信的封装,可以通过使用上面的方法实现对CAN设备的基本操作

  • 配置

  • 打开

  • 关闭

  • 数据发送

  • 数据接收

同时支持CAN/CANFD,通道分离,支持ZLG的USB CAN卡设备。

CAN卡配置信息如下

   /// <summary>/// CAN 设备通道配置信息/// </summary>public class ChannelConfig{/// <summary>/// CAN 设备通道唯一 ID/// </summary>public UInt32 Id { get; set; }
​/// <summary>/// CAN 设备类型,具体见 CanCategory 枚举/// </summary>public CanCategory CCategroy { get; set; } = CanCategory.ZLG_USBCAN_2;
​/// <summary>/// CAN 设备索引 0 1 2 3 4 .../// </summary>public Byte CanIndex { get; set; }
​/// <summary>/// 通道索引 0 1 2 3 .../// </summary>public Byte ChannelIndex { get; set; }
​/// <summary>/// 数据协议/// </summary>public DataProtocol DataProto { get; set; } = DataProtocol.CAN;
​/// <summary>/// 通道波特率/// </summary>public ChannelBaudRate BaudRate { get; set; } = ChannelBaudRate._1000Kbps;
​/// <summary>/// 数据波特率/// </summary>public ChannelDataBaudRate DataBaudRate { get; set; } = ChannelDataBaudRate.None;/// <summary>/// 启用终端电阻/// </summary>public ChannelInternalResistance InternalResistance { get; set; } = ChannelInternalResistance.Disable;
​public override string ToString(){return $"Id = {Id};\n" +$"CCategroy = {CCategroy};\n" +$"CanIndex = {CanIndex};\n" +$"ChannelIndex = {ChannelIndex};\n" +$"DataProto = {DataProto};\n" +$"BaudRate = {BaudRate};\n" +$"DataBaudRate = {DataBaudRate};\n" +$"InternalResistance = {InternalResistance}";}}
​

CAN 消息定义如下:

 [StructLayout(LayoutKind.Sequential, Pack = 1)]public struct UniversalCanMessage{/// <summary>/// 报文 ID/// </summary>public UInt32 ID;/// <summary>/// 报文数据内容长度/// 不是DataLengthCode/// 如果需要获得真实的DLC,需要自己再换算<see cref="DataConverter.DataLen2DLC(int)"/>/// </summary>public Byte DLC;/// <summary>/// CAN 通道接收时间戳,相对于 CAN 打开时间,单位微秒/// </summary>public UInt64 TIMESTAMP;/// <summary>/// 报文数据内容,根据 DLC 来判断真实有效数据内容/// </summary>[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]public Byte[] DATA;
​public override string ToString(){var sb = new System.Text.StringBuilder();sb.AppendLine($"ID = 0x{ID:X8}");sb.AppendLine($"DLC = {DLC}");sb.AppendLine($"TIMESTAMP = {TIMESTAMP} us");
​sb.Append("DATA = ");if (DATA != null){for (int i = 0; i < DLC && i < DATA.Length; i++){sb.Append($"{DATA[i]:X2} ");}}else{sb.Append("null");}
​return sb.ToString().TrimEnd();}}
​

Gycylm.Tools.Devices.Cans.Zlg 该库只针对ZLG USBCAN进行了封装,其中还有其他库实现了Vector、PCAN、GCAN...等常见CAN的封装适配。

笔者对CAN通信上位机开发略有经验,欢迎交流。

整理不易,如有需要,联系 mefdeamon@qq.com 获取

结束


积跬步以至千里:) (:一阵没来由的风

http://www.xdnf.cn/news/17919.html

相关文章:

  • 贺雨禾《梨花往事》北京首映,“野草型演员”深耕走出新赛道
  • 第4问 常见的指标有哪些?
  • 【CVPR2025】计算机视觉|GIFNet:一个模型实现所有图像融合任务!还能增强画质?!
  • [1Prompt1Story] 滑动窗口机制 | 图像生成管线 | VAE变分自编码器 | UNet去噪神经网络
  • 【Qt开发】常用控件(四)
  • 《深度解构:构建浏览器端Redis控制台的WebSocket协议核心技术》
  • 开源 Arkts 鸿蒙应用 开发(十八)通讯--Ble低功耗蓝牙服务器
  • Flink Stream API 源码走读 - window 和 sum
  • 前端开发入门书籍推荐:Vue.js 3与前端基础的完美组合
  • 九尾狐未来机械锂晶核
  • 数据结构:满二叉树 (Full Binary Tree) 和 完全二叉树 (Complete Binary Tree)
  • Three.js三大组件:场景(Scene)、相机(Camera)、渲染器(Renderer)
  • tree组件(几种不同分叉树Vue3)
  • 免费万能电子书格式转换器!Neat Converter支持 ePub、Azw3、Mobi、Doc、PDF、TXT 文件的相互转换。
  • 【图像算法 - 15】智能行李识别新高度:基于YOLO12实例分割与OpenCV的精准检测(附完整代码)
  • React手撕组件和Hooks总结
  • springboot项目单独对数据源配置加解密
  • 编程基础之字符串——过滤多余的空格
  • B3844 [GESP样题 二级] 画正方形
  • CPP多线程2:多线程竞争与死锁问题
  • 复合机器人食品分拣生产线:一体化控制系统引领高效柔性新食代
  • 硬核北京 | 2025世界机器人大会“破圈”,工业智能、康养科技…… 亦庄上演“机器人总动员”
  • Java 多线程教程
  • 心路历程-三个了解敲开linux的大门
  • 第三十七天(js前端数据加密和混淆)
  • 设计模式之静态代理
  • 拒绝造轮子(C#篇)使用SqlSugar实现数据库的访问
  • KingbaseES高可用架构深度解析——从读写分离到异地灾备的全方位守护
  • Vue2.x核心技术与实战(一)
  • Flutter InheritedWidget 详解:从生命周期到数据流动的完整解析