using ImTools;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace OrpaonEMS.App.CANDrive
{
///
/// CAN驱动
/// EMUC-B202-W1_CAN_API_V2.2.0_Win
/// EMUC-B202-W1_CAN 有两个CAN口,目前工控机接出来的是CAN2口,那么调用和使用的时候使用CAN2口,在一些函数使用的过程中
/// 需要同时指定两个口的参数,那么另一个不适用的随便设置
///
public class CAN
{
const string LibName = @"C:\\CAN_inno\\EMUC-B202-W1_CAN_API_V2.2.0_Win\\2.0B_Lib_v2.2.0\\64\\lib_emuc2_64.dll";
/* load .dll */
[DllImport(LibName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int EMUCOpenDevice(int com_port);
[DllImport(LibName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int EMUCCloseDevice(int com_port);
///
/// Get firmware and library version
///
///
///
///
[DllImport(LibName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int EMUCShowVer(int com_port, ref VER_INFO ver_info);
[DllImport(LibName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int EMUCResetCAN(int com_port);
[DllImport(LibName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int EMUCClearFilter(int com_port, int CAN_port);
///
/// Set CAN port to active/inactive. Default is inactive.
///
///
///
///
///
[DllImport(LibName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int EMUCInitCAN(int com_port, int CAN1_sts, int CAN2_sts);
[DllImport(LibName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int EMUCSetBaudRate(int com_port, int CAN1_baud, int CAN2_baud);
[DllImport(LibName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int EMUCSetMode(int com_port, int CAN1_mode, int CAN2_mode);
[DllImport(LibName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int EMUCSetFilter(int com_port, ref FILTER_INFO filter_info);
[DllImport(LibName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int EMUCSetErrorType(int com_port, int err_type);
///
/// Set CAN acceptance filter
///
///
///
///
[DllImport(LibName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int EMUCGetCfg(int com_port, ref CFG_INFO cfg_info);
[DllImport(LibName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int EMUCExpCfg(int com_port, [MarshalAs(UnmanagedType.LPStr)] string file_name);
[DllImport(LibName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int EMUCImpCfg(int com_port, [MarshalAs(UnmanagedType.LPStr)] string file_name);
[DllImport(LibName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int EMUCSend(int com_port, ref CAN_FRAME_INFO can_frame_info);
[DllImport(LibName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int EMUCReceive(int com_port, ref CAN_FRAME_INFO can_frame_info);
[DllImport(LibName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int EMUCReceiveNonblockCS(int com_port, uint cnt, uint interval, [Out] CAN_FRAME_INFO[] can_frame_info);
///
/// 实例化函数
///
public CAN()
{
}
///
/// Can连接
///
///
public static bool ConnectionCan(BaudRate ConBaudRate)
{
int i;
int j;
//返回值
int rtn;
//获取Com口给Global
Global.com_port = FindEmucDev();
if (Global.com_port >= 0)
{
Console.WriteLine("EMUC open device (COM {0}) successfully !\n", Global.com_port + 1);
/* ----- EMUCInitCAN() ----- */
rtn = EMUCInitCAN(Global.com_port, CANStatus.EMUC_INACTIVE.GetHashCode(), CANStatus.EMUC_INACTIVE.GetHashCode());
if (rtn == 0)
Console.WriteLine("EMUC initial CAN successfully !\n");
else
Console.WriteLine("EMUC initial CAN failed !\n");
/* ----- EMUCShowVer() ----- */
rtn = EMUCShowVer(Global.com_port, ref Global.ver_info);
if (rtn == 0)
{
Console.WriteLine("EMUC show version successfully !");
Console.WriteLine("FW ver: {0}", Global.ver_info.fw);
Console.WriteLine("LIB ver: {0}", Global.ver_info.api);
Console.WriteLine("Model: {0}\n", Global.ver_info.model);
}
else
Console.WriteLine("EMUC show version failed !\n");
/* ----- EMUCResetCAN() ----- */
rtn = EMUCResetCAN(Global.com_port);
if (rtn == 0)
Console.WriteLine("EMUC reset CAN successfully !\n");
else
Console.WriteLine("EMUC reset CAN failed !\n");
/* ----- EMUCClearFilter() ----- */
Global.CAN_port = CANPort.EMUC_CAN_2.GetHashCode();
rtn = EMUCClearFilter(Global.com_port, Global.CAN_port);
if (rtn == 0)
Console.WriteLine("EMUC clear filter successfully !\n");
else
Console.WriteLine("EMUC clear filter failed !\n");
/* ----- EMUCSetBaudRate() ----- */
rtn = EMUCSetBaudRate(Global.com_port, ConBaudRate.GetHashCode(), ConBaudRate.GetHashCode());
if (rtn == 0)
Console.WriteLine("EMUC set baud rate successfully !\n");
else
Console.WriteLine("EMUC set baud rate failed !\n");
/* ----- EMUCSetErrorType() ----- */
rtn = EMUCSetErrorType(Global.com_port, ErrType.EMUC_DIS_ALL.GetHashCode());
if (rtn == 0)
Console.WriteLine("EMUC set error type successfully !\n");
else
Console.WriteLine("EMUC set error type failed !\n");
/* ----- EMUCSetMode() ----- */
rtn = EMUCSetMode(Global.com_port, CANMode.EMUC_NORMAL.GetHashCode(), CANMode.EMUC_NORMAL.GetHashCode());
if (rtn == 0)
Console.WriteLine("EMUC set mode successfully !\n");
else
Console.WriteLine("EMUC set mode failed !\n");
/* ----- CAN1的设置 EMUCSetFilter() ----- */
Global.filter_info.CAN_port = CANPort.EMUC_CAN_1.GetHashCode();
Global.filter_info.flt_type = IDType.EMUC_SID.GetHashCode();
Global.filter_info.flt_id = 0x0000ABCD;
Global.filter_info.mask = 0x1FFFFFFF;
rtn = EMUCSetFilter(Global.com_port, ref Global.filter_info);
if (rtn == 0)
Console.WriteLine("EMUC set CAN 1 filter successfully !\n");
else
Console.WriteLine("EMUC set CAN 1 filter failed !\n");
/* ----- CAN2的设置 EMUCSetFilter() ----- */
Global.filter_info.CAN_port = CANPort.EMUC_CAN_2.GetHashCode();
Global.filter_info.flt_type = IDType.EMUC_SID.GetHashCode();
Global.filter_info.flt_id = 0x00000000;
Global.filter_info.mask = 0x00000000;
rtn = EMUCSetFilter(Global.com_port, ref Global.filter_info);
if (rtn == 0)
Console.WriteLine("EMUC set CAN 2 filter successfully !\n");
else
Console.WriteLine("EMUC set CAN 2 filter failed !\n");
/* ----- EMUCGetCfg() ----- */
/* ----- 获取配置信息----- */
rtn = EMUCGetCfg(Global.com_port, ref Global.cfg_info);
if (rtn == 0)
{
Console.WriteLine("EMUC get config. successfully !");
for (i = 0; i < Global.CAN_NUM; i++)
{
Console.WriteLine("CAN {0}:", i + 1);
Console.WriteLine("baud rate = {0}", Global.cfg_info.baud[i]);
Console.WriteLine("mode = {0}", Global.cfg_info.mode[i]);
Console.WriteLine("filter type = {0}", Global.cfg_info.flt_type[i]);
Console.WriteLine("filter id = {0:X8}", Global.cfg_info.flt_id[i]);
Console.WriteLine("filter mask = {0:X8}\n", Global.cfg_info.flt_mask[i]);
}
Console.WriteLine("error set = {0}\n", Global.cfg_info.err_set);
}
else
Console.WriteLine("EMUC get config. failed !\n");
/* Send & Receive must initial CAN to EMUC_ACTIVE */
/*---------------------------------------------------------------------------*/
//EMUCClearFilter(Global.com_port, CANPort.EMUC_CAN_1.GetHashCode()); /* not necessary */
//EMUCClearFilter(Global.com_port, CANPort.EMUC_CAN_2.GetHashCode()); /* not necessary */
rtn = EMUCInitCAN(Global.com_port, CANStatus.EMUC_ACTIVE.GetHashCode(), CANStatus.EMUC_ACTIVE.GetHashCode());
if (rtn == 0)
{
return true;
}
else
{
return false;
}
}
else Console.WriteLine("No EMUC device !\n"); return false;
}
///
/// 发送数据
///
public static bool SendData(uint id, byte[] data)
{
//int i;
/* ----- EMUCSend ----- */
Global.frame_send.CAN_port = CANPort.EMUC_CAN_2.GetHashCode();//默认使用CAN2口
Global.frame_send.id_type = IDType.EMUC_EID.GetHashCode();//默认使用标准帧
Global.frame_send.rtr = RTRSelect.EMUC_DIS_RTR.GetHashCode();//默认使用数据帧,不是远程数据帧
Global.frame_send.dlc = 8;//默认数据长度为8
//Global.frame_send.id = 0x00000011;
Global.frame_send.id = id;
//Global.frame_send.data = Global.data_send;
Global.frame_send.data = data;
//Console.WriteLine("EMUC send started !");
//for (i = 0; i < Global.data_send_cnt; i++)
//{
// Thread.Sleep(1);
if (EMUCSend(Global.com_port, ref Global.frame_send) == 0)
{
//Console.WriteLine("EMUC send finished !\n", Global.data_send_cnt);
return true;
}
return false;
//EMUCSend(Global.com_port, ref Global.frame_send);
//}
Console.WriteLine("EMUC send finished (with {0} data) !\n", Global.data_send_cnt);
}
///
///接受到的消息内容
///
public static void Start()
{
/* ----- EMUCReceive() ----- */
Global.TRDRecv.Start();
Console.WriteLine("\nEMUC reveice start ...\n");
}
///
/// 停止接收线程并关闭设备
///
public static void Stop()
{
try { Global.StopRequested = true; } catch { }
try {
if (Global.TRDRecv != null && Global.TRDRecv.IsAlive)
{
Global.TRDRecv.Join(500);
}
} catch { }
try { if (Global.com_port >= 0) EMUCCloseDevice(Global.com_port); } catch { }
}
public void StartTest()
{
int i;
int j;
//返回值
int rtn;
/* for EMUCReceiveNonblockCS() */
uint cnt;
uint interval;
CAN_FRAME_INFO[] frame_non_block;
/*-----------------------------*/
//获取Com口给Global
Global.com_port = FindEmucDev();
if (Global.com_port >= 0)
{
Console.WriteLine("EMUC open device (COM {0}) successfully !\n", Global.com_port + 1);
/* ----- EMUCInitCAN() ----- */
rtn = EMUCInitCAN(Global.com_port, CANStatus.EMUC_INACTIVE.GetHashCode(), CANStatus.EMUC_INACTIVE.GetHashCode());
if (rtn == 0)
Console.WriteLine("EMUC initial CAN successfully !\n");
else
Console.WriteLine("EMUC initial CAN failed !\n");
/* ----- EMUCShowVer() ----- */
rtn = EMUCShowVer(Global.com_port, ref Global.ver_info);
if (rtn == 0)
{
Console.WriteLine("EMUC show version successfully !");
Console.WriteLine("FW ver: {0}", Global.ver_info.fw);
Console.WriteLine("LIB ver: {0}", Global.ver_info.api);
Console.WriteLine("Model: {0}\n", Global.ver_info.model);
}
else
Console.WriteLine("EMUC show version failed !\n");
/* ----- EMUCResetCAN() ----- */
rtn = EMUCResetCAN(Global.com_port);
if (rtn == 0)
Console.WriteLine("EMUC reset CAN successfully !\n");
else
Console.WriteLine("EMUC reset CAN failed !\n");
/* ----- EMUCClearFilter() ----- */
Global.CAN_port = CANPort.EMUC_CAN_1.GetHashCode();
rtn = EMUCClearFilter(Global.com_port, Global.CAN_port);
if (rtn == 0)
Console.WriteLine("EMUC clear filter successfully !\n");
else
Console.WriteLine("EMUC clear filter failed !\n");
/* ----- EMUCSetBaudRate() ----- */
rtn = EMUCSetBaudRate(Global.com_port, BaudRate.EMUC_BAUDRATE_1M.GetHashCode(), BaudRate.EMUC_BAUDRATE_1M.GetHashCode());
if (rtn == 0)
Console.WriteLine("EMUC set baud rate successfully !\n");
else
Console.WriteLine("EMUC set baud rate failed !\n");
/* ----- EMUCSetErrorType() ----- */
rtn = EMUCSetErrorType(Global.com_port, ErrType.EMUC_DIS_ALL.GetHashCode());
if (rtn == 0)
Console.WriteLine("EMUC set error type successfully !\n");
else
Console.WriteLine("EMUC set error type failed !\n");
/* ----- EMUCSetMode() ----- */
rtn = EMUCSetMode(Global.com_port, CANMode.EMUC_NORMAL.GetHashCode(), CANMode.EMUC_NORMAL.GetHashCode());
if (rtn == 0)
Console.WriteLine("EMUC set mode successfully !\n");
else
Console.WriteLine("EMUC set mode failed !\n");
/* ----- EMUCSetFilter() ----- */
Global.filter_info.CAN_port = CANPort.EMUC_CAN_1.GetHashCode();
Global.filter_info.flt_type = IDType.EMUC_EID.GetHashCode();
Global.filter_info.flt_id = 0x0000ABCD;
Global.filter_info.mask = 0x1FFFFFFF;
rtn = EMUCSetFilter(Global.com_port, ref Global.filter_info);
if (rtn == 0)
Console.WriteLine("EMUC set CAN 1 filter successfully !\n");
else
Console.WriteLine("EMUC set CAN 1 filter failed !\n");
Global.filter_info.CAN_port = CANPort.EMUC_CAN_2.GetHashCode();
Global.filter_info.flt_type = IDType.EMUC_EID.GetHashCode();
Global.filter_info.flt_id = 0x00001234;
Global.filter_info.mask = 0x00FFEEEE;
rtn = EMUCSetFilter(Global.com_port, ref Global.filter_info);
if (rtn == 0)
Console.WriteLine("EMUC set CAN 2 filter successfully !\n");
else
Console.WriteLine("EMUC set CAN 2 filter failed !\n");
/* ----- EMUCGetCfg() ----- */
rtn = EMUCGetCfg(Global.com_port, ref Global.cfg_info);
if (rtn == 0)
{
Console.WriteLine("EMUC get config. successfully !");
for (i = 0; i < Global.CAN_NUM; i++)
{
Console.WriteLine("CAN {0}:", i + 1);
Console.WriteLine("baud rate = {0}", Global.cfg_info.baud[i]);
Console.WriteLine("mode = {0}", Global.cfg_info.mode[i]);
Console.WriteLine("filter type = {0}", Global.cfg_info.flt_type[i]);
Console.WriteLine("filter id = {0:X8}", Global.cfg_info.flt_id[i]);
Console.WriteLine("filter mask = {0:X8}\n", Global.cfg_info.flt_mask[i]);
}
Console.WriteLine("error set = {0}\n", Global.cfg_info.err_set);
}
else
Console.WriteLine("EMUC get config. failed !\n");
/* ----- EMUCExpCfg() ----- */
rtn = EMUCExpCfg(Global.com_port, Global.file_name);
if (rtn == 0)
Console.WriteLine("EMUC export config. successfully !\n");
else
Console.WriteLine("EMUC export config. failed !\n");
/* ----- EMUCImpCfg() ----- */
rtn = EMUCImpCfg(Global.com_port, Global.file_name);
if (rtn == 0)
Console.WriteLine("EMUC import config. successfully !\n");
else
Console.WriteLine("EMUC import config. failed !\n");
/* Send & Receive must initial CAN to EMUC_ACTIVE */
/*---------------------------------------------------------------------------*/
EMUCClearFilter(Global.com_port, CANPort.EMUC_CAN_1.GetHashCode()); /* not necessary */
EMUCClearFilter(Global.com_port, CANPort.EMUC_CAN_2.GetHashCode()); /* not necessary */
EMUCInitCAN(Global.com_port, CANStatus.EMUC_ACTIVE.GetHashCode(), CANStatus.EMUC_ACTIVE.GetHashCode());
/* ----- EMUCSend ----- */
Global.frame_send.CAN_port = CANPort.EMUC_CAN_1.GetHashCode();
Global.frame_send.id_type = IDType.EMUC_EID.GetHashCode();
Global.frame_send.rtr = RTRSelect.EMUC_DIS_RTR.GetHashCode();
Global.frame_send.dlc = 8;
Global.frame_send.id = 0x001234AB;
Global.frame_send.data = Global.data_send;
Console.WriteLine("EMUC send started !");
for (i = 0; i < Global.data_send_cnt; i++)
{
Thread.Sleep(1);
EMUCSend(Global.com_port, ref Global.frame_send);
}
Console.WriteLine("EMUC send finished (with {0} data) !\n", Global.data_send_cnt);
/* ----- EMUCReceiveNonblock() ----- */
cnt = 5;
interval = 5 * 1000;
frame_non_block = new CAN_FRAME_INFO[cnt];
Console.WriteLine("Non-block ---------------------> Time start !");
rtn = EMUCReceiveNonblockCS(Global.com_port, cnt, interval, frame_non_block);
if (rtn > 0)
{
Console.WriteLine("Non-block ---------------------> Time out or Data enough !\n");
for (i = 0; i < rtn; i++)
{
switch (frame_non_block[i].msg_type)
{
case (int)MsgType.EMUC_DATA_TYPE:
PrintData(frame_non_block[i]);
break;
case (int)MsgType.EMUC_EEERR_TYPE:
Console.WriteLine("EEPROM Error !");
break;
case (int)MsgType.EMUC_BUSERR_TYPE:
Console.WriteLine("Bus Error !");
System.Console.Write("error data (CAN 1): ");
for (j = 0; j < Global.DATA_LEN_ERR; j++)
System.Console.Write("{0:X2} ", frame_non_block[i].data_err[j]);
Console.WriteLine();
System.Console.Write("error data (CAN 2): ");
for (j = 0; j < Global.DATA_LEN_ERR; j++)
System.Console.Write("{0:X2} ", frame_non_block[i].data_err[j + Global.DATA_LEN_ERR]);
Console.WriteLine();
break;
default:
break;
}
}
}
else
Console.WriteLine("Non-block ---------------------> Time out (No data) !\n");
/* ----- EMUCReceive() ----- */
Global.TRDRecv.Start();
Console.WriteLine("\nEMUC reveice start ...\n");
/* ----- EMUCCloseDevice() ----- */
/*
rtn = EMUCCloseDevice(Global.com_port);
if(rtn == 0)
Console.WriteLine("EMUC close device (COM {0}) successfully !\n", Global.com_port + 1);
else
Console.WriteLine("EMUC close device failed !\n");
*/
while (true)
Thread.Sleep(10000);
}
else
Console.WriteLine("No EMUC device !\n");
Console.ReadLine();
}
#region 原始方法
/* success: return COM ID, failed: return -1 */
/*---------------------------------------------------------------------*/
///
/// 打开后返回对应的Com口
/// 返回Com口的ID
///
///
public static int FindEmucDev()
{
int i;
int rtn = -1;
for (i = 0; i < Global.MAX_COM_NUM; i++)
{
if (EMUCOpenDevice(i) == 0)
{
rtn = i;
break;
}
}
return rtn;
} /* END: FindEmucDev() */
/*---------------------------------------------------------------------*/
///
/// 循环接受数据
///
public static void TRDRecvFx()
{
int i;
int rtn;
while (!Global.StopRequested)
{
rtn = EMUCReceive(Global.com_port, ref Global.frame_recv);
if (rtn == 1)
{
switch (Global.frame_recv.msg_type)
{
case (int)MsgType.EMUC_DATA_TYPE:
PrintData(Global.frame_recv);
switch (Global.frame_recv.id)
{
case 402686016://ID(0x18008040)
ACCANParsData.Load_0x18008040_Msg(Global.frame_recv);
break;
case 402751552://ID(0x18018040)
ACCANParsData.Load_0x18018040_Msg(Global.frame_recv);
break;
default:
break;
}
break;
case (int)MsgType.EMUC_EEERR_TYPE:
Console.WriteLine("EEPROM Error !");
break;
case (int)MsgType.EMUC_BUSERR_TYPE:
//Console.WriteLine("Bus Error !");
//System.Console.Write("error data (CAN 1): ");
//for (i = 0; i < Global.DATA_LEN_ERR; i++)
// //System.Console.Write("{0:X2} ", Global.frame_recv.data_err[i]);
////Console.WriteLine();
//System.Console.Write("error data (CAN 2): ");
//for (i = 0; i < Global.DATA_LEN_ERR; i++)
// //System.Console.Write("{0:X2} ", Global.frame_recv.data_err[i + Global.DATA_LEN_ERR]);
////Console.WriteLine();
break;
default:
break;
}
}
}
} /* END: TRDRecvFx() */
public static void ParseData(byte[] data)
{
}
/*---------------------------------------------------------------------*/
///
/// 打印数据
///
///
public static void PrintData(CAN_FRAME_INFO frame_recv)
{
int i;
/* CAN port & cnt */
if (frame_recv.CAN_port == CANPort.EMUC_CAN_1.GetHashCode())
{
Global.recv_cnt1++;
//System.Console.Write("(CAN 1) {0}. ", Global.recv_cnt1);
}
else if (frame_recv.CAN_port == CANPort.EMUC_CAN_2.GetHashCode())
{
Global.recv_cnt2++;
//System.Console.Write("(CAN 2) {0}. ", Global.recv_cnt2);
}
/* ID */
//if (frame_recv.id_type == IDType.EMUC_SID.GetHashCode())
//System.Console.Write("ID: {0:X3}; ", frame_recv.id);
//else if (frame_recv.id_type == IDType.EMUC_EID.GetHashCode())
//System.Console.Write("ID: {0:X8}; ", frame_recv.id);
/* Data */
//System.Console.Write("Data: ");
//for (i = 0; i < frame_recv.dlc; i++)
//System.Console.Write("{0:X2} ", frame_recv.data[i]);
//Console.WriteLine();
} /* END: PrintData() */
#endregion
/* global variables */
public class Global
{
///
/// 设备最大的COM数
///
public const int MAX_COM_NUM = 256;
public const int CAN_NUM = 2;
public const int DATA_LEN = 8;
public const int DATA_LEN_ERR = 6;
///
/// Com口
/// -1是失败的
///
public static int com_port { get; set; }
///
/// CAN口
///
public static int CAN_port { get; set; }
[MarshalAs(UnmanagedType.LPStr)]
public static string file_name = "emuc_config";
public static int data_send_cnt = 500;
public static byte[] data_send = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 };
public static uint recv_cnt1 = 0;
public static uint recv_cnt2 = 0;
///
/// 停止标志
///
public static volatile bool StopRequested = false;
///
/// 版本信息
///
public static VER_INFO ver_info = new VER_INFO();
///
/// 过滤信息
///
public static FILTER_INFO filter_info = new FILTER_INFO();
public static CFG_INFO cfg_info = new CFG_INFO();
public static CAN_FRAME_INFO frame_send = new CAN_FRAME_INFO();
public static CAN_FRAME_INFO frame_recv = new CAN_FRAME_INFO();
public static Thread TRDRecv = new Thread(TRDRecvFx) { IsBackground = true };
}
}
/* structure */
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct VER_INFO
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string fw;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string api;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string model;
}
///
///
/// CAN标识符、过滤器、屏蔽器之间的关系
///CAN节点通过标识符来识别CAN帧是不是自己想要的,识别方法就是通过滤波屏蔽寄存器的设置来完成,接收滤波寄存器设置了标识符每位的值,
///接收屏蔽寄存器一般有相同的数量匹配接收滤波寄存器,规定接收滤波寄存器标识符每一位的值是否需要进行匹配,比如芯片设置有6个接收滤波寄存器和6个接收屏蔽青存器,
///从总线上接收 CAN 帧,然后依次将收到的 CAN 帧标识符与6对接收滤波和屏蔽寄存器进行匹配,符合某对接收滤波和屏蔽寄存器要求了,就停止匹配,将数据接收到对应的缓冲区中..
///例如:设置某接收滤波寄存器 00000000001(11 位),接收屏蔽寄存器 11111111101(11 位),则该对组合会拒绝接收 00000000011和 00000000001 之外所有的标识符对应的 CAN 帧,
///因为屏蔽器规定第二位(为 0)以外的所有标识符位要严格匹配(与滤波器值一致),第二位的滤波器值和收到的 CAN 标识符第二位值是否一致都可以。
/// https://www.cnblogs.com/lijf/p/17418979.html
///对于机器来说,我们要为它准备好两张纸片,一片写上屏蔽码,另一片纸片写上验证码,屏蔽码上相应位为1时,表示此位需要与验证码对应位进行比较,反之,则表示不需要。机器在执行任务的时候先将获取的身份证号码与屏蔽码进行“与”操作,再将结果与验证码的进行比较,根据判断是否相同来决定是否通过。整个判别流程如下所示:
///从上图可以很容易地理解屏蔽码与验证码的含义,这样一来,能通过的结果数量就完全取决于屏蔽码,设得宽,则可以通过的多(所有位为0,则不过任何过滤操作,则谁都可以通过),设得窄,则通过的少(所有位设为1,则只有一个能通过)。那么知道这个有什么用呢?因为bxCAN的过滤器的掩码模式就是采用这种方式,在bxCAN中,分别采用了两个寄存器(CAN_FiR1,CAN_FiR2)来存储屏蔽码与验证码,从而实现掩码模式的工作流程的。这样,我们就知道了bxCAN过滤器的掩码模式的大概工作原理。
///
///
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct FILTER_INFO
{
public int CAN_port;
///
/// 过滤类型/方式
/// 比如:只收标准码,只收拓展码,接受所有类型
///
public int flt_type;
///
/// 过滤验收码
/// 就是要接收的帧ID
///
public uint flt_id;
///
/// 过滤屏蔽码
/// 就是选择性的过滤帧ID。
/// 当屏蔽码的某一位为1时,则忽略此位,此位不需要与验收码一致。当屏蔽码的某一位为0时,此位必须与验收码的此位一致。
///
public uint mask;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct CFG_INFO
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public byte[] baud;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public byte[] mode;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public byte[] flt_type;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public uint[] flt_id;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public uint[] flt_mask;
public byte err_set;
}
#region 结构体和枚举
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct CAN_FRAME_INFO
{
///
/// 哪个端口发送的
/// 当前的CAN模块有两个端口
///
public int CAN_port;
///
/// : [input] CAN ID type. (SID=11bit, EID=29bit)
/// 标准还是拓展
///
public int id_type;
///
/// [input] Remote transmit request
/// 远程还是数据帧
///
public int rtr;
///
/// dlc: [input] Data length.
/// 数据长度
///
public int dlc;
///
/// There three types of received data define in msg_type.
//1. EMUC_DATA_TYPE: Normal CAN frame.
//2. EMUC_EEERR_TYPE: EEPROM error message.
//3. EMUC_BUSERR_TYPE: Register of CANbus error status.
///
public int msg_type;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 13)]
public string recv_time; /* e.g., 15:30:58:789 (h:m:s:ms) */
///
/// 帧Id
///
public uint id;
///
/// 接受的数据
///
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] data;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
public byte[] data_err;
}
/* enumeration */
enum CANPort : int
{
///
/// CAN1
///
EMUC_CAN_1 = 0,
///
/// CAN2
///
EMUC_CAN_2
};
/*----------------------*/
public enum BaudRate : int
{
EMUC_BAUDRATE_100K = 4,
EMUC_BAUDRATE_125K,
EMUC_BAUDRATE_250K,
EMUC_BAUDRATE_500K,
EMUC_BAUDRATE_800K,
EMUC_BAUDRATE_1M
};
/*----------------------*/
enum CANStatus : int
{
///
/// 默认
/// 未激活
///
EMUC_INACTIVE = 0,
///
/// 激活
///
EMUC_ACTIVE
};
/*----------------------*/
enum CANMode : int
{
///
/// 正常
///
EMUC_NORMAL = 0,
///
/// 监听(只听)模式
///
EMUC_LISTEN
};
/*----------------------*/
///
/// 过滤类型/方式
///
/// 比如:只收标准码,只收拓展码,接受所有类型
///
/// ***也可以作为发送时的帧的类型的***
///
public enum IDType : int
{
//0可能是接受所有类型
///
/// SID=11bit
/// 标准帧
///
EMUC_SID = 1,
///
/// EID=29bit
/// Extended Mode
/// 拓展帧
///
EMUC_EID
};
/*----------------------*/
enum RTRSelect : int
{
///
/// 取消使用RTR
/// 普通的
/// 数据帧
///
EMUC_DIS_RTR = 0,
///
/// 启用RTR
/// 远程帧
///
EMUC_EN_RTR
};
/*----------------------*/
///
/// CAN Error Frame
///
enum ErrType : int
{
///
/// disable all error frame
///
EMUC_DIS_ALL = 0,
///
/// enable EEPROM error only
///
EMUC_EE_ERR,
///
/// enable CAN bus error only
///
EMUC_BUS_ERR,
///
/// enable both EERPOM and CAN bus error
///
EMUC_EN_ALL = 255
};
/*----------------------*/
///
/// There three types of received data define in msg_type
///
enum MsgType : int
{
///
/// Normal CAN frame
///
EMUC_DATA_TYPE = 0,
///
/// EEPROM error message
///
EMUC_EEERR_TYPE,
///
/// : Register of CANbus error status
///
EMUC_BUSERR_TYPE
};
#endregion
}