拒绝造轮子(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 获取

结束


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

相关推荐
民乐团扒谱机7 小时前
【微实验】基于Python实现的实时键盘鼠标触控板拾取检测(VS2019,附完整代码)
python·c#·计算机外设
CreasyChan7 小时前
Unity中C#状态模式详解
unity·c#·状态模式
工程师0077 小时前
线程同步的意义
c#·锁机制·线程同步
yugi9878387 小时前
基于C#实现的WiFi信号强度扫描程序
开发语言·c#
sali-tec8 小时前
C# 基于halcon的视觉工作流-章70 深度学习-Deep OCR
开发语言·人工智能·深度学习·算法·计算机视觉·c#·ocr
武藤一雄8 小时前
C#中常见集合都有哪些?
开发语言·微软·c#·.net·.netcore
唐青枫8 小时前
C#.NET struct 全解析:什么时候该用值类型?
c#·.net
kaikaile199517 小时前
基于C#实现一维码和二维码打印程序
开发语言·c#
我不是程序猿儿18 小时前
【C#】画图控件的FormsPlot中的Refresh功能调用消耗时间不一致缘由
开发语言·c#
rit843249918 小时前
C# Socket 聊天室(含文件传输)
服务器·开发语言·c#