最近在做采集的一些任务所以学了一下Modbus通信,学了好几天昨天终于把大概弄明白了,其实简单来说就是客户端向设备发送一个请求报文请求数据,服务器端根据请求报文向客户端端回发一个报文,客户端在接收到响应报文之后对响应报文进行解析,解析之后在将数据存到数据库里或者打印出来。

报文格式:

下面让我们来详细的了解一下这个过程。

首先,做就是在客户端添加一个SOCKET与设备建立连接。说简单点,你不要认为是什么Modbus,就认为是一台电脑,开了SOCKET服务在这里。参考代码如下:

public static void testframe () {
TcpClient client = new TcpClient ();
client.Connect (IPAddress.Parse ("127.0.0.1"), 5556);
}

这里IP和端口号都是由设备方提供的。真实程序一般都把这两个参数写配置文件中。

设备连上以后,下一步当然就是读取数据。Modbus的基本原理就是程序向设备请求,需要读取哪个数据,设备就会返回相应的数据。我们知道机器或者说是电脑是只认识01001这样的字符串的。所以所谓的Modbus协议,说得简单一点,就是规定这样一个0101字符各代表什么含义。

下面是核心代码即请求报文和响应报文的代码:

 if (client.Connected) {

                NetworkStream sm = client.GetStream ();     // start address = 99 , count = 3
sm.Write (new byte[] {
0x01, 0x00, // transfer flag (little-endian)
0x00, 0x00, // protocol flag
0x00, 0x06, // length (big-endian)
0x01, // device id
0x03, // function code
0x00, 0x63, // start address (big-endian)
0x00, 0x03 // count (big-endian)
}, 0, 12); byte [] frame = new byte [256];
int read_len = sm.Read (frame, 0, frame.Length);
if (read_len > 9) {
Console.WriteLine ("successful in receiving:");
int cnt = (int) frame [8];
for (int i = 0; i < cnt; i += 2) {
uint val = (uint) frame [i + 9];
val <<= 8;
val |= (uint) frame[i + 10];
Console.WriteLine (val);
}
} else if (read_len == 9) {
Console.WriteLine ("rcv error!!");
Console.WriteLine ("error code : " + (frame[7] - 0x80) + frame[8]);
} }

下面对这段代码进行一下解释:

MSDN里对NetworkStream 类的解释是“提供用于网络访问的基础数据流。”,并且“要创建 NetworkStream,必须提供连接的Socket。”。

NetworkStream.Write 方法         //将数据写入 NetworkStream。(发送请求报文)  ,方法里有三个参数分别是

buffer
类型:System.Byte[]
类型 Byte 的数组,该数组包含要写入NetworkStream
的数据。
offset
类型:System.Int32
buffer 中开始写入数据的位置。
size
类型:System.Int32
要写入 NetworkStream 的字节数。

           NetworkStream.Read方法和write方法类似,只不过Read方法接受的是响应报文,并且需要先将接收到的数据存在frame数组里,然后再对这一串数据进行解析得到想要的数据 。
          下面单独对解析过程做一下解释:
                  byte [] frame = new byte [256];    //定义一个标识名为frame的byte类型的数组用于存放接收到的数据流
int read_len = sm.Read (frame, 0, frame.Length); //NetworkStream.Read的返回值是<span><span><span class="sentence" id="mt5">从 <span><a target=_blank href="https://msdn.microsoft.com/zh-cn/library/system.net.sockets.networkstream.aspx" target="_blank">NetworkStream</a></span> 中读取的字节数。</span></span></span>
if (read_len > 9) {
Console.WriteLine ("successful in receiving:");
int cnt = (int) frame [8]; //响应报文的第9个byte表示的是数据部分的长度
for (int i = 0; i < cnt; i += 2) { //i+=2是因为每个数据是2byte
uint val = (uint) frame [i + 9]; //一个数据是2byte,其中前一个byte是高位,后一个byte是低位
val <<= 8; //左移8位将高位的数放入高位
val |= (uint) frame[i + 10]; //微运算,将低位的数与高位的数取或
Console.WriteLine (val);
}
}


下面是几张Modbus报文的图:
请求报文:

响应报文:

C#读取Modbus数据的更多相关文章

  1. java的poi技术读取Excel数据到MySQL

    这篇blog是介绍java中的poi技术读取Excel数据,然后保存到MySQL数据中. 你也可以在 : java的poi技术读取和导入Excel了解到写入Excel的方法信息 使用JXL技术可以在 ...

  2. Hive读取外表数据时跳过文件行首和行尾

    作者:Syn良子 出处:http://www.cnblogs.com/cssdongl 转载请注明出处 有时候用hive读取外表数据时,比如csv这种类型的,需要跳过行首或者行尾一些和数据无关的或者自 ...

  3. 读取数据库数据,并将数据整合成3D饼图在jsp中显示

    首先我将生成饼图的方法独立写成一个PieChar.java类,详细代码如下:(数据库需要自己建,如有需要的话) import java.io.IOException; import java.sql. ...

  4. .NET读取Excel数据,提示错误:未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”提供程序

    解决.NET读取Excel数据时,提示错误:未在本地计算机上注册“Microsoft.ACE.OLEDB.12.0”提供程序的操作: 1. 检查本机是否安装Office Access,如果未安装去去h ...

  5. oledbdataadapter 读取excel数据时,有的单元格内容不能读出

    表现:excel中某列中,有的单元格左上角有绿色箭头标志,有的没有,c#编写读取程序,但是只能读取出带绿色箭头的单元格中的内容,其余不带的读取不到内容 原因:excel中单元格因为是文本格式而存储了数 ...

  6. wcf序列化大对象时报错:读取 XML 数据时,超出最大

    错误为: 访问服务异常:格式化程序尝试对消息反序列化时引发异常: 尝试对参数 http://tempuri.org/ 进行反序列化时出 错: request.InnerException 消息是“反序 ...

  7. Openxml入门---Openxm读取Excel数据

    Openxml读取Excel数据: 有些问题,如果当Cell 里面是 日期和浮点型的话,对应的Cell.DataType==Null,对应的时间会转换为一个浮点型,对于这块可以通过DateTime.F ...

  8. NPOI操作excel之读取excel数据

    NPOI 是 POI 项目的 .NET 版本.POI是一个开源的Java读写Excel.WORD等微软OLE2组件文档的项目.  一.下载引用 去NPOI官网http://npoi.codeplex. ...

  9. [渣译文] 使用 MVC 5 的 EF6 Code First 入门 系列:为ASP.NET MVC应用程序读取相关数据

    这是微软官方教程Getting Started with Entity Framework 6 Code First using MVC 5 系列的翻译,这里是第七篇:为ASP.NET MVC应用程序 ...

随机推荐

  1. SYN2306B型 GPS北斗双模授时板

    SYN2306B型 GPS北斗双模授时板 产品概述 SYN2306B型GPS北斗双模授时板是由西安同步电子科技有限公司精心设计.自行研发生产的一款双模授时板卡,接收北斗或者GPS北斗混合授时卫星信号, ...

  2. java集合框架collection(3)Set、List和Map

    Set.List和Map是java collection中最常用的三种数据结构. Set是集合,不允许有重复的元素,List是动态数组实现的列表,有序可重复,Map是key-value的键值对,用于快 ...

  3. C++虚函数与虚表

    有一定面向对象知识的朋友对继承与多态一定很熟悉,C++想实现继承的话就要使用虚函数,那么什么是虚函数,其原理是什么,下面尽量给大家分析一下C++中其运行机制: 首先,基础,什么是虚函数,什么是多态? ...

  4. 【数据结构--二叉树】Java递归实现二叉树遍历

    参考链接:https://www.cnblogs.com/yaobolove/p/6213936.html 这有一棵树: 1.节点对象 package com.tree.mybinarytree; / ...

  5. Thread中的start()方法和自己定义的run()方法有什么区别

    在讲这个问题之前引入一下多线程的小知识吧 /*/windows系统中的应用程序来做说明 ,例如:扫雷程序,游戏进行的同时,可以同时记录分数,计算时间等. 其实一个应用程序就是一个可执行文件,中包含了一 ...

  6. Codeforces Round #567 (Div. 2)A

    A. Chunga-Changa 题目链接:http://codeforces.com/contest/1181/problem/A 题目 Soon after the Chunga-Changa i ...

  7. WIFI密码破解全攻略

    开篇介绍 目前无线网络加密技术日益成熟.以前的wep加密方式日渐淘汰,因为这种加密方式非常容易破解,当然现在还是有不少使用这种加密方式无线网络.现在大部分的无线网络都是使用wpa/wpa2方式来加密的 ...

  8. 如何将 qsys 子模块设置为参数可调的方式给另外的qsys 调用

    Intel FPGA Quartus 软件中的 Qsys工具 也就是 Platform Designer 系统集成工具,可以 图形化界面操作 使用系统自带ip,自定义ip 系统自动生成 ip 间的连接 ...

  9. 50道SQL练习题及答案与详细分析!!!

    以前在学校还没有很认真地意识到,现在到了企业才发现sql是那么的重要,看到网上有很多的sql 练习题,特地拿来练练手! 数据表介绍 --1.学生表 Student(SId,Sname,Sage,Sse ...

  10. Maven项目读取resources下文件的路径

    要取编译后的路径,而不是你看到的src/main/resources的路径.如下: URL url = 类名.class.getClassLoader().getResource("conf ...