C# WPF實(shí)現(xiàn)讀寫CAN數(shù)據(jù)
項(xiàng)目配置
復(fù)制Dll庫文件
文件在上面的資料里面
設(shè)置不安全代碼
CAN C#工具類
CAN_Tool.cs
using Microsoft.VisualBasic; using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Threading; namespace CAN_TEST.tool { /*------------兼容ZLG的數(shù)據(jù)類型---------------------------------*/ //1.ZLGCAN系列接口卡信息的數(shù)據(jù)類型。 //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 = 4)] // public byte[] Reserved; //} //以下為簡易定義與調(diào)用方式,在項(xiàng)目屬性->生成->勾選使用不安全代碼即可 unsafe 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; public fixed byte str_Serial_Num[20]; public fixed byte str_hw_Type[40]; public fixed byte Reserved[8]; } / //2.定義CAN信息幀的數(shù)據(jù)類型。 unsafe public struct VCI_CAN_OBJ //使用不安全代碼 { public uint ID; public uint TimeStamp; //時(shí)間標(biāo)識(shí) public byte TimeFlag; //是否使用時(shí)間標(biāo)識(shí) public byte SendType; //發(fā)送標(biāo)志。保留,未用 public byte RemoteFlag; //是否是遠(yuǎn)程幀 public byte ExternFlag; //是否是擴(kuò)展幀 public byte DataLen; //數(shù)據(jù)長度 public fixed byte Data[8]; //數(shù)據(jù) public fixed byte Reserved[3];//保留位 } //3.定義初始化CAN的數(shù)據(jù)類型 public struct VCI_INIT_CONFIG { public UInt32 AccCode; public UInt32 AccMask; public UInt32 Reserved; public byte Filter; //0或1接收所有幀。2標(biāo)準(zhǔn)幀濾波,3是擴(kuò)展幀濾波。 public byte Timing0; //波特率參數(shù),具體配置,請查看二次開發(fā)庫函數(shù)說明書。 public byte Timing1; public byte Mode; //模式,0表示正常模式,1表示只聽模式,2自測模式 } /*------------其他數(shù)據(jù)結(jié)構(gòu)描述---------------------------------*/ //4.USB-CAN總線適配器板卡信息的數(shù)據(jù)類型1,該類型為VCI_FindUsbDevice函數(shù)的返回參數(shù)。 public struct VCI_BOARD_INFO1 { public UInt16 hw_Version; public UInt16 fw_Version; public UInt16 dr_Version; public UInt16 in_Version; public UInt16 irq_Num; public byte can_Num; public byte Reserved; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] str_Serial_Num; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] str_hw_Type; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] str_Usb_Serial; } /*------------數(shù)據(jù)結(jié)構(gòu)描述完成---------------------------------*/ public struct CHGDESIPANDPORT { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public byte[] szpwd; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public byte[] szdesip; public Int32 desport; public void Init() { szpwd = new byte[10]; szdesip = new byte[20]; } } public class CAN_Tool { const int DEV_USBCAN = 3; const int DEV_USBCAN2 = 4; /// <summary> /// /// </summary> /// <param name="DeviceType"></param> /// <param name="DeviceInd"></param> /// <param name="Reserved"></param> /// <returns></returns> /*------------兼容ZLG的函數(shù)描述---------------------------------*/ /*------------兼容ZLG的函數(shù)描述---------------------------------*/ [DllImport("controlcan.dll")] public static extern UInt32 VCI_OpenDevice(UInt32 DeviceType, UInt32 DeviceInd, UInt32 Reserved); [DllImport("controlcan.dll")] public static extern UInt32 VCI_CloseDevice(UInt32 DeviceType, UInt32 DeviceInd); [DllImport("controlcan.dll")] public static extern UInt32 VCI_InitCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_INIT_CONFIG pInitConfig); [DllImport("controlcan.dll")] public static extern UInt32 VCI_ReadBoardInfo(UInt32 DeviceType, UInt32 DeviceInd, ref VCI_BOARD_INFO pInfo); [DllImport("controlcan.dll")] public static extern UInt32 VCI_GetReceiveNum(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd); [DllImport("controlcan.dll")] public static extern UInt32 VCI_ClearBuffer(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd); [DllImport("controlcan.dll")] public static extern UInt32 VCI_StartCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd); [DllImport("controlcan.dll")] public static extern UInt32 VCI_ResetCAN(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd); [DllImport("controlcan.dll")] public static extern UInt32 VCI_Transmit(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pSend, UInt32 Len); [DllImport("controlcan.dll")] public static extern UInt32 VCI_Receive(UInt32 DeviceType, UInt32 DeviceInd, UInt32 CANInd, ref VCI_CAN_OBJ pReceive, UInt32 Len, Int32 WaitTime); /*------------其他函數(shù)描述---------------------------------*/ [DllImport("controlcan.dll")] public static extern UInt32 VCI_ConnectDevice(UInt32 DevType, UInt32 DevIndex); [DllImport("controlcan.dll")] public static extern UInt32 VCI_UsbDeviceReset(UInt32 DevType, UInt32 DevIndex, UInt32 Reserved); [DllImport("controlcan.dll")] public static extern UInt32 VCI_FindUsbDevice2(ref VCI_BOARD_INFO pInfo); /*------------函數(shù)描述結(jié)束---------------------------------*/ static UInt32 m_bOpen = 0; static UInt32 m_devind = 0; static UInt32 m_canind = 0; static UInt32[] m_arrdevtype = new UInt32[20]; static VCI_CAN_OBJ[] m_recobj = new VCI_CAN_OBJ[1000]; static UInt32 m_devtype = 4;//USBCAN2 //this.timer_rec = new System.Windows.Forms.Timer(this.components); public static void init() { m_arrdevtype[2] = 3; m_arrdevtype[3] = 4; } public static void close_CAN() { CAN_Tool.VCI_CloseDevice(m_devtype, m_devind); m_bOpen = 0; } public static void start_CAN() { if (m_bOpen == 0) return; CAN_Tool.VCI_StartCAN(m_devtype, m_devind, m_canind); } unsafe public static string can_send(string can_data_idText,string can_send_data) { if (m_bOpen == 0) { MessageBox.Show("CAN斷開連接", "錯(cuò)誤"); return null; } VCI_CAN_OBJ sendobj = new VCI_CAN_OBJ(); //sendobj.Init(); sendobj.RemoteFlag = (byte)0; sendobj.ExternFlag = (byte)0; sendobj.ID = System.Convert.ToUInt32("0x" + can_data_idText, 16); int len = (can_send_data.Length + 1) / 3; sendobj.DataLen = System.Convert.ToByte(len); String strdata = can_send_data; //MessageBox.Show(strdata); int i = -1; if (i++ < len - 1) sendobj.Data[0] = System.Convert.ToByte("0x" + strdata.Substring(i * 3, 2), 16); if (i++ < len - 1) sendobj.Data[1] = System.Convert.ToByte("0x" + strdata.Substring(i * 3, 2), 16); if (i++ < len - 1) sendobj.Data[2] = System.Convert.ToByte("0x" + strdata.Substring(i * 3, 2), 16); if (i++ < len - 1) sendobj.Data[3] = System.Convert.ToByte("0x" + strdata.Substring(i * 3, 2), 16); if (i++ < len - 1) sendobj.Data[4] = System.Convert.ToByte("0x" + strdata.Substring(i * 3, 2), 16); if (i++ < len - 1) sendobj.Data[5] = System.Convert.ToByte("0x" + strdata.Substring(i * 3, 2), 16); if (i++ < len - 1) sendobj.Data[6] = System.Convert.ToByte("0x" + strdata.Substring(i * 3, 2), 16); if (i++ < len - 1) sendobj.Data[7] = System.Convert.ToByte("0x" + strdata.Substring(i * 3, 2), 16); if (CAN_Tool.VCI_Transmit(m_devtype, m_devind, m_canind, ref sendobj, 1) == 0) { MessageBox.Show("發(fā)送失敗", "錯(cuò)誤"); return null; } else { return "TX 幀ID:" + can_data_idText + " 數(shù)據(jù): " + can_send_data; } } public static string connect_CAN(int CAN_Type, int CAN_id,int RUN_mod) { //以下兩行為多卡同機(jī)測試代碼,用來獲取序列號與對應(yīng)的設(shè)備索引號,單卡可以不使用。 VCI_BOARD_INFO[] vbi2 = new VCI_BOARD_INFO[50]; uint num1 = CAN_Tool.VCI_FindUsbDevice2(ref vbi2[0]); m_devtype = m_arrdevtype[CAN_Type + 2]; m_devind = 0; m_canind = (UInt32)CAN_id; if (CAN_Tool.VCI_OpenDevice(m_devtype, m_devind, 0) == 0) { MessageBox.Show("打開設(shè)備失敗,請檢查設(shè)備類型和設(shè)備索引號是否正確", "錯(cuò)誤"); m_bOpen = 0; return ""; } m_bOpen = 1; VCI_INIT_CONFIG config = new VCI_INIT_CONFIG(); config.AccCode = System.Convert.ToUInt32("0x" + "00000000", 16); config.AccMask = System.Convert.ToUInt32("0x" + "FFFFFFFF", 16); config.Timing0 = System.Convert.ToByte("0x" + "00", 16); config.Timing1 = System.Convert.ToByte("0x" + "1C", 16); config.Filter = (Byte)(0 + 1); config.Mode = (Byte)RUN_mod; CAN_Tool.VCI_InitCAN(m_devtype, m_devind, m_canind, ref config); return m_bOpen == 0 ? "斷開" : "連接"; } unsafe public static string TimerRecTick() { UInt32 res = new UInt32(); res = CAN_Tool.VCI_Receive(m_devtype, m_devind, m_canind, ref m_recobj[0], 1000, 100); / //IntPtr[] ptArray = new IntPtr[1]; //ptArray[0] = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(VCI_CAN_OBJ)) * 50); //IntPtr pt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)) * 1); //Marshal.Copy(ptArray, 0, pt, 1); //MessageBox.Show(res+""); //res = VCI_Receive(m_devtype, m_devind, m_canind, pt, 50/*50*/, 100); if (res == 0xFFFFFFFF) res = 0;//當(dāng)設(shè)備未初始化時(shí),返回0xFFFFFFFF,不進(jìn)行列表顯示。 String str = ""; 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)); str = "RX: "; str += " 幀ID:0x" + System.Convert.ToString(m_recobj[i].ID, 16); str += " 幀格式:"; if (m_recobj[i].RemoteFlag == 0) str += "數(shù)據(jù)幀 "; else str += "遠(yuǎn)程幀 "; if (m_recobj[i].ExternFlag == 0) str += "標(biāo)準(zhǔn)幀 "; else str += "擴(kuò)展幀 "; // if (m_recobj[i].RemoteFlag == 0) { str += "數(shù)據(jù): "; byte len = (byte)(m_recobj[i].DataLen % 9); byte j = 0; fixed (VCI_CAN_OBJ* m_recobj1 = &m_recobj[i]) { if (j++ < len) str += " " + System.Convert.ToString(m_recobj1->Data[0], 16); if (j++ < len) str += " " + System.Convert.ToString(m_recobj1->Data[1], 16); if (j++ < len) str += " " + System.Convert.ToString(m_recobj1->Data[2], 16); if (j++ < len) str += " " + System.Convert.ToString(m_recobj1->Data[3], 16); if (j++ < len) str += " " + System.Convert.ToString(m_recobj1->Data[4], 16); if (j++ < len) str += " " + System.Convert.ToString(m_recobj1->Data[5], 16); if (j++ < len) str += " " + System.Convert.ToString(m_recobj1->Data[6], 16); if (j++ < len) str += " " + System.Convert.ToString(m_recobj1->Data[7], 16); } } return str + "\n"; } return null; } } }
主界面
MainWindow.xaml
<Window x:Class="CAN_TEST.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Title="CAN測試" Height="600" Width="400"> <Grid> <StackPanel> <StackPanel Orientation="Horizontal" Height="30" Margin="0,20,0,0"> <Button Margin="10,0,0,0" Click="connect_CAN" Width="100">連接分析儀</Button> <Button Margin="20,0,0,0" Click="close_CAN" Width="100">斷開分析儀</Button> <Button Margin="20,0,0,0" Click="start_CAN" Width="100">啟動(dòng)CAN</Button> </StackPanel> <StackPanel Orientation="Horizontal" Height="30" Margin="0,20,0,0"> <StackPanel Orientation="Horizontal" Margin="20,0,0,0"> <TextBlock>CAN類型</TextBlock> <ComboBox HorizontalAlignment="Center" Width="100" Margin="20,0,0,0" x:Name="CAN_Type"> <ComboBoxItem>USBCAN V1</ComboBoxItem> <ComboBoxItem>USBCAN V2</ComboBoxItem> </ComboBox> </StackPanel> <StackPanel Orientation="Horizontal" Margin="20,0,0,0"> <TextBlock>CAN通道</TextBlock> <ComboBox HorizontalAlignment="Center" Width="100" Margin="20,0,0,0" x:Name="CAN_id"> <ComboBoxItem>CAN1</ComboBoxItem> <ComboBoxItem>CAN2</ComboBoxItem> </ComboBox> </StackPanel> </StackPanel> <StackPanel Orientation="Horizontal" Height="30" Margin="0,20,0,0"> <StackPanel Orientation="Horizontal" Margin="20,0,0,0"> <TextBlock>CAN運(yùn)行模式</TextBlock> <ComboBox HorizontalAlignment="Center" Width="100" Margin="20,0,0,0" x:Name="RUN_mod"> <ComboBoxItem>正常</ComboBoxItem> <ComboBoxItem>只聽</ComboBoxItem> <ComboBoxItem>自測</ComboBoxItem> </ComboBox> </StackPanel> <TextBlock Margin="20,0,0,0">連接狀態(tài):</TextBlock> <TextBlock Text="斷開" x:Name="CAN_statusText"></TextBlock> </StackPanel> <StackPanel Orientation="Horizontal"> <StackPanel Orientation="Vertical" Width="300" Margin="0,10,0,0"> <TextBlock TextAlignment="Center">數(shù)據(jù)發(fā)送</TextBlock> <StackPanel Orientation="Horizontal" Margin="0,10,0,0"> <TextBlock TextAlignment="Center" Margin="20,0,0,0">幀ID:</TextBlock> <TextBox Width="200" Margin="33,0,0,0" x:Name="can_data_id" Text="00000123"></TextBox> </StackPanel> <StackPanel Orientation="Horizontal" Margin="0,10,0,0"> <TextBlock TextAlignment="Center" Margin="20,0,0,0">發(fā)送數(shù)據(jù):</TextBlock> <TextBox Width="200" Margin="10,0,0,0" x:Name="can_send_data" Text="00 01 02 03 04 05 06 07 "></TextBox> </StackPanel> <Button Width="50" Margin="0,10,0,0" Click="can_send">發(fā)送</Button> </StackPanel> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBlock TextAlignment="Center">數(shù)據(jù)接收</TextBlock> </StackPanel> <StackPanel Orientation="Horizontal"> <TextBox Width="350" Height="200" Margin="10,0,0,0" VerticalScrollBarVisibility="Visible" MaxLines="5" x:Name="resData" TextWrapping="Wrap"> </TextBox> </StackPanel> </StackPanel> </Grid> </Window>
MainWindow.xaml.cs
using CAN_TEST.tool; using System.Collections.ObjectModel; using System.ComponentModel; using System.Configuration; using System.Runtime.InteropServices; using System.Text; using System.Timers; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Windows.Threading; using static CAN_TEST.MainWindow; namespace HZFM_TEST { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { DispatcherTimer m_timer = new DispatcherTimer(); public MainWindow() { InitializeComponent(); // 初始化CAN CAN_Tool.init(); // 啟動(dòng)定時(shí)器 m_timer.Interval = TimeSpan.FromSeconds(0.2); m_timer.Tick += new System.EventHandler(timer_rec_Tick); } private void close_CAN(object sender, RoutedEventArgs e) { // 關(guān)閉CAN CAN_Tool.close_CAN(); } private void start_CAN(object sender, RoutedEventArgs e) { // 啟動(dòng)CAN CAN_Tool.start_CAN(); } private void connect_CAN(object sender, RoutedEventArgs e) { // 連接CAN分析儀 string outData = CAN_Tool.connect_CAN(CAN_Type.SelectedIndex, CAN_id.SelectedIndex, RUN_mod.SelectedIndex); if(outData.Length > 0) { m_timer.Start(); } CAN_statusText.Text = outData; } // 定時(shí)收數(shù)據(jù)任務(wù) unsafe private void timer_rec_Tick(object sender, EventArgs e) { string res = CAN_Tool.TimerRecTick(); if(res != null) { resData.AppendText(res + "\r\n"); } } // 發(fā)送慘數(shù)據(jù) unsafe private void can_send(object sender, RoutedEventArgs e) { string res = CAN_Tool.can_send(can_data_id.Text, can_send_data.Text); if (res != null) { resData.AppendText(res + "\r\n"); } } // 讀取數(shù)據(jù) private void read_Data(object sender, RoutedEventArgs e) { Button btn = sender as Button; int id = int.Parse(btn.CommandParameter.ToString()) + 1; string res = CAN_Tool.can_send("01800300", can_send_data.Text); if (res != null) { resData.AppendText(res + "\r\n"); } } } }
到此這篇關(guān)于C# WPF實(shí)現(xiàn)讀寫CAN數(shù)據(jù)的文章就介紹到這了,更多相關(guān)C#讀寫CAN數(shù)據(jù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#實(shí)現(xiàn)修改系統(tǒng)時(shí)間的方法
這篇文章主要介紹了C#實(shí)現(xiàn)修改系統(tǒng)時(shí)間的方法,是一個(gè)非常實(shí)用的功能,需要的朋友可以參考下2014-07-07C# 創(chuàng)建文本文件寫入讀取實(shí)現(xiàn)代碼
C# 創(chuàng)建文本文件寫入讀取,可以用來做系統(tǒng)日志或程序操作日志或者錯(cuò)誤記錄,需要的朋友可以參考下。2011-11-11C#編程:List.ForEach與foreach循環(huán)的對比分析
這篇文章主要介紹了C#編程:List.ForEach與foreach循環(huán)的對比分析,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-03-03C#將html table 導(dǎo)出成excel實(shí)例
C#將html table 導(dǎo)出成excel實(shí)例,需要的朋友可以參考一下2013-04-04巧用Dictionary實(shí)現(xiàn)日志數(shù)據(jù)批量插入
這篇文章主要介紹了巧用Dictionary實(shí)現(xiàn)日志數(shù)據(jù)批量插入,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02解析c#操作excel后關(guān)閉excel.exe的方法
C#和Asp.net下excel進(jìn)程一被打開,有時(shí)就無法關(guān)閉,尤其是website.對關(guān)閉該進(jìn)程有過GC、release等方法,但這些方法并不是在所有情況下均適用2013-07-07C#實(shí)現(xiàn)讓窗體獲得焦點(diǎn)的方法示例
這篇文章主要介紹了C#實(shí)現(xiàn)讓窗體獲得焦點(diǎn)的方法,涉及C#窗體事件相關(guān)操作技巧,需要的朋友可以參考下2017-06-06