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