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的资料以及上位机示例软件,有问题可以随时发微信咨询

相关推荐

  1. EPSON机器人PC软件C#网络TCP通讯

    2024-07-15 10:20:02       48 阅读
  2. C11编写简易16虚拟

    2024-07-15 10:20:02       64 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-15 10:20:02       70 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-15 10:20:02       74 阅读
  3. 在Django里面运行非项目文件

    2024-07-15 10:20:02       62 阅读
  4. Python语言-面向对象

    2024-07-15 10:20:02       72 阅读

热门阅读

  1. 聊聊自动驾驶中的LiDAR和Radar

    2024-07-15 10:20:02       20 阅读
  2. python安全脚本开发简单思路

    2024-07-15 10:20:02       26 阅读
  3. 使用C++和libcurl下载指定的文件

    2024-07-15 10:20:02       26 阅读
  4. 微信小程序开发入门指南

    2024-07-15 10:20:02       21 阅读
  5. 等保测评全流程详解

    2024-07-15 10:20:02       20 阅读
  6. Writing Bazel rules: data and runfiles

    2024-07-15 10:20:02       21 阅读