C#开发串口通信实例及串口基础

一、串口通信简介

       串行接口(串口)是一种可以将接受来自CPU的并行数据字符转换为连续的串行数据流发送出去,同时可将接受的串行数据流转换为并行的数据字符供给CPU的器件。一般完成这种功能的电路,我们称为串行接口电路。

       串口通信(Serial Communications)的概念非常简单,串口按位(bit)发送和接收字节。尽管比按字节(byte)的并行通信慢,但是串口可以在使用一根线发送数据的同时用另一根线接收数据。串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。对于两个进行通信的端口,这些参数必须匹配。

  1. 波特率:这是一个衡量符号传输速率的参数。指的是信号被调制以后在单位时间内的变化,即单位时间内载波参数变化的次数,如每秒钟传送960个字符,而每个字符格式包含10位(1个起始位,1个停止位,8个数据位),这时的波特率为960Bd,比特率为10位*960个/秒=9600bps。

  2. 数据位:这是衡量通信中实际数据位的参数。当计算机发送一个信息包,实际的数据往往不会是8位的,标准的值是6、7和8位。标准的ASCII码是0~127(7位),扩展的ASCII码是0~255(8位)。

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

  4. 校验位:在串口通信中一种简单的检错方式。有四种检错方式:偶、奇、高和低。当然没有校验位也是可以的。

二、C#串口编程类

       从.NET Framework 2.0开始,C#提供了SerialPort类用于实现串口控制。命名空间:System.IO.Ports。其中详细成员介绍参看MSDN文档。下面介绍其常用的字段、方法和事件。

  1. 常用字段:

名称说明
PortName获取或设置通信端口
BaudRate获取或设置串行波特率
DataBits获取或设置每个字节的标准数据位长度
Parity获取或设置奇偶校验检查协议
StopBits获取或设置每个字节的标准停止位数

2. 常用方法:

名称说明
Close关闭端口连接,将 IsOpen 属性设置为 false,并释放内部 Stream 对象
GetPortNames获取当前计算机的串行端口名称数组
Open打开一个新的串行端口连接
Read从 SerialPort 输入缓冲区中读取
Write 将数据写入串行端口输出缓冲区

3. 常用事件:

名称说明
DataReceived表示将处理 SerialPort 对象的数据接收事件的方法

三、C#开发串口实例

前台页面:

84630f1daf677b62744a088123fe2e9e.png

 后台代码:

using System;

using System.IO.Ports;

using System.Text;

using System.Windows.Forms;

namespace SerialPort

{

    public partial class SerialPort : Form

    {

        String serialPortName;

        public SerialPort()

        {

            InitializeComponent();

        }

        private void Form1_Load(object sender, EventArgs e)

        {

            string[] ports = System.IO.Ports.SerialPort.GetPortNames();//获取电脑上可用串口号

            comboBox1.Items.AddRange(ports);//给comboBox1添加数据

            comboBox1.SelectedIndex = comboBox1.Items.Count > 0 ? 0 : -1;//如果里面有数据,显示第0个

            comboBox2.Text = "115200";/*默认波特率:115200*/

            comboBox3.Text = "1";/*默认停止位:1*/

            comboBox4.Text = "8";/*默认数据位:8*/

            comboBox5.Text = "无";/*默认奇偶校验位:无*/

        }

        private void button1_Click(object sender, EventArgs e)

        {

            if (button1.Text == "打开串口"){//如果按钮显示的是打开

                try{//防止意外错误

                    serialPort1.PortName = comboBox1.Text;//获取comboBox1要打开的串口号

                    serialPortName = comboBox1.Text;

                    serialPort1.BaudRate = int.Parse(comboBox2.Text);//获取comboBox2选择的波特率

                    serialPort1.DataBits = int.Parse(comboBox4.Text);//设置数据位

                    /*设置停止位*/

                    if (comboBox3.Text == "1") { serialPort1.StopBits = StopBits.One; }

                    else if (comboBox3.Text == "1.5") { serialPort1.StopBits = StopBits.OnePointFive; }

                    else if (comboBox3.Text == "2") { serialPort1.StopBits = StopBits.Two; }

                    /*设置奇偶校验*/

                    if (comboBox5.Text == "无") { serialPort1.Parity = Parity.None; }

                    else if (comboBox5.Text == "奇校验") { serialPort1.Parity = Parity.Odd; }

                    else if (comboBox5.Text == "偶校验") { serialPort1.Parity = Parity.Even; }

                    serialPort1.Open();//打开串口

                    button1.Text = "关闭串口";//按钮显示关闭串口

                }

                catch (Exception err)

                {

                    MessageBox.Show("打开失败"+ err.ToString(), "提示!");//对话框显示打开失败

                }

            }

            else{//要关闭串口

                try{//防止意外错误

                    serialPort1.Close();//关闭串口

                }

                catch (Exception){}

                button1.Text = "打开串口";//按钮显示打开

            }

        }

        protected override void WndProc(ref Message m)

        {

            if (m.Msg == 0x0219){//设备改变

                if (m.WParam.ToInt32() == 0x8004){//usb串口拔出

                    string[] ports = System.IO.Ports.SerialPort.GetPortNames();//重新获取串口

                    comboBox1.Items.Clear();//清除comboBox里面的数据

                    comboBox1.Items.AddRange(ports);//给comboBox1添加数据

                    if (button1.Text == "关闭串口"){//用户打开过串口

                        if (!serialPort1.IsOpen){//用户打开的串口被关闭:说明热插拔是用户打开的串口

                            button1.Text = "打开串口";

                            serialPort1.Dispose();//释放掉原先的串口资源

                            comboBox1.SelectedIndex = comboBox1.Items.Count > 0 ? 0 : -1;//显示获取的第一个串口号

                        }

                        else{

                            comboBox1.Text = serialPortName;//显示用户打开的那个串口号

                        }

                    }

                    else{//用户没有打开过串口

                        comboBox1.SelectedIndex = comboBox1.Items.Count > 0 ? 0 : -1;//显示获取的第一个串口号

                    }

                }

                else if (m.WParam.ToInt32() == 0x8000){//usb串口连接上

                    string[] ports = System.IO.Ports.SerialPort.GetPortNames();//重新获取串口

                    comboBox1.Items.Clear();

                    comboBox1.Items.AddRange(ports);

                    if (button1.Text == "关闭串口"){//用户打开过一个串口

                        comboBox1.Text = serialPortName;//显示用户打开的那个串口号

                    }

                    else{

                        comboBox1.SelectedIndex = comboBox1.Items.Count > 0 ? 0 : -1;//显示获取的第一个串口号

                    }

                }

            }

            base.WndProc(ref m);

        }

        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)

        {

            int len = serialPort1.BytesToRead;//获取可以读取的字节数

            byte[] buff = new byte[len];//创建缓存数据数组

            serialPort1.Read(buff, 0, len);//把数据读取到buff数组

            Invoke((new Action(() =>{//C# 3.0以后代替委托的新方法

                    textBox1.AppendText(Encoding.Default.GetString(buff));//对话框追加显示数据

            })));

        }

        private void button2_Click(object sender, EventArgs e)

        {

            textBox1.Clear();//清除接收对话框显示的数据

        }

        private void button3_Click(object sender, EventArgs e)

        {

            String Str = textBox2.Text.ToString();//获取发送文本框里面的数据

            try

            {

                if (Str.Length > 0)

                {

                        serialPort1.Write(Str);//串口发送数据

                }

            }

            catch (Exception){ }

        }

        private void button4_Click(object sender, EventArgs e)

        {

            textBox2.Clear();//清除发送文本框里面的内容

        }

    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/281702.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

我在SharePoint行业的从业经历(一)

大约10年前,我刚刚毕业的时候,找到了一个试用的机会。那个时候的我对软件根本没有概念。编程学的也非常少。仅仅是在系里学过一点VB和C,以为软件就是像QQ或者游戏之类的。我从来没想到会认识…

Linux的学习思路

自学嵌入式确实不大现实(当然也不是说没有这个可能),毕竟嵌入式难度也是比较大的。 嵌入式的应用主要是几个方向, 一是系统开发:侧重开发环境搭建、内核原理、交叉编译等; 二是嵌入式Linux应用开发&#xf…

tinycore php,tinycore中文支持

这两天在弄tinycore,想用它来搭个小系统出来。下载最新的CorePlus-current.iso 4.5.2,用开源的usb的安装工具core2usb-1.6.exe将它安装到u盘,然后接上台式机上,开机从u盘启动,一切顺利。好,开始搞起&#…

javascript权威指南--学习笔记

-一、JavaScript基本数据类型 1、数字--Number类 2、字符串--String类 3、布尔--Boolean类 4、函数Function 5、对象Object 6、数组Array 7、null 8、undefined 备注: 当一个未定义的值用于布尔环境,他就会转为false,用于数字环境就会转为…

支持 dotnet 6 的 dnSpy 神器版本

官方的 dnSpy 在 2021 时,由于某些吃瓜的原因 wtfsck 将 dnSpy 给 Archived 掉,在大佬被哄好之前,预计是不再更新。最新官方版本对 dotnet 6 的支持较弱,对于很多 dotnet 6 应用都无法成功调试,附加调试上去将会让应用…

cmd命令

mstsc 开启远程连接services.msc 开启服务sc delete 服务名称 删除服务telnet 106.75.97.193 查看端口是否占用netstat -a 查看端口监听状态

Robot Framework 教程 (3) - Resource及关键字 的使用

From:http://www.cnblogs.com/buaawp/p/4754399.html Robot Framework 教程 (3) - Resource及关键字 的使用 在进行软件自动化测试时,我们设计并编写好一个测试脚本的业务逻辑之后,需要将其中的业务数据提取为变量,并对业务逻辑进行封装。在后…

mysql中的操作指令,MySQL中常用指令操作的介绍(代码示例)

本篇文章给大家带来的内容是关于MySQL中常用指令操作的介绍(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。l 创建数据库:CREATE DATABASE table_name;l 删除数据库:DROP DATABASE table_na…

mt19937 -- 高质量随机数

优点:产生速度快, 周期大 用法: #include<bits/stdc.h> using namespace std;int main() {mt19937 mt_rand(time(0));cout << mt_rand() << endl;return 0; } 转载于:https://www.cnblogs.com/widsom/p/9935561.html

使用 AutoMapper 自动在多个数据模型间进行转换

访问数据库、IPC 通信、业务模型、视图模型……对于同一个业务的同一种数据&#xff0c;经常会使用多种数据模型工作在不同的代码模块中。这时它们之间的互相转换便是大量的重复代码了。使用 AutoMapper 便可以很方便地在不同的模型之间进行转换而减少编写太多的转换代码&#…

集合类型内建方法

一、集合类型方法方法名称 操作 s.issubset(t)如果s是t的子集&#xff0c;则返回True&#xff0c;否则返回Falses.issuperset(t)如果s是t的超集&#xff0c;则返回True&#xff0c;否则返回Falses.union(t)返回一个新集合&#xff0c;该集合是s和t的并集s.intersection(t)返回…

Maven基础:Maven环境搭建及基本使用(1)

1. Maven环境搭建 1.1 Maven简介 1.2 Maven下载及环境设置 Maven下载地址&#xff1a;http://maven.apache.org/download.cgi 当前下载版本&#xff1a;apache-maven-3.5.0-bin.zip&#xff0c;解压之后路径 D:\Program Files\apache-maven-3.5.0 Maven环境变量设置&#xff1a…

mysql主外键引用关系,关于mysql:数据主/外键关系

我想对于那些已经开发了许多数据库模式的人来说&#xff0c;这将是一个简单的答案&#xff0c;但是我最近发现自己承担了优化(或尝试优化)数据库模式的任务&#xff0c;并且一直在阅读"高性能MySQL"&#xff0c;并且剩下一个关于在模式中使用或"过度使用"外…

解读微软开源MMLSpark:统一的大规模机器学习生态系统

AI前线导读&#xff1a;目前&#xff0c;有很多深度学习框架支持与Spark集成&#xff0c;如Tensorflow on Spark等。然而&#xff0c;微软开源的MMLSpark不仅集成了机器学习框架&#xff08;CNTK深度学习计算框架、LightGBM机器学习框架&#xff09;&#xff0c;还可以将这些计…

floyd判环算法(龟兔赛跑算法)

floyd判环算法&#xff08;龟兔赛跑算法&#xff09; 注意&#xff0c;这个算法是用来判断一条链一条环的图&#xff0c;环的长度或者环与链的交界处的&#xff0c;所以此floyd非彼floyd&#xff08;虽然都是一个人想出来的&#xff09;。 &#xff08;图不是我的&#xff09; …

一个redis的连接库的实现

2019独角兽企业重金招聘Python工程师标准>>> import socketdef format_message( args):"""Create redis message:param args:Message data"""l u"*%d" % len(args)lines [l.encode(utf-8)]for arg in args:if not isinst…

matlab 边缘检测不闭合,Matlab多种图像边缘检测方法

1、用Prewitt算子检测图像的边缘I imread(bacteria.BMP);BW1 edge(I,prewitt,0.04); % 0.04为梯度阈值figure(1);imshow(I);figure(2);imshow(BW1);2、用不同σ值的LoG算子检测图像的边缘I imread(bacteria.BMP);BW1 edge(I,log,0.003); % σ2imshow(BW1);titl…

实现CSS在线美化(格式化)、压缩、加密、解密、混淆工具-toolfk程序员工具网

本文要推荐的[ToolFk]是一款程序员经常使用的线上免费测试工具箱&#xff0c;ToolFk 特色是专注于程序员日常的开发工具&#xff0c;不用安装任何软件&#xff0c;只要把内容贴上按一个执行按钮,就能获取到想要的内容结果。ToolFk还支持 BarCode条形码在线生成、 QueryList采集…

只是他给的实在太多了!

工作几年后&#xff0c;总是会问自己一个问题&#xff0c;工作的意义是什么&#xff1f;这个如果要在网络上寻找答案&#xff0c;那一定是多如牛毛&#xff0c;每一个人都有一套自己的看法。在一开始出入社会工作之时&#xff0c;我并没有意识到这个问题&#xff0c;更没有思考…

[ci]jenkins server启动,通过jnlp的方式启动slave(容器模式)

jenkins server启动,通过jnlp的方式启动slave. java -jar jenkins.jar 配置jnlp端口--全局安全 配置云 配置项目 执行成功 转载于:https://www.cnblogs.com/iiiiher/p/7978831.html