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

news2024/11/17 8:19:21

本文通过实例讲解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进行处理。

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【LeetCode刷题】-- 171.EXcel表列序号

171.EXcel表列序号 方法&#xff1a;进制转换 class Solution {public int titleToNumber(String columnTitle) {//进制转换int number 0;int mul 1;for(int i columnTitle.length()-1;i>0;i--){int k columnTitle.charAt(i) - A 1;number mul * k;mul * 26;}return …

1+X大数据平台运维职业技能等级证书中级

该部分是选择题部分&#xff0c;实操题在主页的另一篇文章 考试名称&#xff1a;“1X”大数据平台运维职业技能等级证书&#xff08;中级&#xff09; 1X 大数据平台运维中级测试题一、单选题 以下哪种情况容易引发 HDFS 负载不均问题&#xff1f;&#xff08; C&#xff09…

解决高风险代码:Unreleased Resource: Streams

Abstract 程序可能无法成功释放某一项系统资源。 Explanation 程序可能无法成功释放某一项系统资源。 资源泄露至少有两种常见的原因&#xff1a; &#xff0d; 错误状况及其他异常情况。 &#xff0d; 未明确程序的哪一部份负责释放资源。 大部分 Unreleased Resource 问题只…

定制软件开发的 5 个挑战

对于大公司来说&#xff0c;定制软件开发就像是眼中钉。无论您是要创建内部使用的工具、自动化手动流程还是推出新产品&#xff0c;从头开始构建它历来都是昂贵且危险的。花钱购买领先的现成解决方案之一&#xff0c;却不得不花费更多的时间和金钱对其进行定制来完成工作&#…

Vue 工作开发小技巧

一、汇总 ​ 本博客&#xff0c;记录了一些Vue在日常开发工作中比较实用的小技巧&#xff0c;后续会陆续添加更新。 ​ 1、利用Sass的:global定义全局样式。 ​ 2、在<style>内部使用v-bind给CSS属性绑定属性值。 ​ 3、父子组件传值时&#xff0c;使用.sync修饰符后…

【抄作业】ubuntu完全卸载CUDA,彻底卸载cuda,卸载不同版本的cuda,cuda不同版本的卸载方法

卸载的实现方法 如何正确、完全的卸载cuda呢&#xff1f; 其实cuda安装时就已经准备好了卸载的接口&#xff0c;卸载程序在/usr/local/cuda-xx.x/bin下&#xff0c;需要注意的是cuda10.0及之前的版本卸载程序名为uninstall_cuda_xx.x.pl&#xff0c;而cuda10.1及之后的版本卸…

leetcode 69. x 的平方根(优质解法)

代码&#xff1a; class Solution {public int mySqrt(int x) {long left0;long rightx;while (left<right){long midleft(right-left1)/2;//注意乘法操作和加法操作都很容易发生溢出if(mid*mid<x){leftmid;}else {rightmid-1;}}return (int)left;} } 题解&#xff1a;…

MES系统物料计划协同:全面解析与应用

一、MES系统物料计划协同概述 MES系统物料计划协同是指通过MES系统对物料计划进行统一管理和协调&#xff0c;确保生产计划的顺利进行。通过将物料需求、采购、库存、生产和配送等环节进行有效集成&#xff0c;实现供应链的优化。这种协同方式有助于提高供应链的透明度和协同性…

[OpenWrt]RAX3000一根线实现上网和看IPTV

背景&#xff1a; 1.我家电信宽带IPTV 2.入户光猫&#xff0c;桥接模式 3.光猫划分vlan&#xff0c;将上网信号IPTV信号&#xff0c;通过lan口&#xff08;问客服要光猫超级管理员密码&#xff0c;具体教程需要自行查阅&#xff0c;关键是要设置iptv在客户侧的vlan id&#…

【抄作业】ImportError :cannot import name xxxxxx ,原博主Activewaste

前情介绍 网上关于这种问题的解决方案一大堆&#xff0c;但是绝大多数都是不适用&#xff0c;或者说解决不了问题&#xff0c;我根据别人所遇到的和我自己遇到的&#xff0c;对这个问题整理了一下&#xff0c;希望能解决这个问题。 问题分析 一、缺少这个module或者func或者p…

java springboot+jsoup写一段爬虫脚本 将指定地址的 图片链接 文本 超链接地址存入自己的属性类对象中

首先 还是最基本的 要在 pom.xml 引入依赖 <dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.14.1</version> </dependency>然后 我们可以在项目中创建一个属性类 我这里就叫 WebContent了…

ArkTS组件通信

父子通信 情况一&#xff1a;子组件只展示父组件中的状态 父组件通过 State修饰符 定义变量&#xff0c;子组件通过 Prop修饰符 获取变量。 Prop是 「单向传递」&#xff0c;父组件将变量「拷贝」一份交给子组件使用&#xff0c;子组件不可修改变量。 父组件 // 声明变量 …

Debian openmediavault 自建Nas系统共享,raid5与btrfs文件系统无损原数据扩容

一、适用环境 1、企业自有物理专业服务器&#xff0c;一些敏感数据不外流时&#xff0c;使用openmediavault自建NAS系统&#xff1b; 2、在虚拟化环境中自建NAS系统&#xff0c;用于内网办公&#xff0c;或出差外网办公时&#xff0c;企业内的文件共享&#xff1b; 3、虚拟化环…

大模型时代-让AI自己开发自己

一、前言 AI能自己开发自己或者开发和一个很像自己的东西吗&#xff1f;显然是可以的&#xff01;因为AI模型的算法&#xff0c;基本就是学习和递归 二、大模型的算法实现例子 本例子就是通过AI模型来写 大模型的实现通常涉及到深度学习框架和大量的计算资源。具体的算法代…

RocketMQ源码 Broker-PullRequestHoldService 长轮询消息拉取组件源码分析

前言 PullRequestHoldService 继承了ServiceThread类&#xff0c;它本身是一个线程&#xff0c;以后台方式无线循环运行&#xff0c;支持长轮询&#xff08;默认5秒&#xff09;和短轮询&#xff08;默认1秒&#xff09;两种方式&#xff08;CountDownlatch 方式控制&#xff…

在HTML中如何设置音频和视频?

目录 一、设置音频二、设置视频 一、设置音频 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Document</title> </head> <body> <!-- controls:控制播放暂停的按钮autop…

【Jmeter】Jmeter基础4-Jmeter元件介绍之监听器

2.4、监听器 监听器主要用于收集、统计、查看和分析结果。 2.4.1、察看结果树 作用&#xff1a;查看取样器请求和响应结果&#xff0c;包括消息头&#xff0c;请求的数据&#xff0c;响应的数据等。一般在调试时才用&#xff0c;在实际运行压测时建议禁用&#xff0c;因为大量…

TikTok科技趋势:平台如何引领数字社交革命?

TikTok作为一款颠覆性的短视频应用&#xff0c;不仅改变了用户的娱乐方式&#xff0c;更在数字社交领域引领了一场革命。本文将深入探讨TikTok在科技趋势方面的引领作用&#xff0c;分析其在数字社交革命中的关键角色&#xff0c;以及通过技术创新如何不断满足用户需求&#xf…

element-ui以服务方式调用loading,自定义修改icon

一、以服务的方式调用Loading 除了常用的v-loading、this.$loading我们还可以以服务的方式调用。主要有以下步骤 引入Loading服务 import { Loading } from element-ui;在需要时调用 Loading.service(options);其中 options 参数为 Loading 的配置项&#xff0c;具体见下表…

2023 亚马逊云科技 re:Invent 大会探秘:Aurora 无限数据库的突破性应用

文章目录 一、前言二、Amazon Aurora 无限数据库2.1 亚马逊云科技数据库产品发展历程2.2 什么是 Amazon Aurora Limitless Database&#xff08;无限数据库&#xff09;2.3 Amazon Aurora Limitless Database 设计架构2.4 Amazon Aurora Limitless Database 分片功能2.5 使用 A…