串口通信(4)-C#串口通信入门实例

本文通过实例讲解C#串口通信。

入门实例设计一个串口助手,能够很好的涵盖串口要点的使用。

目录

一、成品图

 二、界面文件

三、后台代码

四、实例中要点

一、成品图

如下:

实现的过程

创建winform项目,将Form1文件的名称改为MainForm,在主窗体中添加文本控件,选框控件,按钮等控件。以及SerialPort控件,该控件不在窗体中显示。

给控件更改名称

所有控件可以从文件大纲里面查看

设置控件的属性,添加事件。

SerialPort控件的属性如下,把读写的超时时间由默认-1改为1000。

 二、界面文件

 

MainForm.Designer.cs
namespace SerialPortDemo
{
    partial class MainForm
    {
        /// <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();
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.btnOpen = new System.Windows.Forms.Button();
            this.cmbParity = new System.Windows.Forms.ComboBox();
            this.cmbDataBits = new System.Windows.Forms.ComboBox();
            this.cmbStopBits = new System.Windows.Forms.ComboBox();
            this.cmbBaudRate = new System.Windows.Forms.ComboBox();
            this.cmbPortName = new System.Windows.Forms.ComboBox();
            this.label5 = new System.Windows.Forms.Label();
            this.label4 = new System.Windows.Forms.Label();
            this.label3 = new System.Windows.Forms.Label();
            this.label2 = new System.Windows.Forms.Label();
            this.label1 = new System.Windows.Forms.Label();
            this.spt = new System.IO.Ports.SerialPort(this.components);
            this.txtRead = new System.Windows.Forms.TextBox();
            this.chk16Read = new System.Windows.Forms.CheckBox();
            this.btnClearRead = new System.Windows.Forms.Button();
            this.btnSend = new System.Windows.Forms.Button();
            this.btnClearWrite = new System.Windows.Forms.Button();
            this.chk16Write = new System.Windows.Forms.CheckBox();
            this.txtWrite = new System.Windows.Forms.TextBox();
            this.groupBox2 = new System.Windows.Forms.GroupBox();
            this.groupBox3 = new System.Windows.Forms.GroupBox();
            this.label6 = new System.Windows.Forms.Label();
            this.chkReadAutoWrap = new System.Windows.Forms.CheckBox();
            this.chkWriteAutoWrap = new System.Windows.Forms.CheckBox();
            this.groupBox1.SuspendLayout();
            this.groupBox2.SuspendLayout();
            this.groupBox3.SuspendLayout();
            this.SuspendLayout();
            // 
            // groupBox1
            // 
            this.groupBox1.Controls.Add(this.btnOpen);
            this.groupBox1.Controls.Add(this.cmbParity);
            this.groupBox1.Controls.Add(this.cmbDataBits);
            this.groupBox1.Controls.Add(this.cmbStopBits);
            this.groupBox1.Controls.Add(this.cmbBaudRate);
            this.groupBox1.Controls.Add(this.cmbPortName);
            this.groupBox1.Controls.Add(this.label5);
            this.groupBox1.Controls.Add(this.label4);
            this.groupBox1.Controls.Add(this.label3);
            this.groupBox1.Controls.Add(this.label2);
            this.groupBox1.Controls.Add(this.label1);
            this.groupBox1.Location = new System.Drawing.Point(10, 13);
            this.groupBox1.Margin = new System.Windows.Forms.Padding(4);
            this.groupBox1.Name = "groupBox1";
            this.groupBox1.Padding = new System.Windows.Forms.Padding(4);
            this.groupBox1.Size = new System.Drawing.Size(212, 242);
            this.groupBox1.TabIndex = 0;
            this.groupBox1.TabStop = false;
            this.groupBox1.Text = "串口配置";
            // 
            // btnOpen
            // 
            this.btnOpen.Font = new System.Drawing.Font("微软雅黑", 10.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.btnOpen.Location = new System.Drawing.Point(11, 203);
            this.btnOpen.Margin = new System.Windows.Forms.Padding(0);
            this.btnOpen.Name = "btnOpen";
            this.btnOpen.Size = new System.Drawing.Size(187, 35);
            this.btnOpen.TabIndex = 11;
            this.btnOpen.Text = "打开串口";
            this.btnOpen.UseVisualStyleBackColor = true;
            this.btnOpen.Click += new System.EventHandler(this.btnOpen_Click);
            // 
            // cmbParity
            // 
            this.cmbParity.FormattingEnabled = true;
            this.cmbParity.Items.AddRange(new object[] {
            "无",
            "奇校验",
            "偶校验"});
            this.cmbParity.Location = new System.Drawing.Point(79, 167);
            this.cmbParity.Margin = new System.Windows.Forms.Padding(4);
            this.cmbParity.Name = "cmbParity";
            this.cmbParity.Size = new System.Drawing.Size(117, 23);
            this.cmbParity.TabIndex = 10;
            // 
            // cmbDataBits
            // 
            this.cmbDataBits.FormattingEnabled = true;
            this.cmbDataBits.Items.AddRange(new object[] {
            "8",
            "7",
            "6",
            "5"});
            this.cmbDataBits.Location = new System.Drawing.Point(79, 135);
            this.cmbDataBits.Margin = new System.Windows.Forms.Padding(4);
            this.cmbDataBits.Name = "cmbDataBits";
            this.cmbDataBits.Size = new System.Drawing.Size(117, 23);
            this.cmbDataBits.TabIndex = 9;
            // 
            // cmbStopBits
            // 
            this.cmbStopBits.FormattingEnabled = true;
            this.cmbStopBits.Items.AddRange(new object[] {
            "1",
            "1.5",
            "2"});
            this.cmbStopBits.Location = new System.Drawing.Point(79, 103);
            this.cmbStopBits.Margin = new System.Windows.Forms.Padding(4);
            this.cmbStopBits.Name = "cmbStopBits";
            this.cmbStopBits.Size = new System.Drawing.Size(117, 23);
            this.cmbStopBits.TabIndex = 8;
            // 
            // cmbBaudRate
            // 
            this.cmbBaudRate.FormattingEnabled = true;
            this.cmbBaudRate.Items.AddRange(new object[] {
            "1382400",
            "921600",
            "460800",
            "256000",
            "230400",
            "128000",
            "115200",
            "76800",
            "57600",
            "43000",
            "38400",
            "19200",
            "14400",
            "9600",
            "4800",
            "1200"});
            this.cmbBaudRate.Location = new System.Drawing.Point(79, 69);
            this.cmbBaudRate.Margin = new System.Windows.Forms.Padding(4);
            this.cmbBaudRate.Name = "cmbBaudRate";
            this.cmbBaudRate.Size = new System.Drawing.Size(117, 23);
            this.cmbBaudRate.TabIndex = 7;
            // 
            // cmbPortName
            // 
            this.cmbPortName.FormattingEnabled = true;
            this.cmbPortName.Location = new System.Drawing.Point(79, 38);
            this.cmbPortName.Margin = new System.Windows.Forms.Padding(4);
            this.cmbPortName.Name = "cmbPortName";
            this.cmbPortName.Size = new System.Drawing.Size(117, 23);
            this.cmbPortName.TabIndex = 6;
            // 
            // label5
            // 
            this.label5.AutoSize = true;
            this.label5.Location = new System.Drawing.Point(8, 170);
            this.label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
            this.label5.Name = "label5";
            this.label5.Size = new System.Drawing.Size(60, 15);
            this.label5.TabIndex = 4;
            this.label5.Text = "校验位:";
            // 
            // label4
            // 
            this.label4.AutoSize = true;
            this.label4.Location = new System.Drawing.Point(8, 106);
            this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
            this.label4.Name = "label4";
            this.label4.Size = new System.Drawing.Size(60, 15);
            this.label4.TabIndex = 3;
            this.label4.Text = "停止位:";
            // 
            // label3
            // 
            this.label3.AutoSize = true;
            this.label3.Location = new System.Drawing.Point(8, 138);
            this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(60, 15);
            this.label3.TabIndex = 2;
            this.label3.Text = "数据位:";
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(8, 72);
            this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(60, 15);
            this.label2.TabIndex = 1;
            this.label2.Text = "波特率:";
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(8, 41);
            this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(60, 15);
            this.label1.TabIndex = 0;
            this.label1.Text = "端口号:";
            // 
            // spt
            // 
            this.spt.ReadTimeout = 1000;
            this.spt.WriteTimeout = 1000;
            this.spt.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(this.spt_DataReceived);
            // 
            // txtRead
            // 
            this.txtRead.BackColor = System.Drawing.Color.White;
            this.txtRead.ForeColor = System.Drawing.Color.Black;
            this.txtRead.Location = new System.Drawing.Point(244, 38);
            this.txtRead.Margin = new System.Windows.Forms.Padding(4);
            this.txtRead.Multiline = true;
            this.txtRead.Name = "txtRead";
            this.txtRead.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
            this.txtRead.Size = new System.Drawing.Size(652, 280);
            this.txtRead.TabIndex = 1;
            // 
            // chk16Read
            // 
            this.chk16Read.AutoSize = true;
            this.chk16Read.Location = new System.Drawing.Point(28, 38);
            this.chk16Read.Margin = new System.Windows.Forms.Padding(4);
            this.chk16Read.Name = "chk16Read";
            this.chk16Read.Size = new System.Drawing.Size(105, 19);
            this.chk16Read.TabIndex = 2;
            this.chk16Read.Text = "16进制接收";
            this.chk16Read.UseVisualStyleBackColor = true;
            // 
            // btnClearRead
            // 
            this.btnClearRead.Font = new System.Drawing.Font("微软雅黑", 10.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.btnClearRead.Location = new System.Drawing.Point(244, 324);
            this.btnClearRead.Margin = new System.Windows.Forms.Padding(0);
            this.btnClearRead.Name = "btnClearRead";
            this.btnClearRead.Size = new System.Drawing.Size(120, 35);
            this.btnClearRead.TabIndex = 3;
            this.btnClearRead.Text = "清除接收";
            this.btnClearRead.UseVisualStyleBackColor = true;
            this.btnClearRead.Click += new System.EventHandler(this.btnClearRead_Click);
            // 
            // btnSend
            // 
            this.btnSend.Font = new System.Drawing.Font("微软雅黑", 10.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.btnSend.Location = new System.Drawing.Point(780, 543);
            this.btnSend.Margin = new System.Windows.Forms.Padding(0);
            this.btnSend.Name = "btnSend";
            this.btnSend.Size = new System.Drawing.Size(120, 35);
            this.btnSend.TabIndex = 5;
            this.btnSend.Text = "发送";
            this.btnSend.UseVisualStyleBackColor = true;
            this.btnSend.Click += new System.EventHandler(this.btnSend_Click);
            // 
            // btnClearWrite
            // 
            this.btnClearWrite.Font = new System.Drawing.Font("微软雅黑", 10.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.btnClearWrite.Location = new System.Drawing.Point(776, 328);
            this.btnClearWrite.Margin = new System.Windows.Forms.Padding(0);
            this.btnClearWrite.Name = "btnClearWrite";
            this.btnClearWrite.Size = new System.Drawing.Size(120, 35);
            this.btnClearWrite.TabIndex = 6;
            this.btnClearWrite.Text = "清除发送";
            this.btnClearWrite.UseVisualStyleBackColor = true;
            this.btnClearWrite.Click += new System.EventHandler(this.btnClearWrite_Click);
            // 
            // chk16Write
            // 
            this.chk16Write.AutoSize = true;
            this.chk16Write.Location = new System.Drawing.Point(28, 50);
            this.chk16Write.Margin = new System.Windows.Forms.Padding(4);
            this.chk16Write.Name = "chk16Write";
            this.chk16Write.Size = new System.Drawing.Size(105, 19);
            this.chk16Write.TabIndex = 7;
            this.chk16Write.Text = "16进制发送";
            this.chk16Write.UseVisualStyleBackColor = true;
            // 
            // txtWrite
            // 
            this.txtWrite.Location = new System.Drawing.Point(244, 367);
            this.txtWrite.Margin = new System.Windows.Forms.Padding(4);
            this.txtWrite.Multiline = true;
            this.txtWrite.Name = "txtWrite";
            this.txtWrite.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
            this.txtWrite.Size = new System.Drawing.Size(652, 170);
            this.txtWrite.TabIndex = 8;
            // 
            // groupBox2
            // 
            this.groupBox2.Controls.Add(this.chkWriteAutoWrap);
            this.groupBox2.Controls.Add(this.chk16Write);
            this.groupBox2.Location = new System.Drawing.Point(10, 411);
            this.groupBox2.Margin = new System.Windows.Forms.Padding(4);
            this.groupBox2.Name = "groupBox2";
            this.groupBox2.Padding = new System.Windows.Forms.Padding(4);
            this.groupBox2.Size = new System.Drawing.Size(221, 162);
            this.groupBox2.TabIndex = 9;
            this.groupBox2.TabStop = false;
            this.groupBox2.Text = "发送设置";
            // 
            // groupBox3
            // 
            this.groupBox3.Controls.Add(this.chkReadAutoWrap);
            this.groupBox3.Controls.Add(this.chk16Read);
            this.groupBox3.Location = new System.Drawing.Point(10, 263);
            this.groupBox3.Name = "groupBox3";
            this.groupBox3.Size = new System.Drawing.Size(212, 140);
            this.groupBox3.TabIndex = 10;
            this.groupBox3.TabStop = false;
            this.groupBox3.Text = "接收设置";
            // 
            // label6
            // 
            this.label6.AutoSize = true;
            this.label6.Font = new System.Drawing.Font("微软雅黑", 10.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.label6.Location = new System.Drawing.Point(244, 7);
            this.label6.Name = "label6";
            this.label6.Size = new System.Drawing.Size(88, 25);
            this.label6.TabIndex = 11;
            this.label6.Text = "数据接收";
            // 
            // chkReadAutoWrap
            // 
            this.chkReadAutoWrap.AutoSize = true;
            this.chkReadAutoWrap.Location = new System.Drawing.Point(28, 71);
            this.chkReadAutoWrap.Margin = new System.Windows.Forms.Padding(4);
            this.chkReadAutoWrap.Name = "chkReadAutoWrap";
            this.chkReadAutoWrap.Size = new System.Drawing.Size(149, 19);
            this.chkReadAutoWrap.TabIndex = 3;
            this.chkReadAutoWrap.Text = "自动添加回车换行";
            this.chkReadAutoWrap.UseVisualStyleBackColor = true;
            // 
            // chkWriteAutoWrap
            // 
            this.chkWriteAutoWrap.AutoSize = true;
            this.chkWriteAutoWrap.Location = new System.Drawing.Point(28, 93);
            this.chkWriteAutoWrap.Margin = new System.Windows.Forms.Padding(4);
            this.chkWriteAutoWrap.Name = "chkWriteAutoWrap";
            this.chkWriteAutoWrap.Size = new System.Drawing.Size(149, 19);
            this.chkWriteAutoWrap.TabIndex = 8;
            this.chkWriteAutoWrap.Text = "自动添加回车换行";
            this.chkWriteAutoWrap.UseVisualStyleBackColor = true;
            // 
            // MainForm
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(919, 586);
            this.Controls.Add(this.label6);
            this.Controls.Add(this.groupBox3);
            this.Controls.Add(this.btnClearWrite);
            this.Controls.Add(this.btnSend);
            this.Controls.Add(this.groupBox2);
            this.Controls.Add(this.txtWrite);
            this.Controls.Add(this.btnClearRead);
            this.Controls.Add(this.txtRead);
            this.Controls.Add(this.groupBox1);
            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
            this.Margin = new System.Windows.Forms.Padding(4);
            this.MinimumSize = new System.Drawing.Size(841, 559);
            this.Name = "MainForm";
            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
            this.Text = "串口助手";
            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing);
            this.Load += new System.EventHandler(this.MainForm_Load);
            this.groupBox1.ResumeLayout(false);
            this.groupBox1.PerformLayout();
            this.groupBox2.ResumeLayout(false);
            this.groupBox2.PerformLayout();
            this.groupBox3.ResumeLayout(false);
            this.groupBox3.PerformLayout();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.GroupBox groupBox1;
        private System.Windows.Forms.Label label4;
        private System.Windows.Forms.Label label3;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.Label label5;
        private System.Windows.Forms.Button btnOpen;
        private System.Windows.Forms.ComboBox cmbParity;
        private System.Windows.Forms.ComboBox cmbDataBits;
        private System.Windows.Forms.ComboBox cmbStopBits;
        private System.Windows.Forms.ComboBox cmbBaudRate;
        private System.Windows.Forms.ComboBox cmbPortName;
        private System.IO.Ports.SerialPort spt;
        private System.Windows.Forms.TextBox txtRead;
        private System.Windows.Forms.CheckBox chk16Read;
        private System.Windows.Forms.Button btnClearRead;
        private System.Windows.Forms.Button btnSend;
        private System.Windows.Forms.Button btnClearWrite;
        private System.Windows.Forms.CheckBox chk16Write;
        private System.Windows.Forms.TextBox txtWrite;
        private System.Windows.Forms.GroupBox groupBox2;
        private System.Windows.Forms.GroupBox groupBox3;
        private System.Windows.Forms.Label label6;
        private System.Windows.Forms.CheckBox chkReadAutoWrap;
        private System.Windows.Forms.CheckBox chkWriteAutoWrap;
    }
}

三、后台代码

using System;
using System.IO.Ports;
using System.Text;
using System.Windows.Forms;

namespace SerialPortDemo
{
    public partial class MainForm : Form
    {
        string serialPortName;
        bool bListening = false;//是否没有执行完invoke相关操作 (串口防死锁)
        bool bClosing = false;//是否正在关闭串口,执行Application.DoEvents,并阻止再次invoke 
        public MainForm()
        {
            InitializeComponent();
        }
        //窗体加载
        private void MainForm_Load(object sender, EventArgs e)
        {
            //获取当前计算机的串行端口名的数组
            string[] ports = SerialPort.GetPortNames();
            //使用 System.Array 中每个元素的 System.IComparable`1 泛型接口实现,对整个 System.Array 中的元素进行排序。
            Array.Sort(ports);
            //添加到显示列表
            cmbPortName.Items.AddRange(ports);
            cmbPortName.SelectedIndex = cmbPortName.Items.Count > 0 ? 0 : -1;       //如果里面有数据,显示第0个
            //显示默认的显示
            cmbBaudRate.Text = "9600"; //波特率:9600
            cmbStopBits.Text = "1";//默认停止位:1
            cmbDataBits.Text = "8";//默认数据位:8
            cmbParity.Text = "无";//默认奇偶校验位:无
        }
        //处理Windows消息 监听串口硬件的变化
        protected override void WndProc(ref Message m)
        {
            //设备改变
            if (m.Msg == 0x0219)
            {
                //USB串口拔出
                if (m.WParam.ToInt32() == 0x8004)           //usb串口
                {
                    string[] ports = System.IO.Ports.SerialPort.GetPortNames();     //重新获取串口
                    cmbPortName.Items.Clear();                //清除comboBox里面的数据
                    cmbPortName.Items.AddRange(ports);        //给comboBox1添加数据
                    if (btnOpen.Text == "关闭串口")         //用户打开过串口
                    {
                        //如果串行端口已打开,则为 true;否则为 false。 默认值为 false。
                        if (!spt.IsOpen)
                        {
                            btnOpen.Text = "打开串口";
                            //释放由 System.ComponentModel.Component 使用的所有资源。
                            spt.Dispose();
                            cmbPortName.SelectedIndex = cmbPortName.Items.Count > 0 ? 0 : -1;   //显示获取的第一个串口号
                        }
                        else
                        {
                            cmbPortName.Text = serialPortName;
                        }
                    }
                    else
                    {
                        cmbPortName.SelectedIndex = cmbPortName.Items.Count > 0 ? 0 : -1;       //显示获取的第一个串口号
                    }
                }
                //USB串口连上
                else if (m.WParam.ToInt32() == 0x8000)
                {
                    string[] ports = System.IO.Ports.SerialPort.GetPortNames();
                    cmbPortName.Items.Clear();
                    cmbPortName.Items.AddRange(ports);
                    if (btnOpen.Text == "关闭串口")
                    {
                        cmbPortName.Text = serialPortName;
                    }
                    else
                    {
                        cmbPortName.SelectedIndex = cmbPortName.Items.Count > 0 ? 0 : -1;   //显示获取的第一个串口号
                    }
                }
            }
            base.WndProc(ref m);
        }
        /// <字节数组转16进制字符串>
        /// <param name="bytes"></param>
        /// <returns> String 16进制显示形式</returns>
        public static string byteToHexStr(byte[] bytes)
        {
            string returnStr = "";
            try
            {
                if (bytes != null)
                {
                    for (int i = 0; i < bytes.Length; i++)
                    {
                        returnStr += bytes[i].ToString("X2");
                        returnStr += " ";                       //两个16进制用空格隔开,方便看数据
                    }
                }
                return returnStr;
            }
            catch (Exception)
            {
                return returnStr;
            }
        }
        /// <summary>
        ///  字符串转16进制格式,不够自动前面补零
        /// </summary>
        /// <param name="hexString"></param>
        /// <returns></returns>
        private static byte[] strToToHexByte(String hexString)
        {
            int i;
            hexString = hexString.Replace(" ", "");//清除空格         
            if ((hexString.Length % 2) != 0)//奇数个                
            {
                byte[] returnBytes = new byte[(hexString.Length + 1) / 2];
                try
                {
                    for (i = 0; i < (hexString.Length - 1) / 2; i++)
                    {
                        returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
                    }
                    returnBytes[returnBytes.Length - 1] = Convert.ToByte(hexString.Substring(hexString.Length - 1, 1).PadLeft(2, '0'), 16);
                }
                catch
                {
                    MessageBox.Show("含有非16进制字符", "提示");
                    return null;
                }
                return returnBytes;
            }
            else
            {
                byte[] returnBytes = new byte[(hexString.Length) / 2];
                try
                {
                    for (i = 0; i < returnBytes.Length; i++)
                    {
                        returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
                    }
                }
                catch
                {
                    MessageBox.Show("含有非16进制字符", "提示");
                    return null;
                }
                return returnBytes;
            }
        }
        //打开或关闭
        private void btnOpen_Click(object sender, EventArgs e)
        {
            if (btnOpen.Text == "打开串口")                             //如果按钮显示的是打开
            {
                try                                                     //防止意外错误
                {
                    spt.PortName = cmbPortName.Text;              //获取comboBox1要打开的串口号
                    serialPortName = cmbPortName.Text;
                    spt.BaudRate = int.Parse(cmbBaudRate.Text);   //获取comboBox2选择的波特率
                    spt.DataBits = int.Parse(cmbDataBits.Text);   //设置数据位
                    /*设置停止位*/
                    if (cmbStopBits.Text == "1")
                    {
                        spt.StopBits = StopBits.One;
                    }
                    else if (cmbStopBits.Text == "1.5")
                    {
                        spt.StopBits = StopBits.OnePointFive;
                    }
                    else if (cmbStopBits.Text == "2")
                    {
                        spt.StopBits = StopBits.Two;
                    }
                    /*设置奇偶校验*/
                    if (cmbParity.Text == "无")
                    {
                        spt.Parity = Parity.None;
                    }
                    else if (cmbParity.Text == "奇校验")
                    {
                        spt.Parity = Parity.Odd;
                    }
                    else if (cmbParity.Text == "偶校验")
                    {
                        spt.Parity = Parity.Even;
                    }
                    //打开串口
                    try
                    {
                        spt.Open();
                    }
                    catch
                    {

                    }
                    btnOpen.Text = "关闭串口";//按钮显示关闭串口
                    cmbPortName.Enabled = false;
                    cmbBaudRate.Enabled = false;
                    cmbStopBits.Enabled = false;
                    cmbDataBits.Enabled = false;
                    cmbParity.Enabled = false;
                }
                catch (Exception err)
                {
                    MessageBox.Show("打开失败" + err.ToString(), "提示!");//对话框显示打开失败
                }
            }
            else
            {
                //关闭串口
                try
                {
                    spt.Close();
                }
                catch (Exception)
                {

                }
                btnOpen.Text = "打开串口";  //按钮显示打开
                cmbPortName.Enabled = true;
                cmbBaudRate.Enabled = true;
                cmbStopBits.Enabled = true;
                cmbDataBits.Enabled = true;
                cmbParity.Enabled = true;
            }
        }
        //串口接收事件
        private void spt_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if (bClosing == true)
            {
                return;
            }
            bListening = true;
            int len = spt.BytesToRead;  //获取可以读取的字节数
            byte[] buff = new byte[len];        //创建缓存数据数组
                                                // 摘要:
                                                //     从 System.IO.Ports.SerialPort 输入缓冲区读取一些字节并将那些字节写入字节数组中指定的偏移量处。
                                                //
                                                // 参数:
                                                //   buffer:
                                                //     将输入写入到其中的字节数组。
                                                //
                                                //   offset:
                                                //     要写入字节的 buffer 中的偏移量。
                                                //
                                                //   count:
                                                //     最多读取的字节数。 如果 count 大于输入缓冲区中的字节数,则读取较少的字节。
                                                //
                                                // 返回结果:
                                                //     读取的字节数。
            spt.Read(buff, 0, len);
            //C# 3.0以后代替委托的新方法
            Invoke((new Action(() =>
            {
                if (chk16Read.Checked)          //16进制显示
                {
                    if (chkReadAutoWrap.Checked)
                    {
                        txtRead.AppendText(DateTime.Now.ToString() + ":" + byteToHexStr(buff) + "\r\n");
                    }
                    else
                    {
                        txtRead.AppendText(DateTime.Now.ToString() + ":" + byteToHexStr(buff));
                    }
                }
                else
                {
                    if (chkReadAutoWrap.Checked)
                    {
                        txtRead.AppendText(DateTime.Now.ToString() + ":" + Encoding.Default.GetString(buff) + "\r\n");
                    }
                    else
                    {
                        txtRead.AppendText(DateTime.Now.ToString() + ":" + Encoding.Default.GetString(buff));
                    }
                }
                
            })));
            bListening = false;//用完了,主线程可以关闭串口了。 
        }
        //清除接收
        private void btnClearRead_Click(object sender, EventArgs e)
        {
            txtRead.Clear();
        }
        //发送
        private void btnSend_Click(object sender, EventArgs e)
        {
            if (spt.IsOpen == false)
            {
                MessageBox.Show("串口未打开!");
                return;
            }
            string str = txtWrite.Text.ToString();//获取发送文本框里面的数据
            if (chkWriteAutoWrap.Checked == true)
            {
                str += "\r\n";
            }
            try
            {
                if (str.Length > 0)
                {
                    if (chk16Write.Checked)              //16进制发送
                    {
                        byte[] byt = strToToHexByte(str);
                        // 摘要:
                        //     使用缓冲区中的数据将指定数量的字节写入串行端口。
                        //
                        // 参数:
                        //   buffer:
                        //     包含要写入端口的数据的字节数组。
                        //
                        //   offset:
                        //     buffer 参数中从零开始的字节偏移量,从此处开始将字节复制到端口。
                        //
                        //   count:
                        //     要写入的字节数。
                        spt.Write(byt, 0, byt.Length);
                    }
                    else
                    {
                        //将指定的字符串写入串行端口。
                        spt.Write(str);
                    }
                }
            }
            catch (Exception)
            {

            }
        }
        //清除发送
        private void btnClearWrite_Click(object sender, EventArgs e)
        {
            txtWrite.Clear();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            bClosing = true; // 根据当前串口对象,来判断操作  
            while (bListening == true)
            {
                Application.DoEvents();
            }

            try
            {
                if (spt.IsOpen)
                {
                    spt.DiscardInBuffer();
                    spt.DiscardOutBuffer();
                    //取消订阅事件  防止又来了数据要处理,造成状态栏显示数据时访问不存在的控件的问题
                    spt.DataReceived -= new SerialDataReceivedEventHandler(spt_DataReceived);
                    spt.Close();
                }
            }
            catch
            {

            }

        }
    }
}

四、实例中要点

如下:

1、串口的参数设置

2、串口名称的刷新,通过重写消息函数,监听的USB的变化,更新电脑的端口变化。

3、打开和关闭串口尽量判定串口是否打开后在进行操作。

4、串口发送前判定是否已经打开。

5、串口的读取Read和发送Write函数的应用。

6、字符串和16进制的转换以及16进制显示的处理。

7、窗体的关闭与串口处理线程的处理,通过增加标志位进行互斥处理,保证每次关闭都能处理完毕后在关闭,防止卡死。

8、串口接收事件是独立于UI线程的单独线程,因此如果在串口接收线程下刷新UI控件需要用到异步执行,本文使用 Invoke进行处理。

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/243756.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Conda 使用教程大全来啦

什么是 Conda&#xff1f; Conda 是一款功能强大的软件包管理器和环境管理器&#xff0c;您可以在 Windows 的 Anaconda 提示符或 macOS 或 Linux 的终端窗口中使用命令行命令 Conda 可以快速安装、运行和更新软件包及相关依赖项。Conda 可以在本地计算机上创建、保存、加载和…

ubuntu22.04 docker安装ES8

创建es的网络 docker network create elastic安装运行es docker run --name es01 --net elastic -p 9200:9200 -e ES_JAVA_OPTS"-Xms1024m -Xmx1024m" -idt elasticsearch:8.2.2检查是否安装成功 sunyuhuasunyuhua-HKF-WXX:~$ docker ps CONTAINER ID IMAGE …

2023陇剑杯线上线下赛数据分析

好久没打过比赛了&#xff0c;对于这种偏蓝方的比赛我还是很喜欢 本文首发于&#xff1a;先知社区&#xff1a;https://xz.aliyun.com/t/13177 HW hard web_1 题目内容&#xff1a;服务器开放了哪些端口&#xff0c;请按照端口大小顺序提交答案&#xff0c;并以英文逗号隔开(如…

UE虚幻引擎项目更改名字怎么操作?

首先找到项目目录&#xff0c;直接更改项目程序的名字&#xff0c;其次点击项目程序右击使用文本打开&#xff0c;然后将Modules模块中的内容删除即可&#xff0c;然后运行程序就好啦&#xff01;

【LeetCode刷题】--172.阶乘后的零

172.阶乘后的零 方法&#xff1a; class Solution {public int trailingZeroes(int n) {int ans 0;for(int i 5;i<n;i5){for(int x i; x % 50; x/5){ans;}}return ans;} }进一步优化&#xff1a; class Solution {public int trailingZeroes(int n) {int ans 0;while (n…

主动学习与弱监督学习

人工智能数据的获取没有想象中的那么简单&#xff0c;虽然我们早已身处大数据的浪潮下&#xff0c;很多公司在获取数据的大浪中翻滚却始终没有找到一个合适的获取数据的渠道。很多情况下&#xff0c;获取高质量的人工智能数据需要消耗大量的人力、时间、金钱&#xff0c;但是对…

【移动通讯】【MIMO】[P1]【科普篇】

前言&#xff1a; 前面几个月把CA 的技术总体复盘了一下,下面一段时间 主要结合各国一些MIMO 技术的文档,复盘一下MIMO. 这篇主要参考华为&#xff1a; info.support.huawei.com MIMO 技术使用多天线发送和接受信号。主要应用在WIFI 手机通讯等领域. 这种技术提高了系统容量&…

mysql的负向条件查询会不会使用索引

mysql的负向条件查询&#xff0c;例如not in&#xff0c;会不会使用索引&#xff1f; 其实&#xff0c;mysql还是会尽量利用索引。如果查询的列上有索引&#xff0c;并且索引能够覆盖查询所需的列&#xff0c;那么mysql可能会使用索引来获取结果&#xff0c;而不是进行全表扫描…

解决设备能耗管理问题,易点易动来帮忙!

设备能耗管理是现代企业可持续发展的重要环节&#xff0c;然而&#xff0c;许多企业在设备能耗管理方面面临一系列问题&#xff1a; 能耗数据收集困难&#xff1a;企业需要监控和管理大量设备的能耗情况&#xff0c;但传统的手动方式收集能耗数据耗时耗力&#xff0c;无法实时获…

C语言-WIN32API介绍

Windows API 从第一个32位的Windows开始就出现了&#xff0c;就叫做Win32API.它是一个纯C的函数库&#xff0c;就和C标准库一样&#xff0c;使你可以写Windows应用程序过去很多Windows程序是用这个方式做出来的 main()? main()成为C语言的入口函数其实和C语言本身无关&…

Java中常见需要重写equals方法的类

目录 导言 一、自定义类 二、集合类 三、字符串类 四、数组类 五、枚举类 结论 导言 在Java编程中&#xff0c;equals方法是用来比较两个对象是否相等的关键方法之一。然而&#xff0c;在某些情况下&#xff0c;Java提供的默认equals方法可能无法满足我们的需求。因此&a…

《地理信息系统原理》笔记/期末复习资料(11. GIS的输出与地图可视化)

目录 11. GIS的输出与地图可视化 11.1. GIS的输出 11.1.1. 输出方式 11.1.2. GIS的图形输出设备 11.2. 地图符号 11.2.1. 地图符号的实质 11.2.2. 地图符号的分类 11.2.3. 地图符号的设计要求 11.3. 专题信息表达 11.3.1. 专题地图的基本概念 11.3.2. 专题地图的表示…

Esxi虚拟机无法添加加密狗处理

原创作者&#xff1a;运维工程师 谢晋 Esxi虚拟机无法添加加密狗处理 前提纪要添加直通模式 前提纪要 客户将加密狗插在Esxi主机上&#xff0c;并给虚拟机添加USB控制器再添加加密狗设备&#xff0c;但添加时候报错无法识别加密狗&#xff08;如下图&#xff09;&#xff0…

一个文件下png,jpg,jpeg,bmp,xml,json,txt文件名称排序命名

#utf-8 #authors 会飞的渔WZH #time:2023-12-13 import os# 要修改的图像所在的文件夹路径 root_path rD:\images\lines2\3 # 要修改的图像所在的文件夹路径filelist os.listdir(root_path) #遍历文件夹 print(len(filelist)) i0for item in filelist:if item.endswith(.…

HarmonyOS应用开发初体验

9月25日华为秋季全场景新品发布会上&#xff0c;余承东宣布&#xff0c;全面启动鸿蒙原生应用&#xff0c;HarmonyOS NEXT开发者预览版将在2024年第一季度面向开发者开放。 最近鸿蒙开发可谓是火得一塌糊涂&#xff0c;各大培训平台都开设了鸿蒙开发课程。美团发布了鸿蒙高级工…

_try_finally原理探究后续

入口程序的最后一道防线 这里调用mainCRTStartup()&#xff0c;然后调用入口程序 相当于这里才是一个进程开始执行的地方 这里有一个call调用&#xff0c;跟进去看看 发现有修改fs:[0]的操作&#xff0c;这里就相当于编译器为我们注册了一个异常处理函数 这里到kernel32.dll里面…

OpenCV-Python16:图像平滑操作

目录 图像平滑基础 本文目标 2D卷积 图像模糊&#xff08;图像平滑&#xff09; 平均模糊 高斯模糊 中值模糊 双边滤波 图像平滑基础 在尽量保留图像原有信息的情况下&#xff0c;过滤掉图像内部的噪声&#xff0c;这一过程称为对图像的平滑处理&#xff0c;所得的图像…

leetcode--3. 无重复字符的最长子串[滑动窗口\哈希表 c++]

原题 &#xff1a; 3. 无重复字符的最长子串 - 力扣&#xff08;LeetCode&#xff09; 题目解析&#xff1a; 最长子串可以用滑动窗口解决&#xff0c;无重复字符可以使用哈希表解决。 算法原理&#xff1a; 滑动窗口哈希表 哈希表作为一个数组存放每个字符出现的次数。 …

C#云LIS系统源码 B/S架构,SaaS模式,可扩展性强

基于B/S架构的云LIS检验系统源码&#xff0c;整个系统的运行基于WEB层面&#xff0c;只需要在对应的工作台安装一个浏览器软件有外网即可访问。全套系统采用云部署模式&#xff0c;部署一套可支持多家医院检验科共同使用。 采用.Net Core新的技术框架、DEV报表、前端js封装、分…

数学learning

目录 移动平均 简单移动平均 加权移动平均 指数移动平均 矩阵求导 矩阵对标量求导 Matrix-by-scalar 标量对矩阵求导 Scalar-by-matrix 参考博客 移动平均 优化算法里面会涉及到一个知识点&#xff1a;指数移动平均。 但是为了知识的完整性&#xff0c;这里会将常见的移动…