C#-串口通信入门及进阶扩展

目录

一、串口相关参数介绍

1、端口(COM口)

2、波特率(Baud rate)

3、起始位

4、停止位(StopBits)

5、数据位

6、校验位

7、缓存区

二、串口通信助手

三、虚拟串口工具

四、进阶扩展 

1、位运算

2、负数、浮点数存储方式 

3、数据校验算法

3.1、奇偶校验

3.2、LRC

3.3、累加和校验

3.4、CRC

介绍 

常用多项式表

CRC-8

CRC-16

CRC-32

CRC-USB

4、Modbus通信协议

4.1、介绍 

4.2、Modbus-RTU


串口通讯(Serial Communication),是指外设和计算机间,通过数据信号线、地线等,按位进行传输数据的一种双向通讯方式。

串口是一种接口标准,它规定了接口的电气标准,没有规定接口插件电缆以及使用的通信协议,通信协议很多,可根据实际情况选择和自定义。

一、串口相关参数介绍

1、端口(COM口)

CMO口(Communication Module Outlet)是一种用于连接计算机和外部设备的接口,也称为串行端口,简称CMO口,常见串口通讯有一般电脑应用的RS-232(使用 25 针或 9 针连接器)和工业电脑应用的半双工RS-485与全双工RS-422。

电脑端口查看:设置->系统->关于->设备管理器->端口

2、波特率(Baud rate)

波特率是一个电子信号上的术语,用于描述信道的数据传输速度。

单位是bit/s,常见的9600波特率表示每秒传输9600个比特位,1个字节8位,9600/8=1200,代表每秒钟串口可传输1200个字节(不考虑起始位、停止位、校验位的情况下),注意:

  1. 波特率如果太高会导致传输数据不稳定,一般使用9600;
  2.  发送端与接收端波特率不一致会导致数据不一致;

3、起始位

起始位必须是持续一个比特时间的逻辑0电平,标志传输一个字符的开始,接收方可用起始位使自己的接收时钟与发送方的数据同步;

C#开发中一般不需要设置起始位。

4、停止位(StopBits)

停止位可以是是1位、1.5位或2位,可以由软件设定,它一定是逻辑1电平,标志着传输一个字符的结束;

C#开发中一般通过StopBits枚举类型设置停止位,枚举值包括None、One、Two、OnePointFive四种(通常若设备不指定,默认停止位为1位)。

5、数据位

数据位紧跟在起始位之后,是通信中的真正有效信息。数据位的位数可以由通信双方共同约定,一般可以是5位、7位或8位;

C#开发中若设备不指定,默认数据位为8位

6、校验位

校验位仅占一位,用于进行奇校验或偶校验,检验位不是必须有的。如果是奇校验,需要保证传输的数据总共有奇数个逻辑高位;如果是偶校验,需要保证传输的数据总共有偶数个逻辑高位;

C#开发中通常使用Parity枚举类型来设置校验位,有五种,日常开发中使用最多的是None无校验、Odd奇校验、Even偶校验。

7、缓存区

串口包括两个缓存区,发送缓存区和接收缓存区;

发送缓存区:(软件)发送数据时将数据先存在发送缓存区,再通过(硬件)串口发送出去;

接收缓存区:接收数据时先将数据存在接收缓存区,(软件)再从中读取数据;

二、串口通信助手

串口通信助手是用于测试和调试串口通信的工具,可通过串口与外部设备通信,提供界面来监视和控制串口数据的接收和发送,从而验证串口通信是否正常工作。

实现一个串口通信助手示例:C#Wpf-实现串口通信助手

分享一个串口通信助手,下载地址:友善串口通信助手

                                        提取码: h64y

三、虚拟串口工具

当电脑无COM口时,使用该工具虚拟出COM口。 

下载地址:VSPD

提取码:a2cp

破解说明:运行vspd.exe 安装,安装后先不运行,将 vspdctl.dll 文件放入工程目录中,覆盖原文件,即完成破解。

使用说明:点击Add Pair按钮添加虚拟COM口连接对,即可。

四、进阶扩展 

1、位运算

符号意义逻辑介绍示例
~逻辑非取反~a
&逻辑与清0a&b
|逻辑或置1a|b
<<按位左移,超出舍掉乘以2的n次方a<<n
>>按位右移,超出舍掉除以2的n次方a>>n
^异或不同置1,相同清0a^b

  三次异或,可使变量值互换,示例如下:

int a = 13;
int b = 20;
a ^= b;
b ^= a;
a ^= b;
Console.WriteLine($"a:{a}b:{b}");

2、负数、浮点数存储方式 

负数在计算机中是以补码的形式存储,补码计算方式:

  1. 最高位为符号位,负数符号位为1,正数为0;
  2. 除符号位,所有位取反得到反码;
  3. 反码+1得到补码;

浮点数一般分为单精度与双精度两种,在计算机中的存储方式通常分为三部分:

  1. 符号位:正数为0,负数为1;
  2. 指数位:用于存储科学计数法中的指数部分;
  3. 小数位:用于表示小数部分,不足补0

单精度float格式:

符号位指数位小数位
1bit8bits23bits

双精度double格式:

符号位指数位小数位
1bit11bits52bits

float示例:

8.25转化为二进制表示为:整数部分除2取余,小数部分乘2取整,得到1000.01

科学计数法表示为1.00001*2的3次方,指数为3(指数范围为-126-127),为消除负数影响,得到的指数+127,得130,即指数1000 0010,小数:00001,存储格式如下: 

符号位指数位小数位
01000 0010000 0100 0000 0000 0000 0000

3、数据校验算法

由于数据传输距离的因素影响,计算机和受控设备间的通信数据常常出现不可预知的错误,为了避免错误带来的影响,通常会在通信时对数据进行校验。

3.1、奇偶校验

每8位加一个奇偶校验位,

奇校验:若数据位中1的数量为偶数,则校验位置1凑齐奇数个1,反之置0;

偶校验:若数据为中1的数量为奇数,则校验位置1凑齐偶数个1,反之置0;

缺点:减慢传输速率,偶数个错误时检测不出(出错率五五开);

3.2、LRC

纵向冗余校验(Longitudinal Redundancy Check,LRC),又称逐字节奇偶校验,将数据依字节为单位纵向排列,所有字节相同位全部异或(奇数个1为1,反之为0),计算出一个字节的结果。

缺点:纵向偶数个错误时检测不出;

3.3、累加和校验

将数据的每个字节的值相加,其结果减去255的倍数(控制在0-255区间),然后放在数据最后,接收方接收数据后累加和后与校验值比对;

单个字符出错率1/256

3.4、CRC
介绍 

CRC,循环冗余校验,使用的算法思想为除法,将余数作为校验值放在数据末尾;

模二除法(二进制的除法),CRC实际就是模二除法的升级版,通过借位(位移),将余数补在原数据末尾,以此来消掉余数。(接收端将修改后的数据与生成项模二相除没有余数即代表数据无误)

CRC除数叫生成多项式,又称生成项,不同的生成项有不同的CRC,如:CRC8、CRC16、CRC-USB、CRC32……。(二进制转多项式:数字中多少位1代表的是x的多少次方)

模二除法举例: 

模二借位举例:

常用多项式表

CRC-8

CRC-8,8位校验码,适用于对数据简单校验的场景,常见的应用领域包括遥控器、智能家居等,示例如下:

    public static byte CalcCrc8(byte[] data)
    {
        byte crc = 0x00;
        byte polynomial = 0x8C; // CRC-8 多项式
        foreach (byte b in data)
        {
            crc ^= b;
            for (int i = 0; i < 8; i++)
            {
                if ((crc & 0x80) != 0)
                {
                    crc = (byte)((crc << 1) ^ polynomial);
                }
                else
                {
                    crc <<= 1;
                }
            }
        }
        return crc;
    }
CRC-16

CRC-16,16位校验码,适用于中等程度校验场景,常见的应用领域包括Modbus通信协议、SD卡存储等,示例如下:

    public static ushort CalcCrc16(byte[] data)
    {
        ushort crc = 0xFFFF;
        ushort polynomial = 0xA001; // CRC-16 多项式
        foreach (byte b in data)
        {
            crc ^= (ushort)(b << 8);
            for (int i = 0; i < 8; i++)
            {
                if ((crc & 0x01) == 0x01)
                {
                    crc >>= 1;
                    crc ^= polynomial;
                }
                else
                {
                    crc >>= 1;
                }
            }
        }
        return crc;
    }
CRC-32

CRC-32,32位校验码,适用于对数据需高强度校验的场景,常见的应用领域包括网络通信、文件传输、数据库存储等,示例如下:

    public static uint CalcCrc32(byte[] data)
    {
        uint crc = 0xFFFFFFFF;
        uint polynomial = 0xEDB88320; // CRC-32 多项式
        foreach (byte b in data)
        {
            crc ^= b;
            for (int i = 0; i < 8; i++)
            {
                if ((crc & 0x00000001) != 0)
                {
                    crc = (crc >> 1) ^ polynomial;
                }
                else
                {
                    crc >>= 1;
                }
            }
        }
        return ~crc;
    }
CRC-USB

CRC-USB,CRC特殊算法之一,适用于USB接口,例如USB 1.1、USB 2.0等协议中的数据校验,示例如下: 

    public static uint CalcCrcUsb(byte[] data)
    {
        uint crc = 0xFFFFFFFF;
        uint polynomial = 0x04C11DB7; // USB 多项式
        foreach (byte b in data)
        {
            crc ^= (uint)(b << 24);
            for (int i = 0; i < 8; i++)
            {
                if ((crc & 0x80000000) != 0)
                {
                    crc = (crc << 1) ^ polynomial;
                }
                else
                {
                    crc <<= 1;
                }
            }
        }
        return ~crc;
    }

4、Modbus通信协议

4.1、介绍 

Modbus,串行通信协议,属于OSI七层模型中的应用层,最初设计用于可编程逻辑控制器(PLC),Modbus是一种开放式协议,物理层支持使用RS232/RS485/RS422协议的串行设备,同时还支持调制解调器;

Modbus通过设备之间的串行线进行数据传输最简单的设置是使用一根串行电缆连接两个设备(主设备和从设备)上的串行端口;

Modbus遵循主从模式通信,实现主站与一个(单播)或多个(广播)从站交换报文数据,通信由主机发起,一问一答式,从设备无法主动向主机发送数据。

常用类别有Modbus-RTU、Modbus-ASCII、Modbus-TCP,这里主要介绍Modbus-RTU;

4.2、Modbus-RTU

报文格式:

地址码功能码数据CRC-16
1字节1字节n字节2字节

地址码:0为主机广播地址,1-247为从机地址,248-255保留;

功能码:常用功能码如下表:

代码

名称

作用

01

读取线圈状态

取得一组逻辑线圈的当前状态(ON/OFF)

02

读取输入状态

取得一组开关输入的当前状态(ON/OFF)

03

读取保持寄存器

在一个或多个保持寄存器中取得当前的二进制值

04

读取输入寄存器

在一个或多个输入寄存器中取得当前的二进制值

05

强置(写)单线圈

强置一个逻辑线圈的通断状态

06

预置(写)单寄存器

放置一个特定的二进制值到一个单寄存器中

07

读取异常状态

取得8个内部线圈的通断状态

15

强置(写)多线圈

强置一串连续逻辑线圈的通断

16

预置(写)多寄存器

放置一系列特定的二进制值到一系列多寄存器中

17

报告从机标识

可使主机判断编址从机的类型及该从机运行指示灯的状态

数据:通常包括起始地址、数据长度或数据,都为大端模式(低位存于高地址);

CRC校验:通常使用16位校验码,采用小端模式(低位存于低地址);

Modbus-Rtu报文封装示例(仅供参考)

        /// <summary>
        /// MODEBUS_RTU通信数据
        /// </summary>
        /// <param name="devadress">地址码</param>
        /// <param name="funccode">功能码</param>
        /// <param name="paraadress">读/写参数代号地址(起始地址)</param>
        /// <param name="value">读取数据长度或写数据值</param>
        /// <returns></returns>
        public static List<byte> GetModbusData(byte devadress, byte funccode, int paraadress, int value)
        {
            List<byte> data = new List<byte>()
            {
                devadress,
                funccode,
            };

            var high = (paraadress & 0xFF00) >> 8;//高8位
            var low = paraadress & 0xFF;//低8位
            data.Add(Convert.ToByte(high));
            data.Add(Convert.ToByte(low));

            high = (value & 0xFF00) >> 8;
            low = value & 0xFF;
            data.Add(Convert.ToByte(high));
            data.Add(Convert.ToByte(low));

            var res = Crc16.CRC16(data.ToArray());//16位校验
            high = (res & 0xFF00) >> 8;
            low = res & 0xFF;
            data.Add(Convert.ToByte(low));
            data.Add(Convert.ToByte(high));

            return data;
        }

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

五子棋AI算法自动测试方法

先前发了几篇五子棋游戏程序设计的博文&#xff0c;设计了游戏程序&#xff0c;也设计了AI智能奕棋的算法&#xff0c;运行程序检测算法的可行性&#xff0c;完成人机模式游戏功能的设置。 本文主要介绍自动测试算法的方法。 AI智能奕棋的算法testAIq( )&#xff0c;主要是检测…

利用段落检索和生成模型进行开放域问答12.2

利用段落检索和生成模型进行开放域问答 摘要引言2 相关工作3 方法 摘要 事实证明&#xff0c;开放域问答的生成模型具有竞争力&#xff0c;无需借助外部知识。虽然很有希望&#xff0c;但这种方法需要使用具有数十亿个参数的模型&#xff0c;而这些模型的训练和查询成本很高。…

opencv知识库:利用cv2.resize()函数进行图像缩放

引言 在numpy知识库&#xff1a;深入理解numpy.resize函数和数组的resize方法中&#xff0c;小编较为详细地探讨了numpy的resize函数背后的机理。从结果来看&#xff0c;numpy.resize函数并不适合对图像进行缩放操作。而opencv中的resize函数虽然和numpy的resize函数同名&…

结构体||联合体

1.结构体 1.1实际生活中一些东西往往有多个元素组成。如一名学生有身高、体重、名字、学号等。这时候就需要用到结构体。 结构体是一些值的结合&#xff0c;这些值被称为成员变量。结构体的每个成员可以是不同类型的变量&#xff0c;如&#xff1a;标量、数组、指针、甚至是其…

Mysql行格式(记录格式)详解

1.InnoDB行格式简介&#xff1a; 我们平时向表中插入数据&#xff0c;是以行为基本单位&#xff0c;这些行在磁盘上的存储方式成为行格式。在innodb中有四种行格式&#xff1a;Compact、Redundant、Dynamic和Compressed。 默认的行格式是Dynamic: 1.1 Compact行格式 1.1.1 …

Linux 匿名页反向映射

1. 何为反向映射 正向映射&#xff1a; 用户进程在申请内存时&#xff0c;内核并不会立刻给其分配物理内存&#xff0c;而是先为其分配一段虚拟地址空间&#xff0c;当进程访问该虚拟地址空间时&#xff0c;触发page fault异常&#xff0c;异常处理流程中会为其分配物理页面&am…

Docker部署Plik临时文件上传系统并且实现远程访问

文章目录 1. Docker部署Plik2. 本地访问Plik3. Linux安装Cpolar4. 配置Plik公网地址5. 远程访问Plik6. 固定Plik公网地址7. 固定地址访问Plik8. 结语 本文介绍如何使用Linux docker方式快速安装Plik并且结合Cpolar内网穿透工具实现远程访问&#xff0c;实现随时随地在任意设备上…

【预计IEEE出版|EI征稿通知】第六届下一代数据驱动网络国际学术会议 (NGDN 2024)

第六届下一代数据驱动网络国际学术会议 (NGDN 2024) The Sixth International Conference on Next Generation Data-driven Networks 2024年4月26-28日 | 中国沈阳 基于前几届在英国埃克塞特 (ISPA 2020) 、中国沈阳 (TrustCom 2021) 和中国武汉 (IEEETrustCom-2022) 成功举…

【Qt开发流程】之事件系统1:事件系统描述及事件发生流程

Qt的事件系统 在Qt中&#xff0c;事件是对象&#xff0c;派生自抽象的QEvent类&#xff0c;它表示应用程序内部发生的事情或作为应用程序需要知道的外部活动的结果。事件可以由QObject子类的任何实例接收和处理&#xff0c;但它们与小部件特别相关。以下描述了在典型应用程序中…

电子学会C/C++编程等级考试2022年03月(四级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:拦截导弹 某国为了防御敌国的导弹袭击, 发展出一种导弹拦截系统。 但是这种导弹拦截系统有一个缺陷: 虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。 某天, 雷达捕捉到敌国的导弹来袭。…

Java高级技术-反射

认识反射、获取类 获取类的方法 获取类的构造器 获取类的构造器、并对其进行操作 获取构造器的作用&#xff1a;依然是初始化对象返回 获取成员变量 获取成员变量的方法 获取成员变量的作用&#xff1a;赋值、取值 获取类的成员方法 方法 作用&#xff1a;依然是执行 作用、…

什么是DDoS攻击

DDoS攻击 1. 定义2. DDoS攻击类型2.1 网络层攻击2.2 传输层攻击2.3 应用层攻击 3.DDoS攻击态势特点 1. 定义 分布式拒绝服务&#xff08;DDoS&#xff09;攻击是一种常见的网络攻击形式。攻击者利用恶意程序对一个或多个目标发起攻击&#xff0c;企图通过大规模互联网流量耗尽…

【Element-ui】Icon 图标与Button 按钮

文章目录 前言一、Icon 图标1.1 作用1.2 使用方法1.3 图标集合 二、Button 按钮2.1 基础用法2.2 禁用状态2.3 文字按钮2.4 图标按钮2.5 按钮组2.6 加载中2.7 不同尺寸 总结 前言 在前端开发中&#xff0c;界面的设计和交互是至关重要的一部分。一个直观、易用的界面往往离不开…

HarmonyOS应用开发——程序框架UIAbility、启动模式与路由跳转

前言 UIAbility简单来说就是一种包含用户界面的应用组件&#xff0c;用于和用户进行交互。每一个UIAbility实例&#xff0c;对应于一个最近任务列表中的任务。 一个应用可以有一个UIAbility&#xff0c;也可以有多个UIAbility。一个UIAbility可以对应于多个页面&#xff0c;建议…

集成开发环境PyCharm的使用【侯小啾python领航计划系列(三)】

集成开发环境 PyCharm 的使用【侯小啾python领航计划系列(三)】 大家好,我是博主侯小啾, 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ�…

MySQL 性能优化

未完待续... 1. 分库、分表结构优化 1.1 数据库设计 1.2 选择数据类型 1.3 数字类型 1.3.1 整数类型 1.3.2实数类型 1.4 字符串类型 1.4.1 CHAR与VARCHAR 1.4.2 BINARY与VARBINARY 1.4.3 TEXT与BLOB 1.4.4 ENUM类型 1.4.5 SET类型 1.5日期时间类型 1.5.1 日期类型 1.5.2 时间类…

监测tcp连接状态

using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks;namespace 检测tcp连接状态 {public class TCPClient{private TcpClient client;private bool con…

C++核心编程——类与对象基础

C核心编程——类与对象基础 类与对象封装构造函数普通构造拷贝构造初始化成员列表&#xff08;补充&#xff09; 析构函数对象数组对象指针指向对象的指针指向对象成员的指针this指针 静态成员静态数据成员静态成员函数 友元普通函数做友元函数友元成员函数友元类 类与对象 C面…

Fiddler抓包工具之fiddler的composer可以简单发送http协议的请求

一&#xff0c;composer的详解 右侧Composer区域&#xff0c;是测试接口的界面&#xff1a; 相关说明&#xff1a; 1.请求方式&#xff1a;点开可以勾选请求协议是get、post等 2.url地址栏&#xff1a;输入请求的url地址 3.请求头&#xff1a;第三块区域可以输入请求头信息…

Java实战案例————ATM

需求分析 首先ATM银行系统包括两个基础大功能&#xff1a;开户和登陆账户&#xff08;当然在系统中没有一个账户时不能登录&#xff0c;需要先开户&#xff09;。 一名用户有6项基本信息描述&#xff1a;姓名、性别、银行卡号、银行卡密码、账户余额、取款限额。 在登录账户…