zlgcan.Api
大家好,今天和大家分享自己基于【zlgcan接口函数】进行现代化.net开发风格的高性能代码封装,我也是周立功CAN通讯产品忠实的学生,这里并不是说【zlgcan库】性能不高,而是在与.net应用层代码交互方式这块使用的技术对程序性能可以再进一步的提高,大家都知道像.net,java,go语言都是有垃圾回收机制GC的存在,如果在高频通讯频繁创建对象就会给GC造成较大的压力,在性能极致的环境下代码的运行效果往往会和设计偏差较大,所以这里适合两种开发需求:1.通讯频率较高且对性能有较高需求;2.对【zlgcan库】使用不太了解的,且需要最简单入手使用;所以这里对【zlgcan库】进行了,如下几个方面的性能和使用的优化:
- 使用值类型:因为值类型在线程栈里面非常,效率远高于引用类型。
- 去掉将非托管内存每次重新分配到托管内存块,这里会随每次通讯反复产生内存碎片,长时间高频率通讯对GC压力非常大,改进方法是直接操作内存块,几乎是【0 GC】产生,对性能极高的场景有很重要作用。
- 优化了接收线程回调:不需要每次自己创建线程,在其中写很重复的代码。
- 所有的功能全部都使用一行代码搞定。
下面具体介绍使用方法:
- 在周立功官网下载最新【zlgcan库】,地址:https://manual.zlg.cn/web/#/152?page_id=5332
-
下载后解压放到你程序的目录中,并设置对应运行平台:X64或者X86
- 在VS对应工程里面打开NuGet,搜索【XF.net】下载最新版本即可:
- 俱往矣,下面开始进入使用正题了,所有的功能都是一行代码搞定:
1 internal class Program 2 { 3 static void Main(string[] args) 4 { 5 using (var pcan = new XfZlgCan().Open(new CanConnParam() { CanRate = [500, 500], DataRate = [2000, 2000], IsRecvCanFD = true }, Receive)) //一行代码搞定 6 { 7 var sdata = new MessageModel() { CANChannelNo = 0, ID = 0x601, Data = [0x40, 01, 0x20, 0x01, 0x00, 0x00, 0x00, 0x00], DataLen = 8, ExternFlag = false }; //准备要发送的CAN报文: 8 9 pcan.Send(ref sdata); //假设发送can报文: 10 11 var sFDdata = new MessageModel() { CANChannelNo = 1, ID = 0x1830FF81, Data = [1, 2, 3, 4, 5, 6, 7, 0x88, 0x99, 0x10, 0x11, 0x12], DataLen = 12, ExternFlag = true, CANFD_BRS = true }; //假设要发送FD报文 12 13 pcan.SendFD(ref sFDdata); //假设发送canFD报文: 14 15 16 Console.ReadLine(); 17 } 18 } 19 20 21 /// <summary> 22 /// 接收报文:所有的接收报文CAN/CANFD都会进入 23 /// </summary> 24 /// <param name="msg"></param> 25 static void Receive(ref MessageModel msg) 26 { 27 //这里可以写你自己的接收报文逻辑了... 28 29 Console.WriteLine($"通道号:{msg.CANChannelNo}接收:CANID:{msg.ID:X},报文:{BitConverter.ToString(msg.Data, 0, msg.DataLen)},是否FD:{msg.IsFD},是否FD加速:{msg.CANFD_BRS}"); //打印报文 30 } 31 }
运行效果:
- 连接参数说明:
public class CanConnParam { /// <summary> /// zlg设备类型 /// </summary> public uint DeviceType { get; set; } = ZLGCAN.ZCAN_USBCANFD_200U; /// <summary> /// CAN通讯的波特率,第一个元素值代表通道1的can波特率,第二个就是第二个通道的can波特率 /// </summary> public int[] CanRate { get; set; } = new int[] { 500, 500 }; //这里设置两个通道的仲裁波特率都是500K /// <summary> /// CANFD数据波特率,同理与can波特率设置,需要和can波特率设置的个数相同,如果不是FD设备就设置DataRate=null /// </summary> public int[] DataRate { get; set; } = new int[] { 2000, 2000 }; //这里设置两个通道的canfd数据波特率都是2M /// <summary> /// 通道个数 /// </summary> public byte ChnMax { get; set; } = 2; /// <summary> /// 接收大小缓存区 /// </summary> public uint RecvTempListCount { get; set; } = 10000; /// <summary> /// 是否接收CAN报文 /// </summary> public bool IsRecvCan { get; set; } = true; /// <summary> /// 是否接收CANFD报文 /// </summary> public bool IsRecvCanFD { get; set; } = false; /// <summary> /// 接收等待时间 /// </summary> public int RecvWait_time { get; set; } = 10; }
- 希望能给您在项目中得到一点帮助,那就是我万分的荣幸,谢谢!