当前位置: 首页 > news >正文

通信协议_C#实现自定义ModbusRTU主站

背景知识:modbus协议介绍

相关工具

  • mbslave:充当从站。
  • 虚拟串口工具:虚拟出一对串口。
  • VS2022。

实现过程以及Demo

  1. 打开虚拟串口工具:
  2. 打开mbslave:
    从站设置
    在这里插入图片描述
    此处从站连接COM1口。

Demo实现

  1. 创建DLL库,创建ModbusRTU类,进行实现:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.IO.Ports;
using System.Threading;namespace modBusDLL
{public class ModBusRTU{private SerialPort serialPort = null;public ModBusRTU(){serialPort = new SerialPort();}//连接方法//端口号,波特率,数据位,校验位,停止位public void Connect(string portName,int baudRate=9600,int dataBits=8,Parity parity=Parity.None,StopBits stopBits=StopBits.One){ if (serialPort.IsOpen) {serialPort.Close();}serialPort.BaudRate = baudRate;serialPort.PortName = portName;serialPort.Parity = parity;serialPort.StopBits = stopBits;serialPort.DataBits = dataBits;serialPort.Open();}//断开连接方法public void Disconnect(){if (serialPort.IsOpen){serialPort.Close();}}//读消息方法public byte[] ReadKeepRegisters(byte devAdd,ushort start,ushort length){ //拼接报文,发送报文,接受报文,校验报文,解析报文//创建一个字节集合List<byte> ret = new List<byte>();//协议格式:站地址+功能码+起始寄存器地址+寄存器数量+CRC//站地址ret.Add(devAdd);//功能码ret.Add(0x03);//起始寄存器地址//高位地址ret.Add((byte)(start / 256));//低位地址ret.Add((byte)(start % 256));//寄存器数量//高位地址ret.Add((byte)(length / 256));//低位地址ret.Add((byte)(length % 256));byte[] crc= CRCCalc(ret.ToArray());ret.AddRange(crc);//发送报文serialPort.Write(ret.ToArray(), 0, ret.Count);Thread.Sleep(50);//接受长度int byteCount = serialPort.BytesToRead;byte[] data = new byte[byteCount];//读入dataserialPort.Read(data, 0, data.Length);byte[] result = new byte[length*2]; Array.Copy(data,3,result, 0,length*2);return result;}#region 16位CRC校验/// <summary>/// CRC校验,参数data为byte数组/// </summary>/// <param name="data">校验数据,字节数组</param>/// <returns>字节0是高8位,字节1是低8位</returns>public static byte[] CRCCalc(byte[] data){//crc计算赋初始值int crc = 0xffff;for (int i = 0; i < data.Length; i++){crc = crc ^ data[i];for (int j = 0; j < 8; j++){int temp;temp = crc & 1;crc = crc >> 1;crc = crc & 0x7fff;if (temp == 1){crc = crc ^ 0xa001;}crc = crc & 0xffff;}}//CRC寄存器的高低位进行互换byte[] crc16 = new byte[2];//CRC寄存器的高8位变成低8位,crc16[1] = (byte)((crc >> 8) & 0xff);//CRC寄存器的低8位变成高8位crc16[0] = (byte)(crc & 0xff);return crc16;}/// <summary>/// CRC校验,参数为空格或逗号间隔的字符串/// </summary>/// <param name="data">校验数据,逗号或空格间隔的16进制字符串(带有0x或0X也可以),逗号与空格不能混用</param>/// <returns>字节0是高8位,字节1是低8位</returns>public static byte[] CRCCalc(string data){//分隔符是空格还是逗号进行分类,并去除输入字符串中的多余空格IEnumerable<string> datac = data.Contains(",") ? data.Replace(" ", "").Replace("0x", "").Replace("0X", "").Trim().Split(',') : data.Replace("0x", "").Replace("0X", "").Split(' ').ToList().Where(u => u != "");List<byte> bytedata = new List<byte>();foreach (string str in datac){bytedata.Add(byte.Parse(str, System.Globalization.NumberStyles.AllowHexSpecifier));}byte[] crcbuf = bytedata.ToArray();//crc计算赋初始值return CRCCalc(crcbuf);}/// <summary>///  CRC校验,截取data中的一段进行CRC16校验/// </summary>/// <param name="data">校验数据,字节数组</param>/// <param name="offset">从头开始偏移几个byte</param>/// <param name="length">偏移后取几个字节byte</param>/// <returns>字节0是高8位,字节1是低8位</returns>public static byte[] CRCCalc(byte[] data, int offset, int length){byte[] Tdata = data.Skip(offset).Take(length).ToArray();return CRCCalc(Tdata);}#endregion}
}
  1. 在窗体代码中进行调用:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using modBusDLL;namespace easyProjectPractice
{public partial class Form1 : Form{public Form1(){InitializeComponent();this.comboBox1.DataSource=SerialPort.GetPortNames();}private ModBusRTU modBusRTU = new ModBusRTU();private void label1_Click(object sender, EventArgs e){}private void Form1_Load(object sender, EventArgs e){}private void button1_Click(object sender, EventArgs e){modBusRTU.Connect(this.comboBox1.Text);MessageBox.Show("连接成功");}private void button2_Click(object sender, EventArgs e){modBusRTU.Disconnect();MessageBox.Show("断开连接");}private void button3_Click(object sender, EventArgs e){byte[] data = modBusRTU.ReadKeepRegisters(1, 2, 1);textBox1.Text = (data[0] * 256 + data[1]).ToString();}private void textBox1_TextChanged(object sender, EventArgs e){}}
}
  1. 最终可实现通过mdbusRTU协议进行主从站通信:
    在这里插入图片描述
    在这里插入图片描述

总结

简单的modbusRTU主从通信自定义。

接触过的所有通信协议Demo代码

相关文章:

通信协议_C#实现自定义ModbusRTU主站

背景知识&#xff1a;modbus协议介绍 相关工具 mbslave:充当从站。虚拟串口工具:虚拟出一对串口。VS2022。 实现过程以及Demo 打开虚拟串口工具: 打开mbslave: 此处从站连接COM1口。 Demo实现 创建DLL库&#xff0c;创建ModbusRTU类,进行实现&#xff1a; using Syste…...

【C语言】 —— 编译和链接

【C语言】 —— 编译和链接 一、编译环境和运行环境二、翻译环境2.1、 预处理2.2、 编译&#xff08;1&#xff09;词法分析&#xff08;2&#xff09;语法分析&#xff08;3&#xff09;语义分析 2.3、 汇编2.4、链接 三、运行环境 一、编译环境和运行环境 平时我们说写 C语言…...

DNS正向解析与反向解析实验

正向解析 安装bind软件 [rootlocalhost ~]# dnf install bind bind-utils -y修改主配置文件/etc/named.conf [rootlocalhost ~]# vim /etc/named.conf重启DNS服务&#xff08;named&#xff09; [rootlocalhost ~]# systemctl restart named编辑数据配置文件。在/var/named…...

机器学习简介--NLP(二)

机器学习简介 机器学习简介机器学习例子机器学习分类有监督学习有监督学习的应用 无监督学习 机器学习常见概念数据集k折交叉验证过拟合欠拟合评价指标 机器学习简介 机器学习例子 问题&#xff1a; 2&#xff0c;4&#xff0c;6&#xff0c;8&#xff0c;&#xff1f;&#…...

Winform中使用HttpClient实现调用http的post接口并设置传参content-type为application/json示例

场景 Winform中怎样使用HttpClient调用http的get和post接口并将接口返回json数据解析为实体类&#xff1a; Winform中怎样使用HttpClient调用http的get和post接口并将接口返回json数据解析为实体类_winform解析json-CSDN博客 上面使用HttpClient调用post接口时使用的HttpCon…...

【RAG探索第3讲】LlamaIndex的API调用与本地部署实战

原文链接&#xff1a;【RAG探索第3讲】LlamaIndex的API调用与本地部署实战 今天是2024年7月5日&#xff0c;星期五&#xff0c;天气晴&#xff0c;北京。 RAG的文章也看不少了&#xff0c;今天给大家带来一个llamaindex的实战。分为两个部分&#xff0c;调用ChatGLM的API来用l…...

C# —— 日期对象

DateTime 时间类 存储时间对象 可以获取当前时间 DateTime now DateTime.Now;// 获取当前时间 Console.WriteLine("年:" now.Year);//2023 Console.WriteLine("月:" now.Month);//9 Console.WriteLine("日:" now.Day);//12 Console.WriteLi…...

【MySQL04】【 redo 日志】

文章目录 一、前言二、redo 日志1. redo 日志格式2. Mini-Transaction2.1 以组的形式写入 redo 日志2.2 Mini-Transaction &#xff08;MTR&#xff09;概念 3. redo 日志写入过程3.1 redo 日志缓冲区3.3 redo 日志写入 log buffer 4. redo 日志文件4.1 redo 日志刷盘机制4.2 r…...

Android线性布局的概念与属性

线性布局(LinearLayout)是Android中最简单的布局方式&#xff0c;线性布局方式会使得所有在其内部的控件或子布局按一条水平或垂直的线排列。如图所示&#xff0c;图a是纵向线性布局示意图&#xff0c;图b是横向线性布局示意图。 a&#xff09;纵向线性布局示意图 …...

java反射介绍

Java反射API允许你在运行时检查和修改程序的行为。这意味着你可以动态地创建对象、查看类的字段、方法和构造函数&#xff0c;甚至调用它们。这是一个强大的特性&#xff0c;但也应该谨慎使用&#xff0c;因为它可以破坏封装性。 以下是使用Java反射的一些常见用途&#xff1a;…...

Spring中@Transactional的实现和原理

这篇文章写的很详细了&#xff0c;引自脚本之家 Java中SpringBoot的Transactional原理_java_脚本之家...

华为仓颉可以取代 Java 吗?

大家好&#xff0c;我是君哥。 在最近的华为开发者大会上&#xff0c;华为亮相了仓颉编程语言&#xff0c;这是华为历经 5 年&#xff0c;投入大量研发成本沉淀的一门编程语言。 1 仓颉简介 按照官方报告&#xff0c;仓颉编程语言是一款面向全场景智能的新一代编程语言&#…...

性能测试相关理解(一)

根据学习全栈测试博主的课程做的笔记 一、说明 若未特别说明&#xff0c;涉及术语都是jmeter来说&#xff0c;线程数&#xff0c;就是jmeter线程组中的线程数 二、软件性能是什么 1、用户关注&#xff1a;响应时间 2、业务/产品关注&#xff1a;响应时间、支持多少并发数、…...

缓存-分布式锁-原理和基本使用

分布式锁原理和使用 自旋 public Map<String, List<Catelog2Vo>> getCatalogJsonFromDBWithRedisLock() {Boolean b redisTemplate.opsForValue().setIfAbsent(Lock, Lock, Duration.ofMinutes(1));if (!b) {int i 10;while (i > 0) {Object result redisTe…...

判断国内ip

php代码 //是否国内ip function isChinaIP($ip) {saveLog("---isChinaIP----------");$url "https://searchplugin.csdn.net/api/v1/ip/get?ip".$ip;// 发送HTTP请求$response file_get_contents($url);$utf8String mb_convert_encoding($response, &…...

linux修改内核实现禁止被ping(随手记)

概述 Linux默认允许被ping。其主要决定因素为&#xff1a; 内核参数防火墙&#xff08;iptables/firewall&#xff09; 以上的决定因素是与的关系&#xff0c;即需要均满足。 因此&#xff0c;修改linux禁被ping有以上两种方法可以实现。 修改内核文件使禁ping 1. 临时生…...

mac M1安装 VSCode

最近在学黑马程序员Java最新AI若依框架项目开发&#xff0c;里面前端用的是Visual Studio Code 所以我也就下载安装了一下&#xff0c;系统是M1芯片的&#xff0c;安装过程还是有点坑的写下来大家注意一下 1.在appstore中下载 2.在系统终端中输入 clang 显示如下图 那么在终端输…...

代码随想录算法训练营第二十七天 |56. 合并区间 738.单调递增的数字 968.监控二叉树 (可跳过)

56. 合并区间 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 示例 1&#xff1a; 输入&#xff1a;in…...

网络基础:IS-IS协议

IS-IS&#xff08;Intermediate System to Intermediate System&#xff09;是一种链路状态路由协议&#xff0c;最初由 ISO&#xff08;International Organization for Standardization&#xff09;为 CLNS&#xff08;Connectionless Network Service&#xff09;网络设计。…...

Java面试八股之如何提高MySQL的insert性能

如何提高MySQL的insert性能 提高MySQL的INSERT性能可以通过多种策略实现&#xff0c;以下是一些常见的优化技巧&#xff1a; 批量插入&#xff1a; 而不是逐条插入&#xff0c;可以使用单个INSERT语句插入多行数据。例如&#xff1a; INSERT INTO table_name (col1, col2) V…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动

一、前言说明 在2011版本的gb28181协议中&#xff0c;拉取视频流只要求udp方式&#xff0c;从2016开始要求新增支持tcp被动和tcp主动两种方式&#xff0c;udp理论上会丢包的&#xff0c;所以实际使用过程可能会出现画面花屏的情况&#xff0c;而tcp肯定不丢包&#xff0c;起码…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

SpringCloudGateway 自定义局部过滤器

场景&#xff1a; 将所有请求转化为同一路径请求&#xff08;方便穿网配置&#xff09;在请求头内标识原来路径&#xff0c;然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障

关键领域软件测试的"安全密码"&#xff1a;Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力&#xff0c;从金融交易到交通管控&#xff0c;这些关乎国计民生的关键领域…...

通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器

拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件&#xff1a; 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...

Oracle11g安装包

Oracle 11g安装包 适用于windows系统&#xff0c;64位 下载路径 oracle 11g 安装包...

Vue 3 + WebSocket 实战:公司通知实时推送功能详解

&#x1f4e2; Vue 3 WebSocket 实战&#xff1a;公司通知实时推送功能详解 &#x1f4cc; 收藏 点赞 关注&#xff0c;项目中要用到推送功能时就不怕找不到了&#xff01; 实时通知是企业系统中常见的功能&#xff0c;比如&#xff1a;管理员发布通知后&#xff0c;所有用户…...