956 lines
37 KiB
C#
956 lines
37 KiB
C#
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
|
||
{
|
||
/// <summary>
|
||
/// CAN驱动
|
||
/// EMUC-B202-W1_CAN_API_V2.2.0_Win
|
||
/// EMUC-B202-W1_CAN 有两个CAN口,目前工控机接出来的是CAN2口,那么调用和使用的时候使用CAN2口,在一些函数使用的过程中
|
||
/// 需要同时指定两个口的参数,那么另一个不适用的随便设置
|
||
/// </summary>
|
||
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);
|
||
/// <summary>
|
||
/// Get firmware and library version
|
||
/// </summary>
|
||
/// <param name="com_port"></param>
|
||
/// <param name="ver_info"></param>
|
||
/// <returns></returns>
|
||
[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);
|
||
|
||
/// <summary>
|
||
/// Set CAN port to active/inactive. Default is inactive.
|
||
/// </summary>
|
||
/// <param name="com_port"></param>
|
||
/// <param name="CAN1_sts"></param>
|
||
/// <param name="CAN2_sts"></param>
|
||
/// <returns></returns>
|
||
[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);
|
||
|
||
/// <summary>
|
||
/// Set CAN acceptance filter
|
||
/// </summary>
|
||
/// <param name="com_port"></param>
|
||
/// <param name="cfg_info"></param>
|
||
/// <returns></returns>
|
||
[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);
|
||
|
||
/// <summary>
|
||
/// 实例化函数
|
||
/// </summary>
|
||
public CAN()
|
||
{
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// Can连接
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
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;
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 发送数据
|
||
/// </summary>
|
||
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);
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
///接受到的消息内容
|
||
/// </summary>
|
||
public static void Start()
|
||
{
|
||
/* ----- EMUCReceive() ----- */
|
||
Global.TRDRecv.Start();
|
||
Console.WriteLine("\nEMUC reveice start ...\n");
|
||
}
|
||
|
||
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 */
|
||
/*---------------------------------------------------------------------*/
|
||
/// <summary>
|
||
/// 打开后返回对应的Com口
|
||
/// 返回Com口的ID
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
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() */
|
||
|
||
|
||
/*---------------------------------------------------------------------*/
|
||
/// <summary>
|
||
/// 循环接受数据
|
||
/// </summary>
|
||
public static void TRDRecvFx()
|
||
{
|
||
int i;
|
||
int rtn;
|
||
|
||
while (true)
|
||
{
|
||
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)
|
||
{
|
||
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------------------*/
|
||
/// <summary>
|
||
/// 打印数据
|
||
/// </summary>
|
||
/// <param name="frame_recv"></param>
|
||
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
|
||
{
|
||
/// <summary>
|
||
/// 设备最大的COM数
|
||
/// </summary>
|
||
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;
|
||
|
||
/// <summary>
|
||
/// Com口
|
||
/// -1是失败的
|
||
/// </summary>
|
||
public static int com_port { get; set; }
|
||
/// <summary>
|
||
/// CAN口
|
||
/// </summary>
|
||
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;
|
||
/// <summary>
|
||
/// 版本信息
|
||
/// </summary>
|
||
public static VER_INFO ver_info = new VER_INFO();
|
||
/// <summary>
|
||
/// 过滤信息
|
||
/// </summary>
|
||
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);
|
||
}
|
||
|
||
|
||
}
|
||
|
||
|
||
|
||
/* 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;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
///
|
||
/// 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过滤器的掩码模式的大概工作原理。
|
||
///
|
||
/// </summary>
|
||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
|
||
public struct FILTER_INFO
|
||
{
|
||
public int CAN_port;
|
||
/// <summary>
|
||
/// 过滤类型/方式
|
||
/// 比如:只收标准码,只收拓展码,接受所有类型
|
||
/// </summary>
|
||
public int flt_type;
|
||
/// <summary>
|
||
/// 过滤验收码
|
||
/// 就是要接收的帧ID
|
||
/// </summary>
|
||
public uint flt_id;
|
||
/// <summary>
|
||
/// 过滤屏蔽码
|
||
/// 就是选择性的过滤帧ID。
|
||
/// 当屏蔽码的某一位为1时,则忽略此位,此位不需要与验收码一致。当屏蔽码的某一位为0时,此位必须与验收码的此位一致。
|
||
/// </summary>
|
||
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
|
||
{
|
||
/// <summary>
|
||
/// 哪个端口发送的
|
||
/// 当前的CAN模块有两个端口
|
||
/// </summary>
|
||
public int CAN_port;
|
||
/// <summary>
|
||
/// : [input] CAN ID type. (SID=11bit, EID=29bit)
|
||
/// 标准还是拓展
|
||
/// </summary>
|
||
public int id_type;
|
||
/// <summary>
|
||
/// [input] Remote transmit request
|
||
/// 远程还是数据帧
|
||
/// </summary>
|
||
public int rtr;
|
||
/// <summary>
|
||
/// dlc: [input] Data length.
|
||
/// 数据长度
|
||
/// </summary>
|
||
public int dlc;
|
||
/// <summary>
|
||
/// 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.
|
||
/// </summary>
|
||
public int msg_type;
|
||
|
||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 13)]
|
||
public string recv_time; /* e.g., 15:30:58:789 (h:m:s:ms) */
|
||
|
||
/// <summary>
|
||
/// 帧Id
|
||
/// </summary>
|
||
public uint id;
|
||
/// <summary>
|
||
/// 接受的数据
|
||
/// </summary>
|
||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
|
||
public byte[] data;
|
||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
|
||
public byte[] data_err;
|
||
}
|
||
|
||
/* enumeration */
|
||
enum CANPort : int
|
||
{
|
||
/// <summary>
|
||
/// CAN1
|
||
/// </summary>
|
||
EMUC_CAN_1 = 0,
|
||
/// <summary>
|
||
/// CAN2
|
||
/// </summary>
|
||
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
|
||
{
|
||
/// <summary>
|
||
/// 默认
|
||
/// 未激活
|
||
/// </summary>
|
||
EMUC_INACTIVE = 0,
|
||
/// <summary>
|
||
/// 激活
|
||
/// </summary>
|
||
EMUC_ACTIVE
|
||
};
|
||
|
||
/*----------------------*/
|
||
enum CANMode : int
|
||
{
|
||
/// <summary>
|
||
/// 正常
|
||
/// </summary>
|
||
EMUC_NORMAL = 0,
|
||
/// <summary>
|
||
/// 监听(只听)模式
|
||
/// </summary>
|
||
EMUC_LISTEN
|
||
};
|
||
|
||
/*----------------------*/
|
||
/// <summary>
|
||
/// 过滤类型/方式
|
||
///
|
||
/// 比如:只收标准码,只收拓展码,接受所有类型
|
||
///
|
||
/// ***也可以作为发送时的帧的类型的***
|
||
/// </summary>
|
||
public enum IDType : int
|
||
{
|
||
//0可能是接受所有类型
|
||
|
||
|
||
/// <summary>
|
||
/// SID=11bit
|
||
/// 标准帧
|
||
/// </summary>
|
||
EMUC_SID = 1,
|
||
/// <summary>
|
||
/// EID=29bit
|
||
/// Extended Mode
|
||
/// 拓展帧
|
||
/// </summary>
|
||
EMUC_EID
|
||
};
|
||
|
||
/*----------------------*/
|
||
enum RTRSelect : int
|
||
{
|
||
/// <summary>
|
||
/// 取消使用RTR
|
||
/// 普通的
|
||
/// 数据帧
|
||
/// </summary>
|
||
EMUC_DIS_RTR = 0,
|
||
/// <summary>
|
||
/// 启用RTR
|
||
/// 远程帧
|
||
/// </summary>
|
||
EMUC_EN_RTR
|
||
};
|
||
|
||
/*----------------------*/
|
||
/// <summary>
|
||
/// CAN Error Frame
|
||
/// </summary>
|
||
enum ErrType : int
|
||
{
|
||
/// <summary>
|
||
/// disable all error frame
|
||
/// </summary>
|
||
EMUC_DIS_ALL = 0,
|
||
/// <summary>
|
||
/// enable EEPROM error only
|
||
/// </summary>
|
||
EMUC_EE_ERR,
|
||
/// <summary>
|
||
/// enable CAN bus error only
|
||
/// </summary>
|
||
EMUC_BUS_ERR,
|
||
/// <summary>
|
||
/// enable both EERPOM and CAN bus error
|
||
/// </summary>
|
||
EMUC_EN_ALL = 255
|
||
};
|
||
|
||
/*----------------------*/
|
||
/// <summary>
|
||
/// There three types of received data define in msg_type
|
||
/// </summary>
|
||
enum MsgType : int
|
||
{
|
||
/// <summary>
|
||
/// Normal CAN frame
|
||
/// </summary>
|
||
EMUC_DATA_TYPE = 0,
|
||
/// <summary>
|
||
/// EEPROM error message
|
||
/// </summary>
|
||
EMUC_EEERR_TYPE,
|
||
/// <summary>
|
||
/// : Register of CANbus error status
|
||
/// </summary>
|
||
EMUC_BUSERR_TYPE
|
||
};
|
||
|
||
#endregion
|
||
|
||
|
||
|
||
}
|