c# 模拟串口通信 SerialPort的实现示例

目录
  • 一、前导知识
    • 实现串口通信的必要设置
  • 二、实验
    • 绘制窗口
  • 测试
  • 三、总结
  • 四、附件完整代码

一、前导知识

串行口是计算机的标准接口,现在的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的实现示例的文章就介绍到这了,更多相关c# 模

(0)

相关推荐

  • C#中的串口通信SerialPort详解

    今天这篇文章带大家学习下C#中的串口通讯.在日常的开发工作中,如果工作内容是CS方向的同学应该很容易接触到串口通讯方面的业务需求.那么也就很容易想到C#中SerialPort类,它就是专门来处理串口通讯相关的. 了解什么是串口通讯 串口通讯是指外设和计算机间通过数据信号线,地线,控制线等,按位进行传输数据的一种通讯方式. 这种通讯方式使用的数据线少,在远距离通信中可以节约成本,但其传输速度比并行通讯慢. 串口是计算机上一种非常通用的设备通讯协议.大多数计算机包含两个基于RS-232的串口. 串口

  • c# 模拟串口通信 SerialPort的实现示例

    目录 一.前导知识 实现串口通信的必要设置 二.实验 绘制窗口 测试 三.总结 四.附件完整代码 一.前导知识 串行口是计算机的标准接口,现在的PC机(个人电脑)一般至少有两个串行口COM1和COM2.串行口应用广泛,在数据通信.计算机网络以及分布式工业控制系统中,经常采用串行通信来交换数据和信息 电气标准及协议来分包括RS-232-C.RS-422.RS485.USB(Universal Serial Bus)等 实现串口通信的必要设置 串口通信最重要的参数是波特率.数据位.停止位和奇偶校验.

  • java 串口通信实现流程示例

    1.下载64位rxtx for java 链接:http://fizzed.com/oss/rxtx-for-java 2.下载下来的包解压后按照说明放到JAVA_HOME即JAVA的安装路径下面去 3.在maven的pom.xml下添加 <dependency> <groupId>org.rxtx</groupId> <artifactId>rxtx</artifactId> <version>2.1.7</version&g

  • Android串口通信封装之OkUSB的示例代码

    本文介绍了Android串口通信封装之OkUSB的示例代码,分享给大家.具体如下: Github传送门:OkUSB OkUSB 一个简洁的Android串口通信框架. 功能简介 支持设置波特率 支持设置数据位 支持设置停止位 支持设置校验位 支持DTS和RTS 支持串口连接状态监听 用法简介 Gradle allprojects { repositories { ... maven { url 'https://jitpack.io' } } } dependencies { compile '

  • Java实现的串口通信功能示例

    本文实例讲述了Java实现的串口通信功能.分享给大家供大家参考,具体如下: 用Java实现串口通信(windows系统下),需要用到sun提供的串口包 javacomm20-win32.zip.其中要用到三个文件,配置如下: 1.comm.jar放置到 JAVA_HOME/jre/lib/ext; 2.win32com.dll放置到 JAVA_HOME/bin; 3.javax.comm.properties 两个地方都要放     jre/lib(也就是在JAVA文件夹下的jre)    JA

  • Java模拟UDP通信示例代码

    Java基础:模拟UDP通信 1.一次发送,一次接收 1.1.发送方 // 发送端,不需要连接服务器 public class UdpClientDemo {     public static void main(String[] args) throws Exception {         // 1. 发送数据包需要一个Socket         DatagramSocket socket = new DatagramSocket();         // 1.2 建立一个包    

  • python实现串口通信的示例代码

    1 硬件设备 TTL串口摄像头(VC0706) USB转TTL烧录器 2 serial安装 第一次安装的是serial的包导包的时候发现下载错了,正确应该是pyserial.安装后直接import就可以了. 3 实现串口通信 3.1 发现端口 Windows下为COM(N, N=1.2...), Ubuntu下为'/dev/ttyS0'.Windows初学者,可以给您一下两种方式确定端口号. 方法一:输入在终端(cmd)中输入 python -m serial.tools.list_ports

  • C#串口通信程序实例详解

    创建C#串口通信程序之命名空间 System.IO.Ports命名空间中最重用的是SerialPort 类. 创建C#串口通信程序之创建SerialPort 对象 通过创建SerialPort 对象,我们可以在程序中控制串口通信的全过程. 我们将要用到的SerialPort 类的方法: ReadLine():从输入缓冲区读一新行的值,如果没有,会返回NULLWriteLine(string):写入输出缓冲Open():打开一个新的串口连接Close():关闭 复制代码 代码如下: SerialP

  • Android串口通信之串口读写实例

    在Android串口通信:基本知识梳理的基础上,我结合我项目中使用串口的实例,进行总结: Android使用jni直接进行串口设备的读写网上已经有开源项目了,本文是基于网上的开源项目在实际项目中的使用做的调整和优化: Google串口开源项目 下面是我项目中的相关代码及介绍: 1.SerialPort.cpp /* * Copyright 2009 Cedric Priscal * * Licensed under the Apache License, Version 2.0 (the "Li

  • C#串口通信工具类的封装

    本文实例为大家分享了C#串口通信工具类的封装代码,供大家参考,具体内容如下  1.SerialPortHelper串口工具类封装 using System; using System.Collections.Generic; using System.IO.Ports; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Timers;   namespace public.Util {

随机推荐