目录

一、前导知识

实现串口通信的必要设置

波特率

数据位

停止位

奇偶校验位

二、实验

绘制窗口

代码实现

测试

三、总结

四、附件完整代码


一、前导知识

串行口是计算机的标准接口,现在的PC机(个人电脑)一般至少有两个串行口COM1和COM2。串行口应用广泛,在数据通信、计算机网络以及分布式工业控制系统中,经常采用串行通信来交换数据和信息

电气标准及协议来分包括RS-232-C、RS-422、RS485、USB(Universal Serial Bus)等

实现串口通信的必要设置

串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。

对于两个进行通行的端口,这些参数必须匹配:

波特率

这是一个衡量通信速度的参数。它表示**每秒钟传送的bit的个数**。例如300波特表示每秒钟发送300个bit,波特率和距离成反比。高波特率常常用于放置的很近的仪器间的通信,典型的例子就是GPIB设备的通信

数据位

这是衡量通信中实际数据位的参数。当计算机发送一个信息包,实际的数据不会是8位的,标准的值是5、7和8位,如何设置取决于你想传送的信息。比如,标准的ASCII码是0~127(7位)。扩展的ASCII码是0~255(8位)。如果数据使用简单的文本(标准 ASCII码),那么每个数据包使用7位数据。每个包是指一个字节,包括开始/停止位,数据位和奇偶校验位。由于实际数据位取决于通信协议的选取,术语“包”指任何通信的情况。

停止位

用于表示单个包的最后一位。典型的值为1,1.5和2位。由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢

奇偶校验位

在串口通信中一种简单的检错方式。有四种检错方式:偶、奇、高和低。当然没有校验位也是可以的。对于偶和奇校验的情况,串口会设置校验位(数据位后面的一位),用一个值确保传输的数据有偶个或者奇个逻辑高位。例如,如果数据是011,那么对于偶校验,校验位为0,保证逻辑高的位数是偶数个。如果是奇校验,校验位位1,这样就有3个逻辑高位。高位和低位不真正的检查数据,简单置位逻辑高或者逻辑低校验。这样使得接收设备能够知道一个位的状态,有机会判断是否有噪声干扰了通信或者是否传输和接收数据是否不同步

二、实验

我们将通过模拟串口通信,在pc机上进行两个串口(COM1、COM2)的交互

需要用到的软件:

Launch Virtual Serial Port Driver Pro:虚拟串口。使用它来模拟两个串口的连接

绘制窗口

代码实现

1.使用SerialPort控制串口

private SerialPort sp1 = new SerialPort();

2.打开串口

        private void button2_Click(object sender, EventArgs e){if (!sp1.IsOpen){try{//串口号sp1.PortName = "COM1";//波特率sp1.BaudRate = 115200;//数据位sp1.DataBits = 8;//停止位sp1.StopBits = StopBits.One;//奇偶校验位sp1.Parity = Parity.Even;//DataReceived事件发送前,内部缓冲区里的字符数sp1.ReceivedBytesThreshold = 1;sp1.RtsEnable = true; sp1.DtrEnable = true; sp1.ReadTimeout = 3000;// Control.CheckForIllegalCrossThreadCalls = false;//表示将处理 System.IO.Ports.SerialPort 对象的数据接收事件的方法。sp1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(sp1_DataReceived_1);//打开串口sp1.Open();MessageBox.Show("COM1打开成功!");}catch (Exception ex){MessageBox.Show("COM1打开失败!");}}else{MessageBox.Show("COM1打开成功!");}}

3.关闭串口

        private void button3_Click(object sender, EventArgs e){if (sp1.IsOpen){sp1.Close();MessageBox.Show("COM1关闭成功!");}}

串口2的打开和关闭同理串口1实现

4.发送

        private void button1_Click(object sender, EventArgs e){if (sp1.IsOpen){if (!string.IsNullOrEmpty(this.textBox1.Text)){sp1.WriteLine(this.textBox1.Text+"\r\n");}else{MessageBox.Show("发送数据为空");}}else{MessageBox.Show("COM1未打开!");}}

5.接收

        StringBuilder builder1 = new StringBuilder();//在接收到了ReceivedBytesThreshold设置的字符个数或接收到了文件结束字符并将其放入了输入缓冲区时被触发public void sp1_DataReceived_1(object sender, SerialDataReceivedEventArgs e){Console.WriteLine("接收中...");int n = sp1.BytesToRead;      //先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致byte[] buf = new byte[n];   //声明一个临时数组存储当前来的串口数据sp1.Read(buf, 0, n);      //读取缓冲数据builder1.Remove(0, builder1.Length); //清除字符串构造器的内容builder1.Append(Encoding.ASCII.GetString(buf));string comdata = builder1.ToString();Console.WriteLine("data: + " + comdata);this.Invoke(settextevent,comdata);}

这里仅仅实现了一般的接收方式,并不严谨和健壮

测试

使用软件模拟串口连接

打开两个程序

在一程序中打开串口1,在二程序中打开串口2,发送消息

在一程序中输入字符"hello,HanHanCheng!",发现在二程序中接收到,同样,在二程序中输入,在一中也能收到

三、总结

1.由于是异步线程接收,在接收中需要使用委托来跨线程调用组件

        public delegate void settext(string text);public event settext settextevent;public void set(string text){this.textBox2.Text = text;}//再注册settextevent += set;

2.DataReceived事件触发条件需要注意,可能在实现时,无法触发导致无法接收。

触发条件是:在接收到了ReceivedBytesThreshold设置的字符个数或接收到了文件结束字符并将其放入了输入缓冲区时被触发

四、附件完整代码

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 Training_USBCOM
{public partial class Form1 : Form{public Form1(){InitializeComponent();settextevent += set;}private SerialPort sp1 = new SerialPort();StringBuilder builder = new StringBuilder();private void button1_Click(object sender, EventArgs e){if (sp1.IsOpen){if (!string.IsNullOrEmpty(this.textBox1.Text)){sp1.WriteLine(this.textBox1.Text+"\r\n");}else{MessageBox.Show("发送数据为空");}}else{MessageBox.Show("COM1未打开!");}}public delegate void settext(string text);public event settext settextevent;public void set(string text){this.textBox2.Text = text;}StringBuilder builder1 = new StringBuilder();//在接收到了ReceivedBytesThreshold设置的字符个数或接收到了文件结束字符并将其放入了输入缓冲区时被触发public void sp1_DataReceived_1(object sender, SerialDataReceivedEventArgs e){Console.WriteLine("接收中...");int n = sp1.BytesToRead;      //先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致byte[] buf = new byte[n];   //声明一个临时数组存储当前来的串口数据sp1.Read(buf, 0, n);      //读取缓冲数据builder1.Remove(0, builder1.Length); //清除字符串构造器的内容builder1.Append(Encoding.ASCII.GetString(buf));string comdata = builder1.ToString();Console.WriteLine("data: + " + comdata);this.Invoke(settextevent,comdata);}private void button2_Click(object sender, EventArgs e){if (!sp1.IsOpen){try{//串口号sp1.PortName = "COM1";//波特率sp1.BaudRate = 115200;//数据位sp1.DataBits = 8;//停止位sp1.StopBits = StopBits.One;//奇偶校验位sp1.Parity = Parity.Even;//DataReceived事件发送前,内部缓冲区里的字符数sp1.ReceivedBytesThreshold = 1;sp1.RtsEnable = true; sp1.DtrEnable = true; sp1.ReadTimeout = 3000;// Control.CheckForIllegalCrossThreadCalls = false;//表示将处理 System.IO.Ports.SerialPort 对象的数据接收事件的方法。sp1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(sp1_DataReceived_1);//打开串口sp1.Open();MessageBox.Show("COM1打开成功!");}catch (Exception ex){MessageBox.Show("COM1打开失败!");}}else{MessageBox.Show("COM1打开成功!");}}private void button3_Click(object sender, EventArgs e){if (sp1.IsOpen){sp1.Close();MessageBox.Show("COM1关闭成功!");}}private void button5_Click(object sender, EventArgs e){if (!sp1.IsOpen){try{//串口号sp1.PortName = "COM2";//波特率sp1.BaudRate = 115200;//数据位sp1.DataBits = 8;//停止位sp1.StopBits = StopBits.One;//奇偶校验位sp1.Parity = Parity.Even;sp1.ReceivedBytesThreshold = 1;sp1.RtsEnable = true; sp1.DtrEnable = true; sp1.ReadTimeout = 3000;Control.CheckForIllegalCrossThreadCalls = false;//表示将处理 System.IO.Ports.SerialPort 对象的数据接收事件的方法。sp1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(sp1_DataReceived_1);//打开串口sp1.Open();MessageBox.Show("COM2打开成功!");}catch (Exception ex){MessageBox.Show("COM2打开失败!");}}else{MessageBox.Show("COM2打开成功!");}}private void button4_Click(object sender, EventArgs e){if (sp1.IsOpen){sp1.Close();MessageBox.Show("COM2关闭成功!");}}}
}

c# 模拟串口通信 SerialPort相关推荐

  1. linux gpio 模拟串口,STM32的GPIO口模拟串口通信.rar

    [实例简介] 利用GPIO.EXTI外部中断.TIM定时器实现URAT串口,该例子来自21IC网,未做改动,明天自己调试,看看效果 完全是根据UART协议编写 [实例截图] [核心代码] STM32的 ...

  2. C#中的串口通信SerialPort

    前言 大家好,我是阿辉. 今天这篇文章带大家学习下C#中的串口通讯.在日常的开发工作中,如果工作内容是CS方向的同学应该很容易接触到串口通讯方面的业务需求.那么也就很容易想到C#中SerialPort ...

  3. SoftwareSerial库的使用——Arduino软件模拟串口通信

    除HardwareSerial外,Arduino还提供了SoftwareSerial类库,它可以将你的其他数字引脚通过程序模拟成串口通信引脚. 通常我们将Arduino UNO上自带的串口称为硬件串口 ...

  4. 【Unity3D软硬件】Unity3D与串口通信 SerialPort类完全教程

    推荐阅读 CSDN主页 GitHub开源地址 Unity3D插件分享 简书地址 我的个人博客 QQ群:1040082875 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有 ...

  5. C#串口通信 SerialPort类

    因为公司项目需要将USB扫码枪改为串口扫码枪,串口扫码的好处在于不需要一个输入框来接受USB扫出来的文本,能解决多个扫码枪一起扫码时的并发问题,所以需要用到多线程及串口技术. 一.串口通信简介 串行接 ...

  6. 普通io口模拟串口通信

    之前公司在做项目的时候需要用到多串口,板载串口资源不足,就在网上找相关内容,结合自己的理解做出虚拟串口. 模拟串口需要用到两个普通io引脚,一个定时器. /** *软件串口的实现(IO模拟串口) * ...

  7. 用GPIO口模拟串口通信,它真的来了

    你是否遇到过某个MCU串口不够的情况? 这时我们可以考虑用GPIO去模拟,如何具体实现呢? 首选我们需要了解串口的传输协议, UART使用异步模式工作,不需要时钟信号,其一般格式为:起始位+数据位+校 ...

  8. Android 模拟串口通信过程

    https://gitee.com/isnullpointer/serialport-demo 1.环境 Android 模拟器选择了 Genymotion : 串口模拟的工具叫 Launch Vir ...

  9. 51单片机C语言波特率十六进制,理解51单片机串口通信的波特率与USB转串口通信...

    RS232 在我们电脑上,一般都会有一个9针的串行接口,这个串行接口叫做RS232接口,它和UART通信有关联,但是由于现在笔记本电脑不带9针串口,所以和单片机通信越来越趋于使用USB虚拟串口. 九针 ...

  10. UART串口通信浅谈之(二)--寄存器设置

    1.1 通信的三种基本类型 常用的通信通常可以分为单工.半双工.全双工通信. 单工就是指只允许一方向另外一方传送信息,而另一方不能回传信息.比如我们的电视遥控器,我们的收音机广播等,都是单工通信技术. ...

最新文章

  1. mysql的基本知识
  2. 用.NET调用oracle的存储过程返回记录集
  3. ROS知识【15】:在eclipse创建ROS项目
  4. 初等数论--整除--整数表示:算数分解定理/素因数分解式/进制表示
  5. 没有CLOB类型却报ORA-00932: 数据类型不一致: 应为 -, 但却获得 CLOB
  6. rtk采点后如何导入cad_【干货】RTK实操视频:工程之星5.0操作攻略!(第五部分)...
  7. Linux 5.7 将支持国产 RISC-V 芯片 K210
  8. .ajax 自定义headers,Ajax设置自定义请求头的两种方法
  9. 【分享-免费下载】免费下载配乐/视频/平面设计/游戏素材
  10. HTTP -- 目录
  11. html打印预览出现重叠,html – 使用打印模式css打印网页时页眉和正文内容重叠...
  12. MySQL - ODBC安装错误问题!
  13. IE开发者人员工具使用说明 pptx
  14. Unknown error: Unable to build: the file dx.jar was not loaded from the SDK folder!
  15. PROTEL技术应用技巧总结
  16. 【基础教程】基于matlab图像处理图像分割【含Matlab源码 191期】
  17. 为什么IEEE 1588如此精确呢?
  18. 支付宝小程序卡包开发(流程+详细案例+商户会员卡)
  19. 基于HTML+CSS+JavaScript制作服装商城网站设计毕业论文源码
  20. BZOJ 2827 千山鸟飞绝 Treap

热门文章

  1. 马尔可夫模型 Markov Model
  2. linux编译成功没有响应,解决Xilinx ZCU106 Linux启动后没有响应问题。
  3. 汽车应急启动电源,拉杆音箱,蓝牙音响升压芯片合集,DCDC大功率外置MOS升压芯片10W,200W,400W
  4. RTF文件结构分析及其应用
  5. html美化select样式,CSS美化select下拉框
  6. pcie总线与cpci总线_PCI和CPCI
  7. Windows防火墙命令行手册
  8. 四元数、欧拉角及方向余弦矩阵的相互转换公式
  9. 信用评分模型详解(上)之 评分卡模型
  10. python开根号函数的实现