C#简单访问CANcaseXL,使用CANcaseXL收发报文

CANcaseXL是Vector的usb CAN适配器,其配套的软件CANoe是个非常强大的软件……

CANoe的介绍改天再说,今天演示一下如何在winform中使用CANcaseXL收发报文

首先得感谢Vector提供的详细文档XL Driver Libary - Description.pdf(此文件在安装盘\Drivers\XL Driver Libary\doc中)

还需要一些dll,如vxlapi_NET20.dll(此文件在安装盘\Drivers\XL Driver Libary\bin中)

当然了,里面还有很多demo可以参考有C++和C#的

1.首先参考文档给出的流程图,文档有介绍函数的作用和参数列表,这里面是C++版本的,和C#版略有不同




2.废话不多说,然后贴代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using vxlapi_NET20;

namespace Bootloader
{
    class DeviceCANcaseXL : ICANDevice
    {
        // variables needed by XLDriver
        private static uint hwType = (uint)XLClass.XLhwTypes.XL_HWTYPE_CANCASEXL;
        private static uint hwIndex = 0;
        private static uint hwChannel = 0;
        private static uint busType = (uint)XLClass.XLbusTypes.XL_BUS_TYPE_CAN;
        private static uint flags = 0;
        private static int portHandle = -1;
        private static int eventHandle = -1;
        private static UInt64 accessMask = 0;
        private static UInt64 permissionMask = 0;
        private static UInt64 txMask = 0;
        private static uint appChannel = 0;
        private const string applicationName = "Bootloader";
        private static int channelIndex = 0;

        public XLDriver xd;
        private UInt32 responseID;
        bool ICANDevice.initDevice(int baudRate, UInt32 responseID)
        {
            XLClass.XLstatus status;
            xd = new XLDriver();
            this.responseID = responseID;
            /* init driver */
            status = xd.XL_OpenDriver();
            status = xd.XL_SetApplConfig(applicationName, appChannel, hwType, hwIndex, hwChannel, busType);
            accessMask = xd.XL_GetChannelMask((int)hwType, (int)hwIndex, (int)hwChannel);
            permissionMask = accessMask;//必要的
            status = xd.XL_OpenPort(ref portHandle, applicationName, accessMask, ref permissionMask, 1024, busType);
            /* setup channels */
            if (status == XLClass.XLstatus.XL_SUCCESS)
            {
                status = xd.XL_CanSetChannelBitrate(portHandle, accessMask, (uint)(baudRate * 1000));

                status = xd.XL_CanSetChannelOutput(portHandle, accessMask, (byte)XLClass.XLoutputModes.XL_OUTPUT_MODE_NORMAL);

                status = xd.XL_CanSetChannelAcceptance(portHandle, accessMask, responseID, 0x7FF, XLClass.XLacceptanceFilter.XL_CAN_STD);

                status = xd.XL_CanSetReceiveMode(portHandle, 0, 0);

                status = xd.XL_SetNotification(portHandle, ref eventHandle, 1);

                status = xd.XL_ActivateChannel(portHandle, accessMask, busType, flags);
                /* on bus */
                xd.XL_ResetClock(portHandle);

                xd.XL_FlushReceiveQueue(portHandle);
                xd.XL_CanFlushTransmitQueue(portHandle, accessMask);
                return true;
            }
            else
                return false;        
        }

        bool ICANDevice.closeDevice()
        {
            if (
                (xd.XL_DeactivateChannel(portHandle, accessMask) == XLClass.XLstatus.XL_SUCCESS)
             && (xd.XL_ClosePort(portHandle) == XLClass.XLstatus.XL_SUCCESS)
             && (xd.XL_CloseDriver() == XLClass.XLstatus.XL_SUCCESS)
                )
                return true;
            else
                return false;
        }

        bool ICANDevice.sendData(CAN_DATA cd)
        {
            XLClass.xl_event xlEvent = new XLClass.xl_event();
            xlEvent.tag = 0x0A;//必要的
            xlEvent.tagData.can_Msg.id = cd.ID;
            xlEvent.tagData.can_Msg.dlc = (ushort)cd.DLC;
            for (int i = 0; i < cd.DLC; i++)
                xlEvent.tagData.can_Msg.data[i] = cd.Data[i];
            XLClass.XLstatus status = xd.XL_CanTransmit(portHandle, accessMask, xlEvent);

            return (bool)(status == XLClass.XLstatus.XL_SUCCESS);
        }

        int ICANDevice.receiveData(ref CAN_DATA[] cdBuffer)
        {
            int count = 0;
            XLClass.XLstatus status; 
            XLClass.xl_event xlEvent = new XLClass.xl_event();
            status = xd.XL_Receive(portHandle, ref xlEvent);
            while (status == XLClass.XLstatus.XL_SUCCESS && count < 100)
            {
                if (xlEvent.tagData.can_Msg.dlc > 0 && responseID == xlEvent.tagData.can_Msg.id)
                {
                    cdBuffer[count].DLC = xlEvent.tagData.can_Msg.dlc;
                    cdBuffer[count].ID = xlEvent.tagData.can_Msg.id;
                    cdBuffer[count].channel = 0;
                    cdBuffer[count].isExtendFlag = false;
                    cdBuffer[count].isRemtoeFlag = false;
                    cdBuffer[count].isRx = true;
                    cdBuffer[count].Time = DateTime.Now.Ticks;
                    cdBuffer[count].Data = new byte[8];
                    for (int i = 0; i < cdBuffer[count].DLC; i++)
                    {
                        cdBuffer[count].Data[i] = xlEvent.tagData.can_Msg.data[i];
                    }
                    count++;
                }

                status = xd.XL_Receive(portHandle, ref xlEvent);
            }

            return count;
        }
    }
}
其中用到的结构体

public struct CAN_DATA
    {
        public UInt32 ID;
        public int DLC;
        public byte[] Data;
        public long Time;
        public bool isRemtoeFlag;
        public bool isExtendFlag;
        public byte channel;
        public bool isRx;
    }
使用的接口

namespace Bootloader
{
    interface ICANDevice
    {
        bool initDevice(int baudRate, UInt32 responseID);
        bool closeDevice();
        bool sendData(CAN_DATA cd);
        int receiveData(ref CAN_DATA[] cdBuffer);
    }
}

当然了,工程中必须添加对vxlapi_NET20的静态引用

需要注意的是:

1.文档注释必要的有两处,这两句必不可少

2.每次发送的是数据都会出现在接收的队列中,以获得时间戳,因此要注意接收数据的区分

  • 4
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
使用C#组建Modbus RTU协议的报文,你可以按照以下步骤进行操作: 1. 首先,你需要使用C#中的串口通信功能来与Modbus设备进行通信。你可以使用SerialPort类来实现这一功能。在你的代码中,需要引入System.IO.Ports命名空间。 2. 创建一个SerialPort对象,并设置串口通信的相关参数,例如波特率、数据位、停止位和校验位等。例如: ```csharp SerialPort serialPort = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One); serialPort.Open(); ``` 请根据你的实际情况修改串口号、波特率等参数。 3. 组建Modbus RTU协议的报文。Modbus RTU协议的报文由多个字节组成,包括设备地址、功能码、数据和校验等。根据Modbus协议规范,你可以使用字节数组来表示报文。 4. 通过串口发送报文使用SerialPort对象的Write方法将报文发送到Modbus设备。例如: ```csharp byte[] message = new byte[]{ 0x01, 0x03, 0x00, 0x00, 0x00, 0x0A, 0xC5, 0xCD }; serialPort.Write(message, 0, message.Length); ``` 在这个例子中,我们发送了一个读取保持寄存器的功能码为3的请求。 5. 接收Modbus设备的响应。使用SerialPort对象的Read方法从串口接收Modbus设备的响应。你可以根据Modbus协议规范解析接收到的字节数据。 ```csharp byte[] buffer = new byte[serialPort.BytesToRead]; serialPort.Read(buffer, 0, buffer.Length); ``` 在这个例子中,我们将接收到的字节数据存储在名为buffer的字节数组中。 6. 最后,记得关闭串口连接。 ```csharp serialPort.Close(); ``` 这就是使用C#组建Modbus RTU协议报文的基本步骤。当然,具体的实现还取决于你需要实现的Modbus功能和设备。你可能需要参考Modbus协议规范来了解更多细节,并根据具体情况进行适当的调整和处理。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值