lemonHe

主要关注FPGA信号处理和数字图像处理技术,欢迎交流 邮箱:heliminlemon@163.com

使用C#设计串口调试助手

0
阅读(2707)

不管是工业的控制系统,还是简单的民用系统,要做控制,都离不开协议,而要实现协议,在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中新建窗体应用程序

blob.png

2. 添加serialPort组件,微软提供的该组件,方便创建serialPort对象,并集成了与serialPort相关的方法和属性,用起来非常方便。

blob.png

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属性中预设常用波特率

blob.png

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) 软件界面如下,界面非常简单,干净整洁。

blob.png

(2) 使用虚拟串口工具,虚拟出一对串口,虚拟串口工具下载地址如下

https://pan.baidu.com/s/1c2FxtQC下载后请参看说明文件,安装完成后先不要打开,使用vspdctl.dll文件覆盖安装目录内的文件即可完成破解。

blob.png

(3) 开始测试

一端使用写的上位机,另一端使用串口调试助手。

串口调试助手发送一串16进制码,上位机接收,结果如下:

blob.png

上位机发送一串16进制码,串口调试助手接收,结果如下:

blob.png

这个上位机只是完成了简单的串口通信功能,后期再讲讲下位机、上位机进行串口数据解析,如何联系到应用协议,这样才有实际应用价值。

附上实际代码:

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


Baidu
map