C#编写CAN上位机与仪器通讯

C#编写CAN上位机与仪器通讯

1.前期准备

  1. 安装配置好winform环境

  2. 在文章结尾下载整理好的所需文件

  3. 将ControlCAN.dll文件放入项目的bin/Debug文件夹下

  4. 如果之后执行失败,就还需将kerneldlls文件夹也放入bin/Debug文件夹下

  5. 引用导入的ControlCAN.dll(右键项目引用->添加引用->浏览 然后找到dll文件导入)
    请添加图片描述

  6. 将封装好的controlCAN.cs和ConnectCAN.cs拖入项目中(具体写法也可以参考二次开发说明书以及以下教程自行编写)

  7. 准备完成

2.编写讲解

  1. can通讯需要创建四个变量
  • devtype选择can设备类型

  • devind选择can设备索引(用于插入多个can卡后的选择)

  • canind选择can通道(单个can卡一般具有两个通道)

  • DataReceiveBuffer存放can总线上读取的数据

private UInt32 devtype;//设备类型
private UInt32 devind;//CAN设备索引
private UInt32 canind;//CAN通道索引
public Int32[] DataReceiveBuffer = new Int32[100];//存放数据
  1. 打开can的驱动程序,配置波特率等信息,打开can端口

打开can驱动函数:

controlCAN.VCI_OpenDevice(this.devtype, this.devind, 0)

  • 参数为上面定义的参数,0为默认值

配置can信息:

controlCAN.VCI_InitCAN(devtype, devind, canind, ref config)

  • 参数四为配置的结构体VCI_INIT_CONFIG,内包含可配置的波特率等信息

启动can函数:

controlCAN.VCI_StartCAN(devtype, devind, canind)

  • 参数为上面定义的参数
    public bool CANConnect(string[] canConfig)
    {
        try
        {
            //连接CAN
            if (controlCAN.VCI_OpenDevice(this.devtype, this.devind, 0) == 0)
            {
                throw new Exception("");
            }

            //初始化CAN通讯
            VCI_INIT_CONFIG config = new VCI_INIT_CONFIG();
            config.AccCode = System.Convert.ToUInt32(canConfig[0], 16);
            config.AccMask = System.Convert.ToUInt32(canConfig[1], 16);
            config.Timing0 = System.Convert.ToByte(canConfig[2], 16);
            config.Timing1 = System.Convert.ToByte(canConfig[3], 16);
            config.Filter = 1;
            config.Mode = 0;
            controlCAN.VCI_InitCAN(devtype, devind, canind, ref config);

            controlCAN.VCI_StartCAN(devtype, devind, canind);//启动CAN
        }
        catch
        {
            MessageBox.Show("测试模块连接失败!");
            return false;
        }
        return true;
    }

  1. 发送can命令

主要用到can发送函数

controlCAN.VCI_Transmit(devtype, devind, 0, ref Send_Data, 1)

  • 参数四位需要发送的数据为VCI_CAN_OBJ结构体,可配置报文和数据 ,其余默认
 unsafe public void CANSend(uint ID, string strdata)
 {
     VCI_CAN_OBJ Send_Data = new VCI_CAN_OBJ();
     Send_Data.SendType = 0x1;//正常发送
     Send_Data.RemoteFlag = 0x0;//数据帧设置
     Send_Data.ExternFlag = 0x1;//扩展帧设置

     //去除掉报文和数据中的空格
     Send_Data.ID = Convert.ToUInt32(ID.ToString().Replace(" ", ""));
     strdata = strdata.Replace(" ", "");

     Send_Data.DataLen = Convert.ToByte(strdata.Length / 2);
     byte len = Convert.ToByte(strdata.Length / 2);

     int i = -1;
     if (i++ < len - 1)
         Send_Data.Data[0] = System.Convert.ToByte("0x" + strdata.Substring(i * 2, 2), 16);
     if (i++ < len - 1)
         Send_Data.Data[1] = System.Convert.ToByte("0x" + strdata.Substring(i * 2, 2), 16);
     if (i++ < len - 1)
         Send_Data.Data[2] = System.Convert.ToByte("0x" + strdata.Substring(i * 2, 2), 16);
     if (i++ < len - 1)
         Send_Data.Data[3] = System.Convert.ToByte("0x" + strdata.Substring(i * 2, 2), 16);
     if (i++ < len - 1)
         Send_Data.Data[4] = System.Convert.ToByte("0x" + strdata.Substring(i * 2, 2), 16);
     if (i++ < len - 1)
         Send_Data.Data[5] = System.Convert.ToByte("0x" + strdata.Substring(i * 2, 2), 16);
     if (i++ < len - 1)
         Send_Data.Data[6] = System.Convert.ToByte("0x" + strdata.Substring(i * 2, 2), 16);
     if (i++ < len - 1)
         Send_Data.Data[7] = System.Convert.ToByte("0x" + strdata.Substring(i * 2, 2), 16);

     if (controlCAN.VCI_Transmit(devtype, devind, 0, ref Send_Data, 1) == 0)
     {
         MessageBox.Show("发送失败", "错误",
                 MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
     }
 }

4.can接受数据

主要用到获取can数据数量函数

controlCAN.VCI_GetReceiveNum(devtype, devind, canind);

can数据接收函数

controlCAN.VCI_Receive(devtype, devind, timer_canind, pt, 50, 100)

参数4为一个存放数据的指针

unsafe public void CANRec()
{
    UInt32 timer_canind = canind;
    UInt32 res = new UInt32();//存放返回值
    res = controlCAN.VCI_GetReceiveNum(devtype, devind, timer_canind);
    if (res == 0) return;

    IntPtr pt = Marshal.AllocHGlobal(
        Marshal.SizeOf(typeof(VCI_CAN_OBJ)) * (Int32)50
        );//分配一个能存放50can消息的内存

    res = controlCAN.VCI_Receive(devtype, devind, timer_canind, pt, 50, 100);//接收数据

    for (UInt32 i = 0; i < res; i++)
    {
        VCI_CAN_OBJ obj = (VCI_CAN_OBJ)Marshal.PtrToStructure(
            (IntPtr)((UInt32)pt + i * Marshal.SizeOf(typeof(VCI_CAN_OBJ))),
            typeof(VCI_CAN_OBJ));//读取ptr内存中获取到的数据

        DataReceiveBuffer[0] = (Int32)(obj.ID);

        if (obj.RemoteFlag == 0)
        {
            byte len = (byte)(obj.DataLen % 9);
            for (byte j = 0; j < len; j++)
            {
                DataReceiveBuffer[j + 1] = obj.Data[j];
            }
        }
    }
    Marshal.FreeHGlobal(pt);
}

上述需要的所有文件的下载链接:链接已失效,之后会在同地址上传GPIB、RS232的资料以及上位机示例软件

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>