当前位置:文档之家› C#使用can控制器局域网络协议的通用方法

C#使用can控制器局域网络协议的通用方法

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WindowsCan
{
///


/// 该结构体包含ZLGCAN系列接口卡的设备信息。该结构体将在VCI_ReadBoardInfo函数中被填充。
///

public struct VCI_BOARD_INFO
{
public UInt16 hw_Version;
public UInt16 fw_Version;
public UInt16 dr_Version;
public UInt16 in_Version;
public UInt16 irq_Num;
public byte can_Num;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public byte[] str_Serial_Num;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
public byte[] str_hw_Type;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] Reserved;
}

///
///定义CAN信息帧的数据类型。 结构体在VCI_Transmit和VCI_Receive函数中被用来填充CAN信息帧
///

public struct VCI_CAN_OBJ
{
public Int32 ID;
public UInt32 TimeStamp;
public byte TimeFlag;
public byte SendType;
public byte RemoteFlag;//是否是远程帧
public byte ExternFlag;//是否是扩展帧
public byte DataLen;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] Data;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] Reserved;

public void Init()
{
Data = new byte[8];
Reserved = new byte[3];
}
}

///
/// 定义CAN控制器状态的数据类型。结构体包含CAN控制器状态信息。结构体将在VCI_ReadCanStatus函数中被填充
///

public struct VCI_CAN_STATUS
{
public byte ErrInterrupt;
public byte regMode;
public byte regStatus;
public byte regALCapture;
public byte regECCapture;
public byte regEWLimit;
public byte regRECounter;
public byte regTECounter;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] Reserved;
}

///
/// 定义错误信息的数据类型。
///

public struct VCI_ERR_INFO
{
public UInt32 ErrCode;
public byte Passive_ErrData1;
public byte Passive_ErrData2;
public byte Passive_ErrData3;
public byte ArLost_ErrData;
}

///
/// 定义初始化CAN的数据类型
///

public struct VCI_INIT_CONFIG
{
public UInt32 AccCode;
public UInt32 AccMask;
public UInt32 Reserved;
public byte Filter;
public byte Timing0;
public byte Timing1;
public byte Mode;
}
///
/// CHGDESIPANDPORT结构体用于装载更改CANET-E的目标IP和

端口的必要信息。此结构体在CANETE-E中使用
///


public struct CHGDESIPANDPORT
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
public byte[] szpwd;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public byte[] szdesip;
public Int32 desport;
}
///
/// 创建人员:苏洋洋
/// 功能描述:CAN接口通讯类
/// 创建日期:2010-7-9
///

public class CanHelperCls
{
public static int identity = 0;

///
/// 表示当前设备是否连接状态0为关闭状态
///

public static int m_connect = 0;
///
/// 设备类型号
///

public static uint m_devtype = 3;
///
/// 设备索引号
///

public static uint m_devind = 0;
///
/// can口ID
///

public static uint m_canid = 0;
///
/// 返回字符串
///

public static string strreceive;
///
/// 发送方式
///

public static int sendtype;
///
/// 一个装有发送的协议指令的信息控件(ID)
///

public static ListBox lbosr;

public static uint time = 0;
public static uint motorid;
public static string orderservice = "";
///
/// 接受一个字符串返回一个2位的字符不够了补0
///

/// 2位字符
/// 补齐2位
private static string FortwoString(string s)
{
if (s.Length < 2)
{
s = "0" + s;
}
return s;
}

///
/// 获取缓冲区尚未读取到的帧数
///

///
public uint GetReceiveNum()
{
return VCI_GetReceiveNum(m_devtype, m_devind, m_canid);
}

//public int getorder()
//{

//}
///
/// 接收指令返回
///

///
/// 发送时id的长度
///
/// 返回标示
public uint getMessage(int order,int idlenght,IList idss)
{
VCI_CAN_OBJ[] m_recobj = new VCI_CAN_OBJ[50];
UInt32 res = new UInt32();
m_recobj[0].Data = new Byte[8];
res = VCI_Receive(m_devtype, m_devind, m_canid, ref m_recobj[0], 1, 0);//超时时间为1秒
String str = "";
if (res == 1)//c

an执行成功
{
if (m_recobj[0].RemoteFlag == 0)
{
byte lens = (byte)(m_recobj[0].DataLen % 9);
byte ji = 0;
if (ji++ < lens)
//string.Format("{0:D2}", System.Convert.ToString(m_recobj[0].Data[0], 16))
str += "" + FortwoString(System.Convert.ToString(m_recobj[0].Data[0], 16));
if (ji++ < lens)
str += "" + FortwoString(System.Convert.ToString(m_recobj[0].Data[1], 16));
if (ji++ < lens)
str += "" + FortwoString(System.Convert.ToString(m_recobj[0].Data[2], 16));
if (ji++ < lens)
str += "" + FortwoString(System.Convert.ToString(m_recobj[0].Data[3], 16));
if (ji++ < lens)
str += "" + FortwoString(System.Convert.ToString(m_recobj[0].Data[4], 16));
if (ji++ < lens)
str += "" + FortwoString(System.Convert.ToString(m_recobj[0].Data[5], 16));
if (ji++ < lens)
str += "" + FortwoString(System.Convert.ToString(m_recobj[0].Data[6], 16));
if (ji++ < lens)
str += "" + FortwoString(System.Convert.ToString(m_recobj[0].Data[7], 16));
string mms = string.Format("{0:D2}", System.Convert.ToString(m_recobj[0].Data[0], 16));
strreceive = str;
//if ((strreceive == "0201000000000000") || (strreceive == "0200000000000000"))
//{
// ActionparameterCls.flag = true;
//}
//else
//{
// ActionparameterCls.flag = false;
//}

if (str.Trim() != "")
{
bool idnetity_bol = false;
foreach (string var in idss)
{
if (var == Convert.ToString(m_recobj[0].ID, 16).ToUpper())
{
idnetity_bol = true;
}
}
if (idnetity_bol)
{
if (!(Convert.ToInt32(str.Substring(0, 2)) > 0))
{
MessageBox.Show("当前收到的指令:" + str.ToString());
if (order == 1)
{
string ids = Convert.ToString(m_recobj[0].ID, 16);
lbosr.Items.Add("返回结果错误" + str + "," + "ID是" + ids);
throw new Exception("返回结果错误" + str + "," +

"ID是" + ids);
}
else
{
int ids = int.Parse(m_recobj[0].ID.ToString());
lbosr.Items.Add("返回结果错误" + str + "," + "ID是" + ids);
throw new Exception("返回结果错误" + str + "," + "ID是" + ids);
}
res = (uint)0;
}
else
{
if (order == 1)
{
string ids = Convert.ToString(m_recobj[0].ID, 16);
lbosr.Items.Add("返回" + str + "," + "ID是" + ids);
}
else
{
int ids = int.Parse(m_recobj[0].ID.ToString());
lbosr.Items.Add("返回" + str + "," + "ID是" + ids);
}
res = (uint)1;
}
}
else
{
string ids = Convert.ToString(m_recobj[0].ID, 16);
lbosr.Items.Add("返回" + str + "," + "ID是" + ids);
res = (uint)0;
}
}
else
{
res = 0;
if (order ==1)
{
string ids = Convert.ToString(m_recobj[0].ID, 16);
lbosr.Items.Add("返回" + str + "," + "ID是" + ids);
}
else
{
int ids = int.Parse(m_recobj[0].ID.ToString());
lbosr.Items.Add("返回" + str + "," + "ID是" + ids);
}

throw new Exception("指令返回为空");
}


}
}
return res;
}

///


/// 此函数用以清空指定缓冲区。
///

public static void ClearBuffer()
{
VCI_ClearBuffer(m_devtype, m_devind, m_canid);
}
///
/// 发送指令
///

/// 指令对象
/// 发送类型
/// 指令的id(10进制)
/// 添加当前收发指令状态的list控件
/// 指令信息

param>
/// 表示是否为扩展帧
/// 发送标示

public uint sendMessage(string order, string id, ListBox listbox, int iden)
{
VCI_CAN_OBJ vio = new VCI_CAN_OBJ();
vio.SendType = (byte)sendtype;
string[] ids = id.Split(':');
if (ids[0] == "16进制")
{
Int32 idnew = Convert.ToInt32(ids[1], 16);
vio.ID = idnew;
}
else
{
vio.ID = Convert.ToInt32(ids[1]);
}


vio.DataLen = (byte)8;
vio.ExternFlag = (byte)iden;
vio.RemoteFlag = (byte)0;
//VCI_ClearBuffer(m_devtype, m_devind, m_canid);

vio.Init();

int len = (order.Length + 1) / 2;
String strdata = order;
int i = -1;
if (i++ < len - 1)

vio.Data[0] = System.Convert.ToByte("0x" + strdata.Substring(i * 2, 2), 16);
if (i++ < len - 1)
vio.Data[1] = System.Convert.ToByte("0x" + strdata.Substring(i * 2, 2), 16);
if (i++ < len - 1)
vio.Data[2] = System.Convert.ToByte("0x" + strdata.Substring(i * 2, 2), 16);
if (i++ < len - 1)
vio.Data[3] = System.Convert.ToByte("0x" + strdata.Substring(i * 2, 2), 16);
if (i++ < len - 1)
vio.Data[4] = System.Convert.ToByte("0x" + strdata.Substring(i * 2, 2), 16);
if (i++ < len - 1)
vio.Data[5] = System.Convert.ToByte("0x" + strdata.Substring(i * 2, 2), 16);
if (i++ < len - 1)
vio.Data[6] = System.Convert.ToByte("0x" + strdata.Substring(i * 2, 2), 16);
if (i++ < len - 1)
vio.Data[7] = System.Convert.ToByte("0x" + strdata.Substring(i * 2, 2), 16);
uint smap = VCI_Transmit(m_devtype, m_devind, m_canid, ref vio, (uint)1);

if (smap < 1)
{
MessageBox.Show(order + "发送失败", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
listbox.Items.Add("发送失败" + order + ",ID是" + id);
// throw new Exception(order + "发送失败");
}
else
{
listbox.Items.Add("发送" + order + ",ID是" + id);
}


return smap;

}
///


/// 关闭连接
///

public static int closeconn()
{
int result = 0;
if (m_connect == 1)
{

result = (int)VCI_CloseDevice(m_devtype, m_devind);//调用DLL
m_connect = 0;
System.Windows.Forms.MessageBox.Show("断开成功");
}
return result;
}
///

mmary>
/// 连接Can总线(125kbps) 检查当前CAN设备是否连接 并且开启CAN 返回开启CAN的状态 1为开启成功 0为开启失败
///
/// 连接标示
public static int OpenDeviceAndStart()
{
string timing0 = "03";
string timing1 = "1C";
if (m_connect == 1)
{

VCI_CloseDevice(m_devtype, m_devind);//调用DLL 关闭CAN
m_connect = 0;//设置该变量为0
System.Windows.Forms.MessageBox.Show("断开成功");
return m_connect;
}
VCI_INIT_CONFIG InitConfig = new VCI_INIT_CONFIG();//定义CAN初始化配置结构
InitConfig.AccCode = System.Convert.ToUInt32("0x00000000", 16);
InitConfig.AccMask = System.Convert.ToUInt32("0xFFFFFFFF", 16);
InitConfig.Filter = 1;//设定滤波
InitConfig.Mode = 0;//
InitConfig.Timing0 = System.Convert.ToByte("0x" + timing0, 16);//设定定时器1
InitConfig.Timing1 = System.Convert.ToByte("0x" + timing1, 16);//设定定时器2
if (VCI_OpenDevice(m_devtype, m_devind, 0) != 1)//reserverd
{
uint i = VCI_OpenDevice(m_devtype, m_devind, 9600);
System.Windows.Forms.MessageBox.Show("连接失败");

return m_connect;
}
if (VCI_InitCAN(m_devtype, m_devind, m_canid, ref InitConfig) == 1)//canid此函数用以初始化指定的CAN。
{

if (VCI_StartCAN(m_devtype, m_devind, m_canid) == 1)//canid此函数用以启动CAN。
{
m_connect = 1;
System.Windows.Forms.MessageBox.Show("连接成功");
}
}
else
{
System.Windows.Forms.MessageBox.Show("连接失败");
}
return m_connect;
}
#region CAN函数的定义
///


/// 此函数用以打开设备。 为1表示操作成功,0表示操作失败。
///

/// 设备类型
/// 设备索引
/// 当设备为CAN232时,此参数表示为用以打开串口的波特率,可以为2400,4800,9600,14400,19200,28800,57600。当设备为CANETE-E时,
/// 此参数表示要打开的本地端口号,建议在5000到40000范围内取值。当为其他设备时此参数无意义。
/// 为1表示操作成功,0表示操作失败。
[DllImport("controlcan.dll")]
static extern UInt32 VCI_OpenDevice(UInt32 DeviceType, UInt32 DeviceInd, UInt32 Reserved);
///
/// 此函数用以关闭设备。返回为1表示操作成功,0表示

操作失败。
///


/// 设备类型
/// 设备索引
/// 为1表示操作成功,0表示操作失败。
[DllImport("controlcan.dll")]
static extern UInt32 VCI_CloseDevice(UInt32 DeviceType, UInt32 DeviceInd);
///
/// 此函数用以初始化指定的CAN。返回为1表示操作成功,0表示操作失败。(注:在CANET-E中无此函数)
///

/// 设备类型
/// 设备索引
/// 第几路can
/// 初始化VCI_INIT_CONFIG参数结构
/// 为1表示操作成功,0表示操作失败。(注:在CANET-E中无此函数)
[DllImport("controlcan.dll")]
static extern UInt32 VCI_InitCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_INIT_CONFIG pInitConfig);
///
/// 此函数用以获取设备信息 返回 为1表示操作成功,0表示操作失败。(注:在CANET-E中无此函数)
///

/// 设备类型
/// 设备索引
/// 用来存储设备信息的VCI_BOARD_INFO结构指针
///
[DllImport("controlcan.dll")]
static extern UInt32 VCI_ReadBoardInfo(UInt32 DeviceType, UInt32 DeviceInd, ref VCI_BOARD_INFO pInfo);

///
/// 此函数用以获取最后一次错误信息。 为1表示操作成功,0表示操作失败
///

/// 设备类型
/// 设备索引
/// 第几路can
/// 用来存储错误信息的VCI_ERR_INFO结构指针
///
[DllImport("controlcan.dll")]
static extern UInt32 VCI_ReadErrInfo(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_ERR_INFO pErrInfo);
///
/// 此函数用以获取CAN状态 返回为1表示操作成功,0表示操作失败。(注:在CANET-E中无此函数)
///

/// 设备类型
/// 设备索引
/// 第几路can
/// 用来存储CAN状态的VCI_CAN_STATUS结构指针。
/// 为1表示操作成功,0表示操作失败。(注:在CANET-E中无此函数)
[DllImport("controlcan.dll")]
static extern UInt32 VCI_ReadCANStatus(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANIn

d, ref VCI_CAN_STATUS pCANStatus);
///


/// 此函数用以获取设备的相应参数 返回为1表示操作成功,0表示操作失败。
///

/// 设备类型
/// 设备索引
/// 第几路can
/// 参数类型。
/// 用来存储参数有关数据缓冲区地址首指针。
///
[DllImport("controlcan.dll")]
static extern UInt32 VCI_GetReference(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, UInt32 RefType, ref byte pData);
///
/// 此函数用以设置设备的相应参数,主要处理不同设备的特定操作。为1表示操作成功,0表示操作失败。
///

/// 设备类型
/// 设备索引
/// 第几路can
/// 参数类型。
/// 用来存储参数有关数据缓冲区地址首指针。
///
[DllImport("controlcan.dll")]
static extern UInt32 VCI_SetReference(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, UInt32 RefType, ref byte pData);
///
/// 此函数用以获取指定接收缓冲区中接收到但尚未被读取的帧数 返回尚未被读取的帧数
///

/// 设备类型
/// 设备索引
/// 第几路can
///
[DllImport("controlcan.dll")]
static extern UInt32 VCI_GetReceiveNum(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
///
/// 此函数用以清空指定缓冲区。返回为1表示操作成功,0表示操作失败。
///

/// 设备类型
/// 设备索引
/// 第几路can
/// 为1表示操作成功,0表示操作失败。
[DllImport("controlcan.dll")]
static extern UInt32 VCI_ClearBuffer(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);

///
/// 此函数用以启动CAN 返回为1表示操作成功,0表示操作失败。(注:在CANET-E中无此函数)
///

/// 设备类型
/// 设备索引
/// 第几路can
/// 返回为1表示操作成功,0表示操作失败。(注:在CANET-E中无此函数)
[

DllImport("controlcan.dll")]
static extern UInt32 VCI_StartCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
///


/// 此函数用以复位CAN。为1表示操作成功,0表示操作失败。(注:在CANET-E中无此函数)
///

/// 设备类型号。
/// 设备索引
/// 第几路can
/// 为1表示操作成功,0表示操作失败。(注:在CANET-E中无此函数)
[DllImport("controlcan.dll")]
static extern UInt32 VCI_ResetCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd);
///
/// 返回实际发送的帧数
///

/// 设备类型号
/// 设备索引
/// 第几路CAN
/// 要发送的数据帧数组的首指针
/// 要发送的数据帧数组的长度。
/// 返回实际发送的帧数。
[DllImport("controlcan.dll")]
static extern UInt32 VCI_Transmit(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pSend, UInt32 Len);
///
/// 此函数从指定的设备读取数据。 返回实际读取到的帧数。如果返回值为0xFFFFFFFF,则表示读取数据失败,有错误发生,请调用VCI_ReadErrInfo函数来获取错误码
///

/// 设备类型
/// 设备索引
/// 第几路CAN
/// 用来接收的数据帧数组的首指针
/// 用来接收的数据帧数组的长度
/// 等待超时时间,以毫秒为单位
/// 返回实际读取到的帧数。如果返回值为0xFFFFFFFF,则表示读取数据失败,有错误发生,请调用VCI_ReadErrInfo函数来获取错误码
[DllImport("controlcan.dll")]
static extern UInt32 VCI_Receive(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pReceive, UInt32 Len, Int32 WaitTime);
#endregion

}

}

相关主题
文本预览
相关文档 最新文档