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

智能热心网友 2024-08-29 10:35:24 阅读 54

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

1.前期准备

安装配置好winform环境

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

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

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

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

请添加图片描述

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

准备完成

2.编写讲解

can通讯需要创建四个变量

<code>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];//存放数据

打开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;

}

发送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的资料以及上位机示例软件



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。