c#利用虚拟串口工具进行串口通信数据的发送和接收
程序员文章站
2022-06-02 22:49:17
...
原文:我的个人博客
串口通信
串口通信(Serial Communications)的概念非常简单,串口按位(bit)发送和接收字节。尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。对于两个进行通信的端口,这些参数必须匹配。
VSPD虚拟串口工具
在硬件缺失的情况下,要想测试代码使用的是否正确。就需要使用VSPD虚拟串口工具来虚拟出串口,并在程序中打开串口,并发送接收数据。刚开始真的是啥也不懂(现在也啥也不懂^……),跟着别人贴的代码一步一步写但是就是只能发送数据没有办法接收数据。后来我才知道,他们是有硬件,并且把串口的TXD和RXD短接,这样就能实现自己发的数据,自己接收了。不得不说这个操作太骚了。在VSPD中我们发现串口都是成对出现的,也就是COM1发的数据是COM2接收的。并且只有在COM2打开的情况下才能接收数据。但是我确实很想测试一下程序中代码是否正确怎么办呢?难到我需要再写一个代码去打开另一个串口么?这时候我用到了另一个工具友善串口使用助手。可以在友善串口助手中打开与COM4配对的串口COM5,并向COM4发送数据。示意图如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.IO.Ports;
namespace 串口通信
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
pictureBox1.BackgroundImage = Properties.Resources.red;//将表示状态的图片设为红色,表示端口关闭
//检测并添加串口
foreach (string s in System.IO.Ports.SerialPort.GetPortNames())//获取当前计算机的串行端口名的数组
{
cbSerial.Items.Add(s);//添加到对应的下拉列表中
}
sp.WriteTimeout = 3000;
sp.ReadTimeout = 3000;
sp.ReceivedBytesThreshold = 1;
sp.RtsEnable = true;
sp.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);//订阅委托
cbSerial.SelectedIndex = 0; //设置cbSerial的默认选项
}
//接收数据事件
private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
int length = sp.BytesToRead;
byte[] recData = new byte[length];
sp.Read(recData, 0, length);
string recText = Encoding.GetEncoding("GB2312").GetString(recData);
//更新接收区
txtReceive.Invoke(new EventHandler(delegate {
txtReceive.AppendText(recText);
}));
}
//将接受到的内容显示出来
private void AddContent(string content)
{
this.BeginInvoke(new MethodInvoker(delegate
{
txtReceive.AppendText(content);
txtReceive.AppendText("\r\n");
}));
}
//打开相应端口
private void btn_Open_Click(object sender, EventArgs e)
{
if (cbSerial.Items.Count == 0)
{
MessageBox.Show("没有发现串口,请检查线路!");
return;
}
if (sp.IsOpen == false)//端口未打开,打开端口
{
//设置端口属性
sp.PortName = cbSerial.SelectedItem.ToString();//COM4
sp.BaudRate = 19200;//设置比特率
sp.DataBits = 8;//设置数据位长度
sp.Parity = Parity.None;//获取或设置奇偶校验检查协议
sp.StopBits = StopBits.One;//设置停止位
sp2.PortName = cbSerial.SelectedItem.ToString();//COM4
sp2.BaudRate = 19200;//设置比特率
sp2.DataBits = 8;//设置数据位长度
sp2.Parity = Parity.None;//获取或设置奇偶校验检查协议
sp2.StopBits = StopBits.One;//设置停止位
try
{
sp.Open();//打开串口
btnSend.Enabled = true;//可发送数据
MessageBox.Show(sp.PortName + "被打开!");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
btn_Open.Text = "关闭串口";
pictureBox1.BackgroundImage = Properties.Resources.green;
}
else//串口已经被打开,关闭窗口
{
try
{
sp.Close();
btnSend.Enabled = false;//端口已经被关闭不可编辑数据
MessageBox.Show(sp.PortName + "被打开!");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
btn_Open.Text = "打开串口";
pictureBox1.BackgroundImage = Properties.Resources.red;
}
}
//发送数据
public bool sendData(byte[] date)
{
if (sp.IsOpen)
{
try
{
sp.Write(date, 0, date.Length);
return true;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
MessageBox.Show("串口未打开", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return false;
}
//点击按钮触发发送事件
private void btnSend_Click(object sender, EventArgs e)
{
byte[] sendData = null;
if (!sp.IsOpen) //如果没打开
{
MessageBox.Show("请先打开串口!", "Error");
return;
}
String strSend = txtSend.Text;
try
{
sendData = Encoding.UTF8.GetBytes(txtSend.Text.Trim());
sp.Write(sendData, 0, sendData.Length);
}
catch (Exception ex)
{
MessageBox.Show("Error:" + ex.Message, "Error");
}
}
}
}