visual stdio中,用C#,串口通讯写一个简单的对话
using System; using System.IO.Ports; using System.Text; using System.Windows.Forms; namespace SerialPortTool { public partial class Form1 : Form { public Form1() { InitializeComponent(); // 窗体加载初始化参数列表 InitSerialParam(); // 绑定串口数据接收事件 serialPort1.DataReceived SerialPort1_DataReceived; } #region 初始化串口下拉框参数 private void InitSerialParam() { // 刷新端口列表 RefreshPortList(); // 波特率常用值 cbxBaud.Items.AddRange(new object[] { 9600, 19200, 38400, 115200 }); cbxBaud.Text 115200; // 数据位 cbxDataBit.Items.AddRange(new object[] { 5, 6, 7, 8 }); cbxDataBit.Text 8; // 校验位 cbxCheck.Items.AddRange(new object[] { 无, 奇校验, 偶校验 }); cbxCheck.Text 无; // 停止位 cbxStopBit.Items.AddRange(new object[] { 1, 2 }); cbxStopBit.Text 1; } #endregion // 刷新电脑可用COM端口 private void RefreshPortList() { cbxPort.Items.Clear(); string[] ports SerialPort.GetPortNames(); cbxPort.Items.AddRange(ports); if (ports.Length 0) cbxPort.Text ports[0]; } #region 打开/关闭串口按钮点击事件 private void btnOpenSerial_Click(object sender, EventArgs e) { // 先判断串口是否已经打开 if (serialPort1.IsOpen) { serialPort1.Close(); btnOpenSerial.Text 打开串口; MessageBox.Show(串口已关闭); return; } // 前置校验防止解析崩溃无提示 if (string.IsNullOrEmpty(cbxPort.Text)) { MessageBox.Show(端口下拉框为空未识别到COM端口); return; } if (string.IsNullOrEmpty(cbxBaud.Text) || string.IsNullOrEmpty(cbxDataBit.Text)) { MessageBox.Show(波特率/数据位不能为空请选择参数); return; } // 校验下拉框文本是否为纯数字防止手动输入文字报错 if (!int.TryParse(cbxBaud.Text, out int baud)) { MessageBox.Show(波特率必须是数字); return; } if (!int.TryParse(cbxDataBit.Text, out int databit)) { MessageBox.Show(数据位必须是数字); return; } try { serialPort1.PortName cbxPort.Text; serialPort1.BaudRate baud; serialPort1.DataBits databit; // 校验位 switch (cbxCheck.Text) { case 奇校验: serialPort1.Parity Parity.Odd; break; case 偶校验: serialPort1.Parity Parity.Even; break; default: serialPort1.Parity Parity.None; break; } // 停止位 serialPort1.StopBits cbxStopBit.Text 2 ? StopBits.Two : StopBits.One; serialPort1.Encoding Encoding.GetEncoding(GBK); serialPort1.Open(); btnOpenSerial.Text 关闭串口; MessageBox.Show($串口{cbxPort.Text}打开成功); } catch (Exception ex) { // 所有错误都会弹出提示不会无声卡死 MessageBox.Show($打开串口失败\n{ex.Message}, 错误, MessageBoxButtons.OK, MessageBoxIcon.Error); } } #endregion #region 串口接收数据异步回调跨线程更新UI private void SerialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e) { byte[] recvBuf new byte[serialPort1.BytesToRead]; serialPort1.Read(recvBuf, 0, recvBuf.Length); // 委托更新UI跨线程必须Invoke this.Invoke(new Action(() { string recvStr; if (chkHexShow.Checked) { // 16进制显示 recvStr BytesToHex(recvBuf); txtRecv.AppendText($【接收】{recvStr}\r\n); } else { // 文本显示GBK兼容中文 recvStr Encoding.GetEncoding(GBK).GetString(recvBuf); txtRecv.AppendText($【接收】{recvStr}\r\n); } // 自动滚动到末尾 txtRecv.ScrollToCaret(); })); } #endregion #region 发送按钮点击事件 private void btnSend_Click(object sender, EventArgs e) { if (!serialPort1.IsOpen) { MessageBox.Show(请先打开串口); return; } string sendContent txtSend.Text; if (string.IsNullOrWhiteSpace(sendContent)) return; // 勾选发送新行自动追加\r\n if (chkSendNewLine.Checked) sendContent \r\n; byte[] sendBuf; try { if (chkHexSend.Checked) { // 16进制发送文本转字节数组 sendBuf HexToBytes(sendContent); } else { // 文本发送 sendBuf Encoding.GetEncoding(GBK).GetBytes(sendContent); } // 执行发送 serialPort1.Write(sendBuf, 0, sendBuf.Length); // 本地回显发送内容到接收框 this.Invoke(new Action(() { string showText; if (chkHexSend.Checked) showText BytesToHex(sendBuf); else showText sendContent; txtRecv.AppendText($【发送】{showText}\r\n); txtRecv.ScrollToCaret(); })); } catch (Exception ex) { MessageBox.Show(发送失败 ex.Message, 错误, MessageBoxButtons.OK, MessageBoxIcon.Error); } } #endregion #region 工具方法字节 ↔ 16进制字符串互转 // 字节数组转空格分隔16进制字符串 private string BytesToHex(byte[] data) { StringBuilder sb new StringBuilder(); foreach (byte b in data) { sb.Append(b.ToString(X2) ); } return sb.ToString().Trim(); } // 16进制字符串转字节数组 private byte[] HexToBytes(string hexStr) { hexStr hexStr.Replace( , ); if (hexStr.Length % 2 ! 0) throw new Exception(16进制字符长度必须为偶数); byte[] buffer new byte[hexStr.Length / 2]; for (int i 0; i buffer.Length; i) { buffer[i] Convert.ToByte(hexStr.Substring(i * 2, 2), 16); } return buffer; } #endregion } }