C#读取Modbus数据
2015-09-24 18:53
309 查看
最近在做采集的一些任务所以学了一下Modbus通信,学了好几天昨天终于把大概弄明白了,其实简单来说就是客户端向设备发送一个请求报文请求数据,服务器端根据请求报文向客户端端回发一个报文,客户端在接收到响应报文之后对响应报文进行解析,解析之后在将数据存到数据库里或者打印出来。
报文格式:
下面让我们来详细的了解一下这个过程。
首先,做就是在客户端添加一个SOCKET与设备建立连接。说简单点,你不要认为是什么Modbus,就认为是一台电脑,开了SOCKET服务在这里。参考代码如下:
这里IP和端口号都是由设备方提供的。真实程序一般都把这两个参数写配置文件中。
设备连上以后,下一步当然就是读取数据。Modbus的基本原理就是程序向设备请求,需要读取哪个数据,设备就会返回相应的数据。我们知道机器或者说是电脑是只认识01001这样的字符串的。所以所谓的Modbus协议,说得简单一点,就是规定这样一个0101字符各代表什么含义。
下面是核心代码即请求报文和响应报文的代码:
下面对这段代码进行一下解释:
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数组里,然后再对这一串数据进行解析得到想要的数据 。
下面单独对解析过程做一下解释:
下面是几张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#中WinForm窗体事件的执行次序如下:
- C# 生成二维码
- CSharpGL(6)在OpenGL中绘制UI元素
- C#知识体系(二)用案例来理解委托与事件
- C# WindowsForm 员工管理系统二【删除】
- 容易忽略的C#设计模式
- 欢迎使用CSDN-markdown编辑器
- C# Math类
- C#性能优化:延迟初始化Lazy<T>
- C# 将PowerPoint文件转换成PDF文件
- C# 将PPT文件转换成PDF文件
- C# 创建验证码图片
- C#串口操作
- C# WebBrowser 一些方法
- C# struct
- C#格式化数值结果表
- C# 事物
- C# 获取远程xml文件
- 【转】C#结构体和类
- C#插件