一、创建Windows窗体项目
二、添加SerialPort组件
三、默认产生serialPort1对象

四、设置串口属性
三种方法(本实例用第三种)
1.设置下面的属性

2.代码实现

3.用我封装的一个类来实现
C# 封装了用于对 Serialport类属性的配置类及其保存窗
五、串口操作(打开关闭)
按上述步骤初始化串口之后进行串口的打开和关闭操作
打开关闭串口的函数包含在SerialPort类中,利用SerialPort对象来引用
serialPort1.Open();
serialPort1.Close();
例如:在程序中添加一个打开串口按钮btn_open,btn_open.Text初始化为"打开串口"
在btn_open响应函数中加入以下代码
private void btn_open_Click(object sender, EventArgs e)
{
if (btn_open.Text == "打开串口")
{
btn_open.Text = "关闭串口";
serialPort1.Open();
}
else
{
btn_open.Text = "打开串口";
serialPort1.Close();
}
}
此时形成的界面截图如下:

此时程序的代码如下:
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 AHRSmanager;
namespace testOfserialPort
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
}
private void btn_SerialportSet_Click(object sender, EventArgs e)
{
using (串口设置窗口 frmConfig = new 串口设置窗口())
{
frmConfig.ShowDialog();
}
}
private void btn_open_Click(object sender, EventArgs e)
{
if (btn_open.Text == "打开串口")
{
串口设置窗口.ReadSerialPortSet(serialPort1); //串口初始化
btn_open.Text = "关闭串口";
serialPort1.Open();
}
else
{
btn_open.Text = "打开串口";
serialPort1.Close();
}
}
private void Form1_Load(object sender, EventArgs e)
{
btn_open.Text = "打开串口";
}
}
}
这时该程序已经具有开关串口的作用,可以用 单PC机虚拟串口互连方法 介绍的方法进行串口测试(串口互联模式)
运行程序,点击串口配置按钮,进行参数配置,点击打开串口,VSPM就将显示串口的打开和关闭.


六、数据的发送
(一) 十六进制数据发送
使用方法见 C#中用SerialPort类中的Write()方法发送十六进制数
1.为程序添加发送按钮,命名为btn_send,为程序添加文本输入框tb_send
2.在btn_send的回调函数中添加以下代码
private void btn_send_Click(object sender, EventArgs e)
{
Byte[] BSendTemp = new Byte[1]; //建立临时字节数组对象
BSendTemp[0] = Byte.Parse(this.tb_send.Text);//由文本框读入想要发送的数据
this.serialPort1.Write(BSendTemp, 0, 1);//发送数据
}
3.测试
将串口配置为COM3,打开VSPM和串口调试助手,调试助手为COM4
打开串口COM3,将要发送的数写入输入文本框(0-255),点击发送在串口调试助手中就会出现相应的十六进制数据显示
(二) 字符串数据发送
1 为程序添加CheckBox cB_Hex,如若选中则发送Hex数据,如若未选则发送String数据。
2 将btn_send的响应函数btn_send_Click修改为:
private void btn_send_Click(object sender, EventArgs e)
{
if (this.cB_Hex.Checked == true)
{
Byte[] BSendTemp = new Byte[1]; //建立临时字节数组对象
BSendTemp[0] = Byte.Parse(this.tb_send.Text);//由文本框读入想要发送的数据
this.serialPort1.Write(BSendTemp, 0, 1);//发送数据
}
else
{
string serialStringTemp = this.tb_send.Text;
this.serialPort1.WriteLine(serialStringTemp);
}
}
3 运行程序,取消Checkbox的选择
4 发送字符串,下面为测试图
5 这里主要利用了WriteLine函数,这个函数在Console中也有定义,用发基本一样。
七、数据的接收
(A)结构介绍
数据的接收大体有两种方案:1 主动定时读取;2 事件响应驱动
1 主动定时读取
这种方式的适应能力较弱,当数据来源为定时并且不是很快的情况时可以考虑采用这种方法,这种方法主要适用于数据采集系统而不适用于随机事件发生时的通信或控制系统。
当然,这种方法的缺点是如果接收的数据不是定时的,则读取定时器的触发频率就要很小,这样才能保证及时的读取串口缓冲区。这也将大大的浪费系统资源。
2 事件响应驱动
这种方式是串口通信上位机制作的主要方式,其采用中断思想而成,当串口输入缓冲区中的字节数据大于某个设定的个数时,触发串口输入中断,这时在中断程序中读取串口输入缓冲区中的数据,具有实时性和灵活性,是个常用的较好的方法。本文也是采用这种方法来进行串口输入缓冲区的实时数据读取。
(B)事件响应驱动下的串口输入缓冲区数据读取
.NET中封装了
SerialPort 类 表示串行端口资源。
命名空间: System.IO.Ports
程序集: System(在 System.dll 中)
除了前面用到的串口常规属性设置(BuadRate,PortName),这里用到了一个新的串口属性:
这个ReceiveBytesThreshold属性即是设置串口输入缓冲区中的数据字节大于ReceiveBytesThreshold时触发DataReceived事件。
用法:
<1>在设计器双击串口serialport1的DataReceived事件,在代码中就会自动加入serialPort1_DataReceived函数作为DateReceived的事件触发函数。
<2>作为测试,先将serialport1.ReceiveBytesThreshold设为1,即串口输入缓冲区有数就触发DataReceived事件。
<3>加入RichTextBox rTB_receive作为串口接收数据的显示组件
<4>在DataReceived事件响应函数中读取串口输入缓冲区中的数据
string serialReadString;
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
serialReadString += serialPort1.ReadExisting();
}
这里serialReadString即为读取到串口输入缓冲区的数据。
要想将其显示到RichTextBox rTB_receive中,这里出现了一个跨线程的问题,因为DataReceived事件是在辅助线程中被激发的,所以要将数据显示到rTB_receive的主线程中就要进行一定的处理,处理方法如下:
C#中SerialPort类中DataReceived事件GUI实时处理方法
将DataReceived事件响应函数修改为如下:
string serialReadString;
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
serialReadString = serialPort1.ReadExisting();
this.rTB_receive.Invoke
(
new MethodInvoker
(
delegate
{
this.rTB_receive.AppendText(serialReadString);
}
)
);
}
这时就可以按字符串收发了!
<5> 测试图,打开上位机和调试助手,点击调试助手的发送按钮,上位机就会相应的显示接收到的数据.
<6> 这时候就完成了基本上位机功能的编写
至此工程文件:
串口数据的读取还涉及到其他的读取函数,