C#调用C++库,进行串口通信
1、添加C++接口实现,将dll放置在运行路径下。
dll文件下载:https://files.cnblogs.com/files/ZM191018/SerialPortLib.rar?t=1722937417&download=true
[DllImport("SerialPortLib.dll",CharSet=CharSet.Unicode,CallingConvention =CallingConvention.StdCall)] static extern int openDevice(string COMName, int dwBaud, string sframe, ref UIntPtr hCom); [DllImport("SerialPortLib.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)] static extern int closeDevice(UIntPtr hCom); [DllImport("SerialPortLib.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)] static extern int startComminication(RECEIVE_CALLBACK receive, byte[] sendData, int dlen, UIntPtr hCom);
2、调用接口打开串口设备
UIntPtr hCom2 = UIntPtr.Zero; private void button3_Click(object sender, EventArgs e) { string strComName = comboBox1.Text; int iBaud = Convert.ToInt32(comboBox2.Text); string strFrame = comboBox3.Text; try { int iret = openDevice(strComName, iBaud, strFrame, ref hCom2); if (iret == 0) { button3.Enabled = false; } } catch (Exception ex) { MessageBox.Show(ex.ToString()); } }
3、调用接口将委托作为参数传入,当读取到数据时,进行回调
public delegate int RECEIVE_CALLBACK(IntPtr recvData, int dlen); private void button5_Click(object sender, EventArgs e) { string sendStr = richTextBox1.Text; byte[] sendArr=StringToHexByteArray(sendStr); int iret=startComminication(new RECEIVE_CALLBACK(RecvCallBack), sendArr,sendArr.Length, hCom2); } public int RecvCallBack(IntPtr recvData, int dlen) { if (recvData != null && dlen > 0) { byte[] data = new byte[dlen]; Marshal.Copy(recvData, data, 0, dlen); string str = BitConverter.ToString(data, 0, (int)dlen).Replace("-", ""); this.Invoke((EventHandler)delegate { richTextBox2.AppendText(str + "\n"); richTextBox2.SelectionStart = richTextBox2.Text.Length; richTextBox2.ScrollToCaret(); }); return 0; } else { return -1; } }
4、关闭串口
private void button4_Click(object sender, EventArgs e) { int iret = closeDevice(hCom2); if (iret == 0) { hCom2 = UIntPtr.Zero; button3.Enabled = true; } }
5、可能用到的方法
public static byte[] StringToHexByteArray(string hex) { if (hex.Length % 2 == 1) return null; int len = hex.Length >> 1; byte[] arr = new byte[len]; for (int i = 0; i < len; ++i) { arr[i] = (byte)((GetHexVal(hex[i << 1]) << 4) + (GetHexVal(hex[(i << 1) + 1]))); } return arr; } public static int GetHexVal(char hex) { int val = (int)hex; //For uppercase A-F letters: // return val - (val < 58 ? 48 : 55); //For lowercase a-f letters: //return val - (val < 58 ? 48 : 87); //Or the two combined, but a bit slower: return val - (val < 58 ? 48 : (val < 97 ? 55 : 87)); }
6、效果

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO.Ports; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Windows.Forms; namespace WindowsFormsApplication2 { public partial class Form1 : Form { [DllImport("SerialPortLib.dll",CharSet=CharSet.Unicode,CallingConvention =CallingConvention.StdCall)] static extern int openDevice(string COMName, int dwBaud, string sframe, ref UIntPtr hCom); [DllImport("SerialPortLib.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)] static extern int closeDevice(UIntPtr hCom); [DllImport("SerialPortLib.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)] static extern int startComminication(RECEIVE_CALLBACK receive, byte[] sendData, int dlen, UIntPtr hCom); UIntPtr hCom = UIntPtr.Zero; public Form1() { InitializeComponent(); string[] ports=SerialPort.GetPortNames(); for(int i = 0; i < ports.Length; i++) { comboBox1.Items.Add(ports[i]); } if (comboBox1.Items.Count > 0) { comboBox1.SelectedIndex = 0; } comboBox2.SelectedIndex = 0; comboBox3.SelectedIndex = 0; callBack = new RECEIVE_CALLBACK(RecvCallBack); callBack2 = new RECEIVE_CALLBACK(RecvCallBack2); } UIntPtr hCom2 = UIntPtr.Zero; private void button3_Click(object sender, EventArgs e) { string strComName = comboBox1.Text; int iBaud = Convert.ToInt32(comboBox2.Text); string strFrame = comboBox3.Text; try { int iret = openDevice(strComName, iBaud, strFrame, ref hCom2); if (iret == 0) { button3.Enabled = false; } } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } private void button4_Click(object sender, EventArgs e) { int iret = closeDevice(hCom2); if (iret == 0) { hCom2 = UIntPtr.Zero; button3.Enabled = true; } } public delegate int RECEIVE_CALLBACK(IntPtr recvData, int dlen); public RECEIVE_CALLBACK callBack; public RECEIVE_CALLBACK callBack2; Thread thr1; Thread thr2; private void button5_Click(object sender, EventArgs e) { string sendStr = string.Empty; this.Invoke((EventHandler)delegate { sendStr = richTextBox1.Text; }); byte[] sendArr=StringToHexByteArray(sendStr); int iret=startComminication(callBack, sendArr,sendArr.Length, hCom2); if (iret != 0) { trytimes1++; if (trytimes1 > 3) { flag1 = false; thr1.Join(); } } } public int RecvCallBack(IntPtr recvData, int dlen) { try { if (recvData != null && dlen > 0) { byte[] data = new byte[dlen]; Marshal.Copy(recvData, data, 0, dlen); string str = BitConverter.ToString(data, 0, (int)dlen).Replace("-", ""); this.Invoke((EventHandler)delegate { richTextBox2.AppendText(str + "\n"); richTextBox2.SelectionStart = richTextBox2.Text.Length; richTextBox2.ScrollToCaret(); }); trytimes1 = 0; return 0; } else { trytimes1++; if (trytimes1 > 3) { flag1 = false; thr1.Join(); } return -1; } } catch(Exception ex) { return -1; } } private void button6_Click(object sender, EventArgs e) { string sendStr = string.Empty; this.Invoke((EventHandler)delegate { sendStr = richTextBox3.Text; }); byte[] sendArr = StringToHexByteArray(sendStr); int iret = startComminication(callBack2, sendArr, sendArr.Length, hCom); if (iret != 0) { trytimes2++; if (trytimes2 > 3) { flag2 = false; thr2.Join(); } } } int trytimes2 = 0; int trytimes1 = 0; public int RecvCallBack2(IntPtr recvData, int dlen) { try { if (recvData != null && dlen > 0) { byte[] data = new byte[dlen]; Marshal.Copy(recvData, data, 0, dlen); string str = BitConverter.ToString(data, 0, (int)dlen).Replace("-", ""); this.Invoke((EventHandler)delegate { richTextBox4.AppendText(str + "\n"); richTextBox4.SelectionStart = richTextBox4.Text.Length; richTextBox4.ScrollToCaret(); }); trytimes2 = 0; return 0; } else { trytimes2++; if (trytimes2 > 3) { flag2 = false; thr2.Join(); } return -1; } } catch(Exception ex) { return -1; } } public static byte[] StringToHexByteArray(string hex) { if (hex.Length % 2 == 1) throw new Exception("The binary key cannot have an odd number of digits"); int len = hex.Length >> 1; byte[] arr = new byte[len]; for (int i = 0; i < len; ++i) { arr[i] = (byte)((GetHexVal(hex[i << 1]) << 4) + (GetHexVal(hex[(i << 1) + 1]))); } return arr; } public static int GetHexVal(char hex) { int val = (int)hex; //For uppercase A-F letters: // return val - (val < 58 ? 48 : 55); //For lowercase a-f letters: //return val - (val < 58 ? 48 : 87); //Or the two combined, but a bit slower: return val - (val < 58 ? 48 : (val < 97 ? 55 : 87)); } private void button2_Click(object sender, EventArgs e) { string strComName = comboBox1.Text; int iBaud = Convert.ToInt32(comboBox2.Text); string strFrame = comboBox3.Text; try { int iret = openDevice(strComName, iBaud, strFrame, ref hCom); if (iret == 0) { button2.Enabled = false; } } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } private void button1_Click(object sender, EventArgs e) { int iret = closeDevice(hCom); if (iret == 0) { hCom = UIntPtr.Zero; button2.Enabled = true; } } private void richTextBox3_TextChanged(object sender, EventArgs e) { } private void button7_Click(object sender, EventArgs e) { thr1 = new Thread(run1); thr2 = new Thread(run2); thr1.Start(); thr2.Start(); button7.Enabled = false; } bool flag1 = true; private void run1() { flag1 = true; while (flag1) { Thread.Sleep(10); button5_Click(null, null); } } bool flag2 = true; private void run2() { flag2 = true; while (flag2) { Thread.Sleep(10); button6_Click(null, null); } } private void button8_Click(object sender, EventArgs e) { flag1 = false; flag2 = false; button7.Enabled = true; } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { if(MessageBox.Show("关闭窗体?","提示", MessageBoxButtons.OKCancel)==DialogResult.Cancel) { e.Cancel = true; } } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」