C使用TCPIP与ModBus进行通讯_第1页
C使用TCPIP与ModBus进行通讯_第2页
C使用TCPIP与ModBus进行通讯_第3页
C使用TCPIP与ModBus进行通讯_第4页
C使用TCPIP与ModBus进行通讯_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、1. ModBus 的 Client/Server 模型2. 数据包格式及MBAP header (MODBUS Application Protocol header)3. 大小端转换4. 事务标识和缓冲清理5. 示例代码1. ModBus 的 Client/Server 模型Client 与Server之间有两种通讯方式:一种是 TCP/IP,另一种是通过串口 (Serial Port) ,本文重点介绍第一种通讯方式。第二种方式留了接口,暂时还没有实现。2. 数据包格式及MBAP header (MODBUS Application Protocol header)数据包格式数据交换过程中

2、,数据包的格式由三部分组成:协议头+ 功能码 + 数据 ( 请求或接受的数据 ) 。这里主要用到下列两个功能码(十进制):3. 读取寄存器中的值(Read Multiple Register )16: 往寄存器中写值(Write Multiple Register )MBAP header协议头具体包括下列4个字段:Transaction Identifier :事务ID标识,Client每发送一个Request数据包的时 候,需要带上该标识;当 Server响应该请求的时候,会把该标识复制到Response中;这样客户端就可以进行容错判断,防止数据包发审了。(2) Protocal Iden

3、tifier :协议标识,ModBusB议中,该值为 0;Length :整个数据包中,从当个前这个字节之后开始计算,后续数据量的大小(按byte计算)。(4) Unit Identifier : -_-3.大小端转换ModBus使用Big-Endian表示地址和数据项。因此在发送或者接受数据的过程中,需要对数据进行转换。判断大小端对于整数1,在两种机器上有两种不同的标示方式,如上图所示;因此,我们可以用球作符来取其地址,再转换成指向 byte的指针(byte*),最后再取该指针的值;若得到的 byte 值为 1,则为 Little-Endian ,否则为 Big-Endian 。1: uns

4、afe2: 3: int tester = 1;4:bool littleEndian = (*(byte *)(&tester) = ( byte )1;5: 整数/浮点数转换成Byte数组.Net提供了现成的API,可以(value)和(Byte口 data) 来进行转换。下面的代码对该转换进行了封装,加入了 Little-Endian 转Big-Endian的处理(以int为例):1: public class ValueHelper 事务标识和缓冲处理Transaction Identifier上面节中提到,Client每发送一个Request数据包的时候,需要带上一个标识;当

5、Server响应该请求的时候,会把该标识复制到Response中,返回给Client。这样Client就可以用来判断数据包有没有发审。在程序中,可以可以用一个变量及记录该标识:2: private byte dataIndex = 0;3:4: protected byte CurrentDataIndex5: 6: get return ; 7: 8:9: protected byte NextDataIndex()9:10:return +;11: 每次Client发送数据的时候,调用 NextDataIndex()来取得事务标识;接着当 Client读 取Server的返回值的时候,需要

6、判断数据包中的数据标识是否与发送时的标志一致;如 果一致,则认为数据包有效;否则丢掉无效的数据包。缓冲处理上节中提到,如果Client接收到的响应数据包中的标识,与发送给 Server的数据标识 不一致,则认为Server返回的数据包无效,并丢弃该数据包。如果只考虑正常情况,即数据木有差错,Client每次发送请求后,其请求包里面包含需要读取的寄存器数量,能算出从 Server返回的数据两大小,这样 就能确定读完Server 返回的所有缓冲区中的数据;每次交互后,Socket缓冲区中都为空,则整个过程没有问题。但是问题是:如果 Server端出 错,或者数据用包等异常情况下,Client不能确

7、定 Server返回的数据包(占用的缓冲区)有多大;如果缓冲区中的数据没有读完,下次再从 缓冲区中接 着读的时候,数据包必然是不正确的,而且会错误会一直延续到后续的读取 操作中。因此,每次读取数据时,要么全部读完缓冲区中的数据,要么读到错误的时候,就必须 清楚缓冲区中剩余的数据。网上搜了半天,木有找到Windows下如何清 理Socket缓冲区的。有篇文章倒是提到一个狠招,每次读完数据后,直接把Socket给咔嚓掉;然后下次需要读取或发送数据的时候,再重新建立 Socket连接。回过头再来看,其实,在 Client与Server进行交互的过程中,Server每次返回的数据 量都不大,也就一个

8、MBAP Header 十几十个寄存器的值。因此,另一个处理方式,就是每次读取尽可能多的数据(多过缓冲区中的数据量),多读的内容,再忽略掉。暂时这么处理,期待有更好的解决方法。5.源代码类图结构:使用示例写入数据:1:2:3: public override void Send( byte 口 data)4:5:rite Header : MODBUS Application Protocol header16: Identifier)17: ( newByte 0, 0 );20:( byte);存器数量23: ( byte);据的 Byte 数量24:25: 加数据26: (data);

9、数据29:30:31:止连续读写引起前台UI线程阻塞33:34: 取Response:写完后会返回12个byte的结果35: byte 口 responseHeader =36: (2)读取数据:1:=2:3: public override byte 口 Receive。4: 5: ();6: List<byte > sendData = newList< byte >(255);7:8: end9: Identifier)10: ( newByte 0, 0 );13:( byte);止连续读写引起前台UI线程阻塞19: ();20:21: 取 Response H

10、eader :完后会返回 8 个 byte 的 Response Header22: byte receiveData =缓冲区中的数据总量不超过 256byte , 一次读256byte ,防止残余数据影响下次读取32:();23: short identifier = ( short )( short )receiveData0) << 8) +receiveData1);24:25: 取返回数据:根据 ResponseHeadeg读取后续的数据26: if (identifier !=请求的数据标识与返回的标识不一致,则丢掉数据包27: 28: return newByte0;29: 30: byte length = receiveData8;最后一个字节,记录寄存器中数据的Byte数31: byte result = new byte length;32: (receiveData, 9, result, 0, length);33: return result;34: (3)测试发送和

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论