IoTClient开发5 - ModBusRtu协议
前言
前面我们介绍了ModBusTcp协议。今天我们接着来介绍ModBusRtu协议。和ModBusTcp不同的是ModBusRtu基于串口通信,ModBusTcp是基于Tcp以太网通信。
所以我们在讲解ModBusRtu协议之前会先介绍下串口通信。
串口通信
串口出现在1980年前后,当初主要目的是用来做电脑外设设备的连接,如鼠标、键盘等。现在最新的电脑慢慢的取消了原始的串口接口,不过依然广泛用于工控和测量等设备。
串口通信参数
串口通信指的是串口按位(bit)发送和接收字节,串口通信参数主要有波特率、数据位、停止位、校验位。
波特率
波特率表达的是串口通信的速率,一秒钟内传送的信号单元(码元)个数。信号单元一般包含10位(7个数据位、1个校验位、1到2个停止位)。注意:波特率和距离成反比
数据位
通信中实际的数据,有效值为6、7和8。
停止位
用来表示单个包的最后一位,有效值为1、1.5和2。停止位可用来表示传输的结束和校正时钟同步。注意:停止位的位数越多,时钟同步的容忍程度越大,但是数据传输率会越慢。
校验位
奇偶校验作为通信中的检错方式,如果发现错误则重新发送。
示例数据 | 偶校验位 | 奇校验位 |
---|---|---|
0000000 | 00000000 | 00000001 |
1010001 | 10100011 | 10100010 |
1101001 | 11010010 | 11010011 |
1111111 | 11111111 | 11111110 |
从上可以看出奇偶校验就是在数据最后加一位,使数据中的1的数量保持偶数或奇数。
波特率和比特率 (扩展知识)
比特率是我们常用来表达宽带速率的一种方法。看上去和波特率很像,如果波特率的信号码元只传1比特(bit),那么它们之间是相等的。如果波特率的信号码元传10比特,那么波特率是比特率的10倍。所以,波特率和比特率表达的意义是不一样的,不要搞混了。
宽带比特率的实际下载速度 (扩展知识)
Mbps和Mbit/s等效、kbit/s和kbps等效、bps和bit/s等效
1Mbps(Mbit/s) = 11024kbit(kbit/s) = 11024*1024bps(bit/s),注意他们的单位都是bit(比特),而不是byte(字节),所以实际下载速度要除以八。1024 / 8 = 128 kb/s。
CRC16校验
CRC,Cyclic Redundancy Check循环冗余检验,是基于数据计算一组效验码,用于核对数据传输过程中是否被更改或传输错误。而ModBusRtu用到的是其中的CRC16校验。
其计算原理,可参考 1、2、3
以下是CRC16反向算法,经测试可用于ModBusRtu的CRC计算。
public class CRC16
{
/// <summary>
/// 验证CRC16校验码
/// </summary>
/// <param name="value">校验数据</param>
/// <param name="poly">多项式码</param>
/// <param name="crcInit">校验码初始值</param>
/// <returns></returns>
public static bool CheckCRC16(byte[] value, ushort poly = 0xA001, ushort crcInit = 0xFFFF)
{
if (value == null || !value.Any())
throw new ArgumentException("生成CRC16的入参有误");
var crc16 = GetCRC16(value, poly, crcInit);
if (crc16[crc16.Length - 2] == crc16[crc16.Length - 1] && crc16[crc16.Length - 1] == 0)
return true;
return false;
}
/// <summary>
/// 计算CRC16校验码
/// </summary>
/// <param name="value">校验数据</param>
/// <param name="poly">多项式码</param>
/// <param name="crcInit">校验码初始值</param>
/// <returns></returns>
public static byte[] GetCRC16(byte[] value, ushort poly = 0xA001, ushort crcInit = 0xFFFF)
{
if (value == null || !value.Any())
throw new ArgumentException("生成CRC16的入参有误");
//运算
ushort crc = crcInit;
for (int i = 0; i < value.Length; i++)
{
crc = (ushort)(crc ^ (value[i]));
for (int j = 0; j < 8; j++)
{
crc = (crc & 1) != 0 ? (ushort)((crc >> 1) ^ poly) : (ushort)(crc >> 1);
}
}
byte hi = (byte)((crc & 0xFF00) >> 8); //高位置
byte lo = (byte)(crc & 0x00FF); //低位置
byte[] buffer = new byte[value.Length + 2];
value.CopyTo(buffer, 0);
buffer[buffer.Length - 1] = hi;
buffer[buffer.Length - 2] = lo;
return buffer;
}
}
协议报文分析
数据【读取-请求报文】:01 03 00 04 00 01 C5 CB
- 01 站号
- 03 功能码
- 00 04 读取的寄存器的起始地址
- 00 01 读取寄存器的个数
- C5 CB 为CRC16的校验码【使用上面的CRC16类进行的计算结果,CRC16.GetCRC16([01,03,00,04,00,01])】
数据【读取-响应报文】:01 03 02 00 21 78 5C
- 01 站号
- 03 功能码
- 02 数据的字节长度
- 00 21 数据
- 78 5C 为CRC16的校验码
数据【写入-请求报文】:01 10 00 04 00 01 02 00 21 67 CC
- 01 站号
- 10 功能码
- 00 04 写入的寄存器的起始地址
- 00 01 写入寄存器的个数
- 02 写字节的个数
- 00 21 要写的数据
- 67 CC 为CRC16的校验码
数据【写入-响应报文】:01 10 00 04 00 01 40 08
- 01 站号
- 10 功能码
- 00 04 写入的寄存器的起始地址
- 00 01 写入寄存器的个数
- 40 08 为CRC16的校验码
有了报文的分析,具体的协议实现也就不难了。完整实现可参考https://github.com/zhaopeiym/IoTClient/blob/master/IoTClient/Clients/ModBus/ModBusRtuClient.cs
IoTClient中ModBusRtu协议的使用
安装
Nuget安装 Install-Package IoTClient
或图形化安装
使用
//1、实例化客户端 - [COM端口名称,波特率,数据位,停止位,奇偶校验]
ModBusRtuClient client = new ModBusRtuClient("COM3", 9600, 8, StopBits.One, Parity.None);
//2、写操作 - 参数依次是:地址 、值 、站号 、功能码
client.Write("4", (short)33, 2, 16);
client.Write("4", (short)3344, 2, 16);
//3、读操作 - 参数依次是:地址 、站号 、功能码
var value = client.ReadInt16("4", 2, 3).Value;
var value2 = client.ReadInt32("4", 2, 3).Value;
//4、如果没有主动Open,则会每次读写操作的时候自动打开自动和关闭连接,这样会使读写效率大大减低。所以建议手动Open和Close。
client.Open();
//5、读写操作都会返回操作结果对象Result
var result = client.ReadInt16("4", 2, 3);
//5.1 读取是否成功(true或false)
var isSucceed = result.IsSucceed;
//5.2 读取失败的异常信息
var errMsg = result.Err;
//5.3 读取操作实际发送的请求报文
var requst = result.Requst;
//5.4 读取操作服务端响应的报文
var response = result.Response;
//5.5 读取到的值
var value3 = result.Value;
参考
- 同步至索引目录:《物联网基础组件IoTClient开发系列》
- https://baike.baidu.com/item/串口通信
- https://baike.baidu.com/item/比特率/1022775
- https://zh.wikipedia.org/wiki/奇偶校验位
- https://www.cnblogs.com/esestt/archive/2007/08/09/848856.html
- https://zh.wikipedia.org/wiki/循環冗餘校驗
IoTClient开发5 - ModBusRtu协议的更多相关文章
- IoTClient开发3 - ModBusTcp协议客户端实现
前言 进过前面两章的介绍,今天开始正式的实战. 进制转换 很多朋友对于进制转换可能是在刚学计算机的时候有接触,后来做高级语言开发可能就慢慢忘记了.我们做工控开发的时候需要经常进行进制转换,这里和大家一 ...
- IoTClient开发4 - ModBusTcp协议服务端模拟
前言 上篇我们实现了ModBusTcp协议的客户端读写,可是在很多时候编写业务代码之前是没有现场环境的.总不能在客户现场去写代码,或是蒙着眼睛写然后求神拜佛不出错,又或是在办公室部署一套硬件环境.怎么 ...
- IoTClient开发6 - S7-200SmarTcp协议客户端实现
环境和工具 服务端电脑IP:192.168.1.130 客户端电脑IP:192.168.1.120 1.在服务端电脑运行IoTClientTool 2.运行Wireshark 3.在客户端电脑运行Io ...
- 物联网基础组件IoTClient开发系列
系列目录 IoTClient开发1 - 你也可以写个聊天程序 IoTClient开发2 - 你也可以写个服务器 IoTClient开发3 - ModBusTcp协议客户端实现 IoTClient开发4 ...
- 聊聊 iOS 开发中的协议
前言 何为协议,简单来说在OC中我们使用关键字@protocol可以声明一个协议,并在协议中添加多个属性.方法供于遵循者实现,从某个角度上来说,这是一种不同于category机制的category.在 ...
- 用c++开发基于tcp协议的文件上传功能
用c++开发基于tcp协议的文件上传功能 2005我正在一家游戏公司做程序员,当时一直在看<Windows网络编程> 这本书,把里面提到的每种IO模型都试了一次,强烈推荐学习网络编程的同学 ...
- Loadrunner 脚本开发-利用loadrunner开发Windows Sockets协议脚本
脚本开发-利用loadrunner开发Windows Sockets协议脚本 by:授客 QQ:1033553122 欢迎加入软件性能测试交流QQ群:7156436 实践举例 Socket服务端简单实 ...
- Loadrunner脚本开发-基于HTTP协议的流媒体视频在线播放服务器性能测试
脚本开发-基于HTTP协议的流媒体视频在线播放服务器性能测试 by:授客 QQ:1033553122 目的 实现基于http协议的流媒体在线视频播放,服务器性能测试脚本,模拟用户浏览器方式在线播放 ...
- 使用Jayrock开源组件开发基于JSON-RPC协议的接口
最近接手一个以前的项目,无意间发现此项目开发接口的组件:Jayrock(接口组件估计用的少,用的最多的估计是这个Jayrock.json.dll,用于解析json) 以下是Jayrock的介绍官网: ...
随机推荐
- java property 配置文件管理工具框架,避免写入 property 乱序
property property 是 java 实现的 property 框架. 特点 优雅地进行属性文件的读取和更新 写入属性文件后属性不乱序 灵活定义编码信息 使用 OO 的方式操作 prope ...
- 通过canvas合成图片
通过canvas合成图片 效果图 页面布局部分 两个图片以及一个canvas画布 <img src="https://qnlite.gtimg.com/qqnewslite/20190 ...
- Ubuntu Server16.04 安装Odoo11
odoo11采用了python3实现的. 1.sudo adduser odoo //新建一个用户odoo 2.给odoo 用户root 权限 visudo //使用visudo 编辑 /et ...
- 🙈羞,Spring Bean 初始化/销毁竟然有这么多姿势
文章来源:http://1t.click/bfHN 一.前言 日常开发过程有时需要在应用启动之后加载某些资源,或者在应用关闭之前释放资源.Spring 框架提供相关功能,围绕 Spring Bean ...
- tomcat-9.0.20缓存空间不足
问题2:启动时候报这样的警告:警告 [main] org.apache.catalina.webresources.Cache.getResource 无法将位于[/WEB-INF/classes/t ...
- 执行yaml.load()出现警告信息:YAMLLoadWarning: callingyaml.load() without Loader=..
执行yaml.load()出现警告信息:YAMLLoadWarning: callingyaml.load() without Loader=... 原因: yaml5.1版本后弃用了yaml.loa ...
- 2019-10-9:渗透测试,基础学习the-backdoor-factory-master(后门工厂)初接触
该文章仅供学习,利用方法来自网络文章,仅供参考 the-backdoor-factory-master(后门工制造厂)原理:可执行二进制文件中有大量的00,这些00是不包含数据的,将这些数据替换成pa ...
- PostgreSQL的使用向导
目录 数据库 创建数据库 进入数据库 查看版本 查看当前时间日期 简单的select 获得帮助命令 退出psql客户端 创建表 weather和cities表的创建 删除表 插入数据 数据库导出成cs ...
- 数据降维-NMF非负矩阵分解
1.什么是非负矩阵分解? NMF的基本思想可以简单描述为:对于任意给定的一个非负矩阵V,NMF算法能够寻找到一个非负矩阵W和一个非负矩阵H,使得满足 ,从而将一个非负的矩阵分解为左右两个非负矩阵的乘积 ...
- NPOI插件生成导出word文档
因为之前没有接触NPOI过这个插件,所以几乎都是自己一边百度摸索一边学习. 这个插件对于Excel的数据导入和导出,可以说是很方便了, 但是对于导出word文档,可以说是很少的,百度了很多....也不 ...