当前位置: 首页 > news >正文

开源 C# 快速开发(七)通讯--串口

         文章的目的为了记录使用C# 开发学习的经历。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。

相关链接:

开源 C# 快速开发(一)基础知识

开源 C# 快速开发(二)基础控件

开源 C# 快速开发(三)复杂控件

开源 C# 快速开发(四)自定义控件--波形图

开源 C# 快速开发(五)自定义控件--仪表盘

开源 C# 快速开发(六)自定义控件--圆环

开源 C# 快速开发(七)通讯--串口

推荐链接:

开源 C# .net mvc 开发(一)WEB搭建_c#部署web程序-CSDN博客

开源 C# .net mvc 开发(二)网站快速搭建_c#网站开发-CSDN博客

开源 C# .net mvc 开发(三)WEB内外网访问-CSDN博客

开源 C# .net mvc 开发(四)工程结构、页面提交以及显示-CSDN博客

开源 C# .net mvc 开发(五)常用代码快速开发_c# mvc开发-CSDN博客

开源 C# .net mvc 开发(六)发送邮件、定时以及CMD编程-CSDN博客

开源 C# .net mvc 开发(七)动态图片、动态表格和json数据生成-CSDN博客

开源 C# .net mvc 开发(八)IIS Express轻量化Web服务器的配置和使用-CSDN博客

开源 C# .net mvc 开发(九)websocket--服务器与客户端的实时通信-CSDN博客

本章节主要内容是:用C#编写的串口通信工具程序,基于Windows Forms和串口控件实现。

目录:

1.源码分析

2.所有源码

3.效果演示

一、源码分析

1. 构造函数 Form1()
功能:程序启动时的初始化工作,建立自动刷新串口列表的机制。

public Form1()
{InitializeComponent();          // 初始化窗体控件InitializeSerialPort();        // 初始化串口事件处理RefreshPortList();             // 刷新可用串口列表// 创建定时器,每秒刷新一次串口列表System.Windows.Forms.Timer timerRefreshPorts = new System.Windows.Forms.Timer();timerRefreshPorts.Interval = 1000;  // 设置间隔为1000毫秒timerRefreshPorts.Tick += (s, e) => RefreshPortList();  // Lambda表达式处理Tick事件timerRefreshPorts.Start();     // 启动定时器
}

2. 串口初始化 InitializeSerialPort()
功能:绑定串口的数据接收和错误接收事件处理方法。


private void InitializeSerialPort()
{// 注册数据接收事件处理程序serialPort.DataReceived += new SerialDataReceivedEventHandler(SerialPort_DataReceived);// 注册错误接收事件处理程序serialPort.ErrorReceived += new SerialErrorReceivedEventHandler(SerialPort_ErrorReceived);
}

3. 刷新串口列表 RefreshPortList()
功能:动态刷新可用串口列表,保持用户选择状态。

private void RefreshPortList()
{// 保存当前选择的串口string currentSelection = comboBoxPort.SelectedItem?.ToString();// 清空并重新填充串口列表comboBoxPort.Items.Clear();string[] ports = SerialPort.GetPortNames();  // 获取系统可用串口comboBoxPort.Items.AddRange(ports);          // 添加到下拉框// 恢复之前的选择(如果仍然存在)if (!string.IsNullOrEmpty(currentSelection) && comboBoxPort.Items.Contains(currentSelection)){comboBoxPort.SelectedItem = currentSelection;}// 否则选择第一个可用串口else if (comboBoxPort.Items.Count > 0){comboBoxPort.SelectedIndex = 0;}
}

4. 打开/关闭串口按钮 buttonOpenClose_Click()

功能:切换串口的打开/关闭状态。

private void buttonOpenClose_Click(object sender, EventArgs e)
{// 根据串口当前状态决定操作if (serialPort.IsOpen){CloseSerialPort();    // 如果已打开,则关闭}else{OpenSerialPort();     // 如果已关闭,则打开}
}


5. 打开串口 OpenSerialPort()
功能:根据用户选择的参数配置并打开串口。

private void OpenSerialPort()
{// 检查是否选择了串口if (comboBoxPort.SelectedItem == null){MessageBox.Show("请选择串口!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);return;}try{// 配置串口参数serialPort.PortName = comboBoxPort.SelectedItem.ToString();serialPort.BaudRate = int.Parse(comboBoxBaudRate.SelectedItem.ToString());serialPort.DataBits = int.Parse(comboBoxDataBits.SelectedItem.ToString());// 配置校验位(5种模式)switch (comboBoxParity.SelectedItem.ToString()){case "None": serialPort.Parity = Parity.None; break;case "Odd": serialPort.Parity = Parity.Odd; break;case "Even": serialPort.Parity = Parity.Even; break;case "Mark": serialPort.Parity = Parity.Mark; break;case "Space": serialPort.Parity = Parity.Space; break;}// 配置停止位(3种模式)switch (comboBoxStopBits.SelectedItem.ToString()){case "1": serialPort.StopBits = StopBits.One; break;case "1.5": serialPort.StopBits = StopBits.OnePointFive; break;case "2": serialPort.StopBits = StopBits.Two; break;}serialPort.Open();  // 打开串口// 更新UI状态buttonOpenClose.Text = "关闭串口";comboBoxPort.Enabled = false;comboBoxBaudRate.Enabled = false;comboBoxDataBits.Enabled = false;comboBoxParity.Enabled = false;comboBoxStopBits.Enabled = false;}catch (Exception ex){MessageBox.Show($"打开串口失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);}
}


6. 关闭串口 CloseSerialPort()
功能:安全关闭串口并恢复界面控件的可用状态。

private void CloseSerialPort()
{try{// 安全关闭串口if (serialPort.IsOpen){serialPort.Close();}// 恢复UI状态buttonOpenClose.Text = "打开串口";comboBoxPort.Enabled = true;comboBoxBaudRate.Enabled = true;comboBoxDataBits.Enabled = true;comboBoxParity.Enabled = true;comboBoxStopBits.Enabled = true;// 停止自动发送功能checkBoxAutoSend.Checked = false;}catch (Exception ex){MessageBox.Show($"关闭串口失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);}
}


7. 数据接收处理 SerialPort_DataReceived()
功能:在后台线程中接收串口数据,通过线程安全的方式更新UI。

private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{try{// 读取可用数据int bytesToRead = serialPort.BytesToRead;byte[] buffer = new byte[bytesToRead];serialPort.Read(buffer, 0, bytesToRead);// 通过Invoke在UI线程中更新显示this.Invoke(new Action(() => DisplayReceivedData(buffer)));}catch (Exception ex){// 错误信息也要在UI线程中显示this.Invoke(new Action(() =>MessageBox.Show($"接收数据错误:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error)));}
}


8. 数据显示 DisplayReceivedData()
功能:将接收到的字节数据按指定格式显示在文本框中。

private void DisplayReceivedData(byte[] data)
{// 根据复选框选择显示格式if (checkBoxHexReceive.Checked){// 十六进制显示:将字节数组转换为"XX XX XX"格式string hexString = BitConverter.ToString(data).Replace("-", " ");textBoxReceive.AppendText(hexString + " ");}else{// ASCII显示:将字节数组转换为字符串string asciiString = Encoding.ASCII.GetString(data);textBoxReceive.AppendText(asciiString);}// 自动滚动到最新内容textBoxReceive.SelectionStart = textBoxReceive.Text.Length;textBoxReceive.ScrollToCaret();
}

9. 错误接收处理 SerialPort_ErrorReceived()
功能:处理串口通信错误,在接收框中显示错误信息。

private void SerialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
{// 在UI线程中显示错误信息this.Invoke(new Action(() =>textBoxReceive.AppendText($"[错误:{e.EventType}]\r\n")));
}


10. 数据发送 SendData()
功能:处理数据发送逻辑,支持两种格式。

private void SendData()
{// 前置检查if (!serialPort.IsOpen){MessageBox.Show("请先打开串口!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);return;}if (string.IsNullOrEmpty(textBoxSend.Text)){MessageBox.Show("发送内容不能为空!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);return;}try{byte[] sendData;// 根据复选框选择发送格式if (checkBoxHexSend.Checked){// 十六进制发送sendData = HexStringToByteArray(textBoxSend.Text);}else{// ASCII发送sendData = Encoding.ASCII.GetBytes(textBoxSend.Text);}serialPort.Write(sendData, 0, sendData.Length);  // 发送数据}catch (Exception ex){MessageBox.Show($"发送数据失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);}
}


11. 十六进制转换 HexStringToByteArray()
功能:将十六进制字符串转换为字节数组,支持灵活的输入格式。

private byte[] HexStringToByteArray(string hex)
{// 清理字符串:移除所有空格、横线、换行符等hex = hex.Replace(" ", "").Replace("-", "").Replace("\r", "").Replace("\n", "").Replace("\t", "");// 验证长度if (hex.Length % 2 != 0){throw new ArgumentException("十六进制字符串长度必须为偶数");}// 每两个字符转换成一个字节byte[] bytes = new byte[hex.Length / 2];for (int i = 0; i < hex.Length; i += 2){string hexByte = hex.Substring(i, 2);           // 提取两个字符bytes[i / 2] = Convert.ToByte(hexByte, 16);    // 转换为字节}return bytes;
}


12. 自动发送控制 checkBoxAutoSend_CheckedChanged()
功能:管理自动发送功能的启动和停止。

private void checkBoxAutoSend_CheckedChanged(object sender, EventArgs e)
{if (checkBoxAutoSend.Checked){// 启用自动发送前的检查if (!serialPort.IsOpen)        {MessageBox.Show("请先打开串口!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);checkBoxAutoSend.Checked = false;return;}// 配置并启动定时器timerAutoSend.Interval = (int)numericUpDownInterval.Value;timerAutoSend.Tick += (s, args) => SendData();  // 每次Tick事件触发发送timerAutoSend.Start();}else{// 停止自动发送timerAutoSend.Stop();}// 控制间隔设置控件的可用状态numericUpDownInterval.Enabled = !checkBoxAutoSend.Checked;
}

13. 窗体关闭处理 OnFormClosing()
功能:重写窗体关闭事件,确保资源正确释放。

protected override void OnFormClosing(FormClosingEventArgs e)
{// 确保程序退出前关闭串口if (serialPort.IsOpen){serialPort.Close();}base.OnFormClosing(e);  // 调用基类方法
}

二、所有源码

Form1.designer.cs文件


using System;
using System.Drawing;
using System.IO.Ports;
using System.Windows.Forms;namespace _7_uart
{partial class Form1{/*/// <summary>/// 必需的设计器变量。/// </summary>private System.ComponentModel.IContainer components = null;/// <summary>/// 清理所有正在使用的资源。/// </summary>/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>protected override void Dispose(bool disposing){if (disposing && (components != null)){components.Dispose();}base.Dispose(disposing);}#region Windows 窗体设计器生成的代码/// <summary>/// 设计器支持所需的方法 - 不要修改/// 使用代码编辑器修改此方法的内容。/// </summary>private void InitializeComponent(){this.components = new System.ComponentModel.Container();this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;this.ClientSize = new System.Drawing.Size(800, 450);this.Text = "Form1";}#endregion*/private System.ComponentModel.IContainer components = null;private ComboBox comboBoxPort;private ComboBox comboBoxBaudRate;private ComboBox comboBoxDataBits;private ComboBox comboBoxParity;private ComboBox comboBoxStopBits;private Button buttonOpenClose;private TextBox textBoxSend;private TextBox textBoxReceive;private Button buttonSend;private CheckBox checkBoxHexSend;private CheckBox checkBoxHexReceive;private CheckBox checkBoxAutoSend;private NumericUpDown numericUpDownInterval;private Label label1, label2, label3, label4, label5, label6, label7;private SerialPort serialPort;private System.Windows.Forms.Timer timerAutoSend;protected override void Dispose(bool disposing){if (disposing && (components != null)){components.Dispose();if (serialPort != null && serialPort.IsOpen)serialPort.Close();}base.Dispose(disposing);}private void InitializeComponent(){this.components = new System.ComponentModel.Container();this.comboBoxPort = new System.Windows.Forms.ComboBox();this.comboBoxBaudRate = new System.Windows.Forms.ComboBox();this.comboBoxDataBits = new System.Windows.Forms.ComboBox();this.comboBoxParity = new System.Windows.Forms.ComboBox();this.comboBoxStopBits = new System.Windows.Forms.ComboBox();this.buttonOpenClose = new System.Windows.Forms.Button();this.textBoxSend = new System.Windows.Forms.TextBox();this.textBoxReceive = new System.Windows.Forms.TextBox();this.buttonSend = new System.Windows.Forms.Button();this.checkBoxHexSend = new System.Windows.Forms.CheckBox();this.checkBoxHexReceive = new System.Windows.Forms.CheckBox();this.checkBoxAutoSend = new System.Windows.Forms.CheckBox();this.numericUpDownInterval = new System.Windows.Forms.NumericUpDown();this.label1 = new System.Windows.Forms.Label();this.label2 = new System.Windows.Forms.Label();this.label3 = new System.Windows.Forms.Label();this.label4 = new System.Windows.Forms.Label();this.label5 = new System.Windows.Forms.Label();this.label6 = new System.Windows.Forms.Label();this.label7 = new System.Windows.Forms.Label();this.serialPort = new System.IO.Ports.SerialPort(this.components);this.timerAutoSend = new System.Windows.Forms.Timer(this.components);((System.ComponentModel.ISupportInitialize)(this.numericUpDownInterval)).BeginInit();this.SuspendLayout();// // comboBoxPort// this.comboBoxPort.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;this.comboBoxPort.Location = new System.Drawing.Point(80, 20);this.comboBoxPort.Name = "comboBoxPort";this.comboBoxPort.Size = new System.Drawing.Size(100, 23);this.comboBoxPort.TabIndex = 0;// // comboBoxBaudRate// this.comboBoxBaudRate.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;this.comboBoxBaudRate.Items.AddRange(new object[] {"9600","19200","38400","57600","115200"});this.comboBoxBaudRate.Location = new System.Drawing.Point(80, 60);this.comboBoxBaudRate.Name = "comboBoxBaudRate";this.comboBoxBaudRate.Size = new System.Drawing.Size(100, 23);this.comboBoxBaudRate.TabIndex = 1;// // comboBoxDataBits// this.comboBoxDataBits.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;this.comboBoxDataBits.Items.AddRange(new object[] {"5","6","7","8"});this.comboBoxDataBits.Location = new System.Drawing.Point(280, 20);this.comboBoxDataBits.Name = "comboBoxDataBits";this.comboBoxDataBits.Size = new System.Drawing.Size(100, 23);this.comboBoxDataBits.TabIndex = 2;// // comboBoxParity// this.comboBoxParity.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;this.comboBoxParity.Items.AddRange(new object[] {"None","Odd","Even","Mark","Space"});this.comboBoxParity.Location = new System.Drawing.Point(280, 60);this.comboBoxParity.Name = "comboBoxParity";this.comboBoxParity.Size = new System.Drawing.Size(100, 23);this.comboBoxParity.TabIndex = 3;// // comboBoxStopBits// this.comboBoxStopBits.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;this.comboBoxStopBits.Items.AddRange(new object[] {"1","1.5","2"});this.comboBoxStopBits.Location = new System.Drawing.Point(480, 20);this.comboBoxStopBits.Name = "comboBoxStopBits";this.comboBoxStopBits.Size = new System.Drawing.Size(100, 23);this.comboBoxStopBits.TabIndex = 4;// // buttonOpenClose// this.buttonOpenClose.Location = new System.Drawing.Point(480, 60);this.buttonOpenClose.Name = "buttonOpenClose";this.buttonOpenClose.Size = new System.Drawing.Size(100, 30);this.buttonOpenClose.TabIndex = 5;this.buttonOpenClose.Text = "打开串口";this.buttonOpenClose.Click += new System.EventHandler(this.buttonOpenClose_Click);// // textBoxSend// this.textBoxSend.Location = new System.Drawing.Point(20, 150);this.textBoxSend.Multiline = true;this.textBoxSend.Name = "textBoxSend";this.textBoxSend.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;this.textBoxSend.Size = new System.Drawing.Size(560, 100);this.textBoxSend.TabIndex = 6;// // textBoxReceive// this.textBoxReceive.Location = new System.Drawing.Point(20, 313);this.textBoxReceive.Multiline = true;this.textBoxReceive.Name = "textBoxReceive";this.textBoxReceive.ReadOnly = true;this.textBoxReceive.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;this.textBoxReceive.Size = new System.Drawing.Size(560, 187);this.textBoxReceive.TabIndex = 7;// // buttonSend// this.buttonSend.Location = new System.Drawing.Point(480, 260);this.buttonSend.Name = "buttonSend";this.buttonSend.Size = new System.Drawing.Size(100, 30);this.buttonSend.TabIndex = 8;this.buttonSend.Text = "发送";this.buttonSend.Click += new System.EventHandler(this.buttonSend_Click);// // checkBoxHexSend// this.checkBoxHexSend.Location = new System.Drawing.Point(20, 260);this.checkBoxHexSend.Name = "checkBoxHexSend";this.checkBoxHexSend.Size = new System.Drawing.Size(100, 20);this.checkBoxHexSend.TabIndex = 9;this.checkBoxHexSend.Text = "十六进制发送";// // checkBoxHexReceive// this.checkBoxHexReceive.Location = new System.Drawing.Point(120, 260);this.checkBoxHexReceive.Name = "checkBoxHexReceive";this.checkBoxHexReceive.Size = new System.Drawing.Size(100, 20);this.checkBoxHexReceive.TabIndex = 10;this.checkBoxHexReceive.Text = "十六进制接收";// // checkBoxAutoSend// this.checkBoxAutoSend.Location = new System.Drawing.Point(220, 260);this.checkBoxAutoSend.Name = "checkBoxAutoSend";this.checkBoxAutoSend.Size = new System.Drawing.Size(80, 20);this.checkBoxAutoSend.TabIndex = 11;this.checkBoxAutoSend.Text = "自动发送";this.checkBoxAutoSend.CheckedChanged += new System.EventHandler(this.checkBoxAutoSend_CheckedChanged);// // numericUpDownInterval// this.numericUpDownInterval.Location = new System.Drawing.Point(310, 260);this.numericUpDownInterval.Maximum = new decimal(new int[] {10000,0,0,0});this.numericUpDownInterval.Minimum = new decimal(new int[] {100,0,0,0});this.numericUpDownInterval.Name = "numericUpDownInterval";this.numericUpDownInterval.Size = new System.Drawing.Size(60, 25);this.numericUpDownInterval.TabIndex = 12;this.numericUpDownInterval.Value = new decimal(new int[] {1000,0,0,0});// // label1// this.label1.Location = new System.Drawing.Point(20, 20);this.label1.Name = "label1";this.label1.Size = new System.Drawing.Size(50, 20);this.label1.TabIndex = 13;this.label1.Text = "串口:";// // label2// this.label2.Location = new System.Drawing.Point(20, 60);this.label2.Name = "label2";this.label2.Size = new System.Drawing.Size(50, 20);this.label2.TabIndex = 14;this.label2.Text = "波特率:";// // label3// this.label3.Location = new System.Drawing.Point(220, 20);this.label3.Name = "label3";this.label3.Size = new System.Drawing.Size(50, 20);this.label3.TabIndex = 15;this.label3.Text = "数据位:";// // label4// this.label4.Location = new System.Drawing.Point(220, 60);this.label4.Name = "label4";this.label4.Size = new System.Drawing.Size(50, 20);this.label4.TabIndex = 16;this.label4.Text = "校验位:";// // label5// this.label5.Location = new System.Drawing.Point(420, 20);this.label5.Name = "label5";this.label5.Size = new System.Drawing.Size(50, 20);this.label5.TabIndex = 17;this.label5.Text = "停止位:";// // label6// this.label6.Location = new System.Drawing.Point(20, 120);this.label6.Name = "label6";this.label6.Size = new System.Drawing.Size(50, 20);this.label6.TabIndex = 18;this.label6.Text = "发送:";// // label7// this.label7.Location = new System.Drawing.Point(20, 288);this.label7.Name = "label7";this.label7.Size = new System.Drawing.Size(50, 20);this.label7.TabIndex = 19;this.label7.Text = "接收:";// // Form1// this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;this.ClientSize = new System.Drawing.Size(600, 520);this.Controls.Add(this.comboBoxPort);this.Controls.Add(this.comboBoxBaudRate);this.Controls.Add(this.comboBoxDataBits);this.Controls.Add(this.comboBoxParity);this.Controls.Add(this.comboBoxStopBits);this.Controls.Add(this.buttonOpenClose);this.Controls.Add(this.textBoxSend);this.Controls.Add(this.textBoxReceive);this.Controls.Add(this.buttonSend);this.Controls.Add(this.checkBoxHexSend);this.Controls.Add(this.checkBoxHexReceive);this.Controls.Add(this.checkBoxAutoSend);this.Controls.Add(this.numericUpDownInterval);this.Controls.Add(this.label1);this.Controls.Add(this.label2);this.Controls.Add(this.label3);this.Controls.Add(this.label4);this.Controls.Add(this.label5);this.Controls.Add(this.label6);this.Controls.Add(this.label7);this.Name = "Form1";this.Text = "串口调试工具";((System.ComponentModel.ISupportInitialize)(this.numericUpDownInterval)).EndInit();this.ResumeLayout(false);this.PerformLayout();}}
}

From1.cs文件

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System;
using System.IO.Ports;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace _7_uart
{public partial class Form1 : Form{/*public Form1(){InitializeComponent();}*/public Form1(){InitializeComponent();InitializeSerialPort();RefreshPortList();// 定时刷新可用串口System.Windows.Forms.Timer timerRefreshPorts = new System.Windows.Forms.Timer();timerRefreshPorts.Interval = 1000;timerRefreshPorts.Tick += (s, e) => RefreshPortList();timerRefreshPorts.Start();}private void InitializeSerialPort(){serialPort.DataReceived += new SerialDataReceivedEventHandler(SerialPort_DataReceived);serialPort.ErrorReceived += new SerialErrorReceivedEventHandler(SerialPort_ErrorReceived);}private void RefreshPortList(){string currentSelection = comboBoxPort.SelectedItem?.ToString();comboBoxPort.Items.Clear();string[] ports = SerialPort.GetPortNames();comboBoxPort.Items.AddRange(ports);if (!string.IsNullOrEmpty(currentSelection) && comboBoxPort.Items.Contains(currentSelection)){comboBoxPort.SelectedItem = currentSelection;}else if (comboBoxPort.Items.Count > 0){comboBoxPort.SelectedIndex = 0;}}private void buttonOpenClose_Click(object sender, EventArgs e){if (serialPort.IsOpen){CloseSerialPort();}else{OpenSerialPort();}}private void OpenSerialPort(){if (comboBoxPort.SelectedItem == null){MessageBox.Show("请选择串口!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);return;}try{serialPort.PortName = comboBoxPort.SelectedItem.ToString();serialPort.BaudRate = int.Parse(comboBoxBaudRate.SelectedItem.ToString());serialPort.DataBits = int.Parse(comboBoxDataBits.SelectedItem.ToString());// 设置校验位switch (comboBoxParity.SelectedItem.ToString()){case "None": serialPort.Parity = Parity.None; break;case "Odd": serialPort.Parity = Parity.Odd; break;case "Even": serialPort.Parity = Parity.Even; break;case "Mark": serialPort.Parity = Parity.Mark; break;case "Space": serialPort.Parity = Parity.Space; break;}// 设置停止位switch (comboBoxStopBits.SelectedItem.ToString()){case "1": serialPort.StopBits = StopBits.One; break;case "1.5": serialPort.StopBits = StopBits.OnePointFive; break;case "2": serialPort.StopBits = StopBits.Two; break;}serialPort.Open();buttonOpenClose.Text = "关闭串口";comboBoxPort.Enabled = false;comboBoxBaudRate.Enabled = false;comboBoxDataBits.Enabled = false;comboBoxParity.Enabled = false;comboBoxStopBits.Enabled = false;}catch (Exception ex){MessageBox.Show($"打开串口失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);}}private void CloseSerialPort(){try{if (serialPort.IsOpen){serialPort.Close();}buttonOpenClose.Text = "打开串口";comboBoxPort.Enabled = true;comboBoxBaudRate.Enabled = true;comboBoxDataBits.Enabled = true;comboBoxParity.Enabled = true;comboBoxStopBits.Enabled = true;// 停止自动发送checkBoxAutoSend.Checked = false;}catch (Exception ex){MessageBox.Show($"关闭串口失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);}}private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e){try{int bytesToRead = serialPort.BytesToRead;byte[] buffer = new byte[bytesToRead];serialPort.Read(buffer, 0, bytesToRead);// 在UI线程中更新接收文本框this.Invoke(new Action(() => DisplayReceivedData(buffer)));}catch (Exception ex){this.Invoke(new Action(() =>MessageBox.Show($"接收数据错误:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error)));}}private void DisplayReceivedData(byte[] data){if (checkBoxHexReceive.Checked){// 十六进制显示string hexString = BitConverter.ToString(data).Replace("-", " ");textBoxReceive.AppendText(hexString + " ");}else{// ASCII显示string asciiString = Encoding.ASCII.GetString(data);textBoxReceive.AppendText(asciiString);}// 自动滚动到最新内容textBoxReceive.SelectionStart = textBoxReceive.Text.Length;textBoxReceive.ScrollToCaret();}private void SerialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e){this.Invoke(new Action(() =>textBoxReceive.AppendText($"[错误:{e.EventType}]\r\n")));}private void buttonSend_Click(object sender, EventArgs e){SendData();}private void SendData(){if (!serialPort.IsOpen){MessageBox.Show("请先打开串口!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);return;}if (string.IsNullOrEmpty(textBoxSend.Text)){MessageBox.Show("发送内容不能为空!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);return;}try{byte[] sendData;if (checkBoxHexSend.Checked){// 十六进制发送sendData = HexStringToByteArray(textBoxSend.Text);}else{// ASCII发送sendData = Encoding.ASCII.GetBytes(textBoxSend.Text);}serialPort.Write(sendData, 0, sendData.Length);}catch (Exception ex){MessageBox.Show($"发送数据失败:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);}}private byte[] HexStringToByteArray(string hex){hex = hex.Replace(" ", "").Replace("-", "").Replace("\r", "").Replace("\n", "").Replace("\t", "");if (hex.Length % 2 != 0){throw new ArgumentException("十六进制字符串长度必须为偶数");}byte[] bytes = new byte[hex.Length / 2];for (int i = 0; i < hex.Length; i += 2){string hexByte = hex.Substring(i, 2);bytes[i / 2] = Convert.ToByte(hexByte, 16);}return bytes;}private void checkBoxAutoSend_CheckedChanged(object sender, EventArgs e){if (checkBoxAutoSend.Checked){if (!serialPort.IsOpen){MessageBox.Show("请先打开串口!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);checkBoxAutoSend.Checked = false;return;}timerAutoSend.Interval = (int)numericUpDownInterval.Value;timerAutoSend.Tick += (s, args) => SendData();timerAutoSend.Start();}else{timerAutoSend.Stop();}numericUpDownInterval.Enabled = !checkBoxAutoSend.Checked;}protected override void OnFormClosing(FormClosingEventArgs e){if (serialPort.IsOpen){serialPort.Close();}base.OnFormClosing(e);}}
}

三、效果演示

http://www.dtcms.com/a/414225.html

相关文章:

  • 容器化安装新趋势:云原生到边缘计算
  • 【Linux】深入理解Linux的进程(一)
  • 【JAVA】从入门到放弃-03:IDEA、AI插件、工程结构
  • 网站如何做搜索引擎优化精准防恶意点击软件
  • 西安北郊做网站代理网点什么意思
  • 云原生之CNCF 是什么
  • LeetCode算法“无重复字符的最长子串”哈希表+滑动窗口+贪心
  • 使用 TypeScript 实现基于 pgvector 的 LLM 自动化测试用例
  • LeetCode-hot100——验证二叉搜索树
  • CentOS7安装部署K8s
  • 【无标题】使用 Playwright 实现跨 Chromium、Firefox、WebKit 浏览器自动化操作
  • 做网站能用思源黑体吗国内外网站网站
  • 基于Qt的跨平台Word文档导出器WordEx的设计与实现
  • LeetCode 0812.最大三角形面积:三角形面积公式考察
  • LeetCode热题100--994. 腐烂的橘子--中等
  • 杭州做网站优化wordpress整站加密
  • 用Spark+Django打造食物营养数据可视化分析系统
  • 个人用云计算学习笔记 --17(DNS 服务器)
  • 泛微 Ecology10 OA 系统介绍
  • 哪个网站可以直接做ppt上海网站免费制作
  • STM32CubeMX安装教程
  • 游戏引擎以及游戏开发
  • 使用Python实现自动编写Word全自动化系统
  • 用flash做的经典网站微信公众号制作平台
  • OpenAI正式推出GPT-5-Codex增强型AI编程助手,该工具专为软件工程师设计
  • SpringMVC 进阶:核心组件详解与参数绑定全攻略
  • SpringMVC 实战:整合 MyBatis 实现完整 CRUD
  • Interleaving-Reasoning-Generation - 交错推理生成技术
  • 【C++】:继承全面解析
  • 大良营销网站建设机构设计专业所需网站