使用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";
}
}
}
