使用C#设计串口调试助手
0赞不管是工业的控制系统,还是简单的民用系统,要做控制,都离不开协议,而要实现协议,在PC端需要上位机控制软件,当然,使用通用的串口调试助手也可以,不过需要一串一串指令输入,例如,输入cc 03 01 01 a1 0f eb aa表示做A处理,输入cc 03 02 01 a1 10 eb aa表示做B处理,很烦琐,有么有!!!如果自行设计上位机控制软件,两个Button,一个做A处理,一个做B处理,即可搞定,这样做相当的方便。
下面来介绍简单的串口通信软件设计,并介绍虚拟串口工具的使用。
我使用的软件为VS2010,串口虚拟工具版本为7.2.308。
1. VS2010中新建窗体应用程序
2. 添加serialPort组件,微软提供的该组件,方便创建serialPort对象,并集成了与serialPort相关的方法和属性,用起来非常方便。
3. 添加相关控件,设置相关属性包括:
(1) ComboBox:端口号(cbxPortName)、波特率(cbxBaud)
(2) Button:打开串口(btnComOpen)、串口发送(btnComSend)
(3) TextBox:发送框(tbxSend)、接收框(tbxRecv),设置这两个TextBox的 MultiLine属性为true。
(4) Label:端口号名(labelPortName)、波特率名(Labelbaud)、发送计数(sendCount)、接收计数(labelReceiveCount)
4. 在cbxBaud的Items属性中预设常用波特率
5. 添加响应事件
(1) 添加引用及初始化相关操作
1) 添加serialPort类引用
using System.IO.Ports;
2) 初始化
string[] str = SerialPort.GetPortNames();
if (str == null)
{
MessageBox.Show("本机没有串口!", "Error");
return;
}
Array.Sort(str);
cbxPortName.Items.AddRange(str);
(2) 串口打开事件
private void btnComOpen_Click(object sender, EventArgs e)
{
}
(3) 串口发送事件
private void btnComSend_Click(object sender, EventArgs e)
{
}
(4) 串口接收事件
private voi d serialPort1_Datareceived(object sender, SerialDataReceivedEventArgs e)
{
}
6. 调试
(1) 软件界面如下,界面非常简单,干净整洁。
(2) 使用虚拟串口工具,虚拟出一对串口,虚拟串口工具下载地址如下
https://pan.baidu.com/s/1c2FxtQC 下载后请参看说明文件,安装完成后先不要打开,使用vspdctl.dll文件覆盖安装目录内的文件即可完成破解。
(3) 开始测试
一端使用写的上位机,另一端使用串口调试助手。
串口调试助手发送一串16进制码,上位机接收,结果如下:
上位机发送一串16进制码,串口调试助手接收,结果如下:
这个上位机只是完成了简单的串口通信功能,后期再讲讲下位机、上位机进行串口数据解析,如何联系到应用协议,这样才有实际应用价值。
附上实际代码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO.Ports; namespace uartAssist { public partial class Form1 : Form { private StringBuilder builder = new StringBuilder(); //新建StringBuilder类对象,用来处理可变长度字符串 static int receiveCount = 0; static int sendCount = 0; public Form1() { InitializeComponent(); //获取本机串口并添加到cbxPortName中 string[] str = SerialPort.GetPortNames(); if (str == null) { MessageBox.Show("本机没有串口!", "Error"); return; } Array.Sort(str); cbxPortName.Items.AddRange(str); //添加响应事件 serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_Datareceived); } static int n = 0; static int m = 0; private void serialPort1_Datareceived(object sender, SerialDataReceivedEventArgs e) { n = serialPort1.BytesToRead; byte[] datareceive = new byte[n]; receiveCount += n; serialPort1.Read(datareceive, 0, n); builder.Remove(0, builder.Length); this.Invoke((EventHandler)(delegate { foreach (byte b in datareceive) { builder.Append(b.ToString("X2") + " "); } this.txtRecv.AppendText(builder.ToString()); labelReceiveCountNum.Text = receiveCount.ToString(); })); } private void btnComOpen_Click(object sender, EventArgs e) { if (serialPort1.IsOpen) { serialPort1.Close(); btnComOpen.Text = "打开"; } else { serialPort1.PortName = cbxPortName.Text; serialPort1.BaudRate = int.Parse(cbxBaud.Text); serialPort1.Parity = Parity.None; serialPort1.StopBits = StopBits.Two; try { serialPort1.Open(); btnComOpen.Text = "关闭"; } catch (Exception ex) { MessageBox.Show(ex.Message); } } } private void btnComSend_Click(object sender, EventArgs e) { try { string tbxRecvString = txtSend.Text.ToString(); string[] tbxRecvs = tbxRecvString.Split(' '); m = tbxRecvs.Length; byte[] frame = Array.ConvertAll(tbxRecvs, s => Convert.ToByte(s, 16)); serialPort1.Write(frame, 0, m); sendCount += m; labelSendCountNum.Text = sendCount.ToString(); } catch (System.Exception ex) { MessageBox.Show("发送错误:" + ex.Message); } } private void btnCountRst_Click(object sender, EventArgs e) { labelSendCountNum.Text = "0"; labelReceiveCountNum.Text = "0"; } } }