Modbus协议与C语言开发14_第1页
Modbus协议与C语言开发14_第2页
Modbus协议与C语言开发14_第3页
Modbus协议与C语言开发14_第4页
Modbus协议与C语言开发14_第5页
已阅读5页,还剩28页未读 继续免费阅读

下载本文档

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

文档简介

1、Modbus协议上海维度信息技术有限公司张伟Modbus是什么?Modbus是一种串行通信协议,是Modicon于1979年,为使用可编程逻辑控制器(PLC)而发表的。MODBUS是工业领域通信协议的业界标准,并且现在是工业电子设备之间相当常用的连接方式为什么使用Modbus?Modbus比其他通信协议使用的更广泛的主要原因有: 公开发表并且无版税要求 相对容易的工业网络部署 对供应商来说,修改移动原生的位元或字节没有很多限制Modbus允许多个设备连接在同一个网络上进行通信,举个例子,一个由测量温度和湿度的装置,并且将结果发送给计算机。在数据采集与监视控制系统(SCADA)中,Modbus通

2、常用来连接监控计算机和Remote Terminal Unit (RTU)。Modbus的版本(1) 串行连接(RS232,RS485需要Linux内核2.6.28以上):Modbus RTU:是一种紧凑的,采用二进制表示数据的方式Modbus ASCII:是一种人类可读的,冗长的表示方式这两个变种都使用串行通讯(serial communication)方式。RTU格式后续的命令数据带有循环冗余校验的校验和;而ASCII格式采用纵向冗余校验的校验和。被配置为RTU变种的节点不会和设置为ASCII变种的节点通信,反之亦然。Modbus的版本(2) Modbus TCP/IP对于通过TCP/IP

3、(例如以太网)的连接,存在多个Modbus/TCP变种,这种方式不需要校验和的计算。Modbus ASCII 帧格式在ASCII模式中,帧以冒号”:”(ASCII码 3A)表示信息的开始;以回车换行”CRLF”(ASCII码 0D和OA)表示信息结束。有的控制器(584、984A/B/C)可以接受没有结束字符串”CRLF”,此时出现1s的时间间隔,控制器也因为是正常中断开始开始地址地址功能功能数据数据LRC校验校验结束结束1个字符2个字符2个字符N个字符2个字符2个字符Modbus RTU 帧格式(1) RTU模式中,信息开始至少需要有3.5个字符的静止时间(依据通讯的波特率,很容易计算这个时

4、间)。接着,第一个区的数据为设备地址。 各区允许发送的字符均为16进制的0-9,A-F。 网络上的设备连续监测网络上的信息,包括静止时间。当接收到第一个地址数据时,每台设备立即对他解码,以决定是否是自己的地址。 发送完最后一个字符后,也有3.5个字符的静止时间,然后才能发送一个新的消息。 整个信息必须连续发送。如果发送帧信息的时间间隔大于1.5个字符的静止时间时,则接收设备刷新不完整的信息,并假定是下一个地址数据。 一个信息发送后,立即发送一个新信息( 没有3.5个字符的静止时间),信息会产生合并,但CRC校验码无效,从而产生错误。Modbus RTU 帧格式(2)开始开始地址地址功能功能数据

5、数据CRC校验校验结束结束T1+T2+T3+T41 byte1 byteN个byte2个byteT1+T2+T3+T4Modbus设备和通讯(1)Modbus协议是一个 master/slave 架构的协议。有一个节点是 master 节点,其他使用Modbus协议参与通信的节点是 slave 节点。每一个 slave 设备都有一个唯一的地址。在串行和MB+网络中,只有被指定为主节点的节点可以启动一个命令(在以太网上,任何一个设备都能发送一个Modbus命令,但 是通常也只有一个主节点设备启动指令)。Modbus设备和通讯(2)一个ModBus命令包含了打算执行的设备的Modbus地址。所有设

6、备都会收到命令,但只有指定位置的设备会执行及回应指令(地址 0例外,指定地址 0 的指令是广播指令,所有收到指令的设备都会执行,不过不回应指令)。所有的Modbus命令包含了检查码,以确定到达的命令没有被破坏。基本的 ModBus命令能指令一个RTU改变它的寄存器的某个值,控制或者读取一个I/O端口,以及指挥设备回送一个或者多个其寄存器中的数据。Modbus大数据中的应用 嵌入式工控板的运行软件主要包括:数据采集、Modbus TCP Proxy和TCP/IP、和服务器通讯三大块。数据采集软件采用定时触发机制编写。定时采集进程将根据上位机派发的配置文件的配置信息采集实时数据上传至上位机;如果网

7、络暂时故障,需要本地缓存实时采集的数据,在通讯故障排除后实现断点续传;Modbus TCP Proxy代理处理相应服务器发来的设备查询请求并返回处理结果;服务器通讯模块将按照实时/响应数据(根据配置文件)向上位服务器发送信息。Modbus大数据数据采集模块 开源库:libmodbus3.1.x 参考代码QModMaster:主站发出命令,等待从站返回数据;监控总线数据http:/ to Modbus/RTU 代理(非libmodbus库)http:/ Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端 Little-Endian就是低位字节排放在内存的低地址端,

8、高位字节排放在内存的高地址端举例(Hex):12 34 56 78 大端:低地址 - 高地址0 x12 | 0 x34 | 0 x56 | 0 x78(字符串的存储模式类似) 小端:低地址 - 高地址0 x78 | 0 x56 | 0 x34 | 0 x12大端和小端模式的内存定义-16位16bit宽的数0 x1234在Little-endian模式(以及Big-endian模式)CPU内存中的存放方式(假设从地址0 x4000开始存放)为:内存地址小端模式存放内容大端模式存放内容0 x40000 x340 x120 x40010 x120 x34大端和小端模式的内存定义-32位32bit宽的

9、数0 x12345678在Little-endian模式以及Big-endian模式)CPU内存中的存放方式(假设从地址0 x4000开始存放)为:内存地址小端模式存放内容大端模式存放内容0 x40000 x780 x120 x40010 x560 x340 x40020 x340 x560 x40030 x120 x78大端和小端模式的优缺点一般操作系统都是小端,而通讯协议是大端的 小端模式 :强制转换数据不需要调整字节内容,1、2、4字节的存储方式一样 大端模式 :符号位的判定固定为第一个字节,容易判断正负数组在大端小端情况下的存储以unsigned int value = 0 x1234

10、5678为例,分别看看在两种字节序下其存储情况,我们可以用unsigned char buf4来表示value:Big-Endian: 低地址存放高位,如下:高地址 - buf3 (0 x78) - 低位 buf2 (0 x56) buf1 (0 x34) buf0 (0 x12) - 高位 - 低地址Little-Endian: 低地址存放低位,如下:高地址 - buf3 (0 x12) - 高位 buf2 (0 x34) buf1 (0 x56) buf0 (0 x78) - 低位 -低地址如何判断机器的字节序(1)BOOLIsBigEndian()inta=0 x1234;charb=*

11、(char*)&a;/通过将通过将int强制类型转换成强制类型转换成char单字节,通过判断起始存储位置。即等于单字节,通过判断起始存储位置。即等于取取b等于等于a的低地址部分的低地址部分if(b=0 x12)returnTRUE;returnFALSE;如何判断机器的字节序(2)联合体union的存放顺序是所有成员都从低地址开始存放,利用该特性可以轻松地获得了CPU对内存采用Little-endian还是Big-endian模式读写:BOOLIsBigEndian()unionNUMinta;charb;num;num.a=0 x1234;if(num.b=0 x12)returnTRUE;

12、returnFALSEC语言浮点的计算(1)32位CPU四个字节表示浮点值:#includeintmain(void)floata=0.0f;unsignedchar*b=(unsignedchar*)&a;intc4;inti=0;/scanf(%x%x%x%x,c+1,c,c+3,c+2);scanf(%x%x%x%x,c,c+1,c+2,c+3);for(i=0;i4;i+)bi=(unsignedchar)ci;printf(%f,a);return0;输入输入a45a42f6的结果是:的结果是:123.320999C语言浮点的计算(2)16位CPU二个字节表示浮点值:#include

13、intmain(void)floata=0.0f;unsignedchar*b=(unsignedchar*)&a;intc2;inti=0;scanf(%x%x,c,c+1);for(i=0;i2;i+)bi=(unsignedchar)ci;printf(%f,a);return0;C语言:strcpy()和memcpy()strcpy()函数只能拷贝字符串。strcpy()函数将源字符串的每个字节拷贝到目录字符串中,当遇到字符串末尾的null字符(0)时,它会删去该字符,并结束拷贝。memcpy()函数可以拷贝任意类型的数据。因为并不是所有的数据都以null字符结束,所以你要为memcp

14、y()函数指定要拷贝的字节数。在拷贝字符串时,通常都使用strcpy()函数;在拷贝其它数据(例如结构)时,通常都使用memcpy()函数。以下是一个使用strcpy()函数和memcpy()函数的例子:C语言:strcpy()/memcpy()举例#include#includetypedefstructcust-strintid;charlast_name20;charfirst_namel5;CUSTREC;voidmain(void)char*src_string=Thisisthesourcestring;chardest_string50;CUSTRECsrc_cust;CUSTR

15、ECdest_cust;/*Copysrc_stringintodest-string.strcpy(dest_string,src_string);printf(Done!dest_stringis:%sn,dest_string);/*First,intializethesrc_custdatamembers.*/src_cust.id=1;strcpy(src_cust.last_name,“Elton);strcpy(src_cust.first_name,“Zhang);/*Now,Usethememcpy()functiontocopythesrc-custstructuretot

16、hedest_custstructure.memcpy(&dest_cust,&src_cust,sizeof(CUSTREC);printf(Done!Ijustcopiedcustomernumber#%d(%s%s).,dest_cust.id,dest_cust.first_name,dest_cust.last_name);C语言:printf()/fprintf()/sprintf()printf、sprintf与fprintf 的用法区分: printf 是和标准输出文件(stdout)关联的。 fprintf是用于文件操作的,fprintf是格式化输出到一个stream,通常是

17、到文件。 sprintf是格式化输出到一个字符串。C语言:printf()/fprintf()/sprintf()举例(1) while (1) / 等待客户端请求 zmq_msg_t request; zmq_msg_init (&request); zmq_recv (responder, &request, 0); printf (收到 Hellon); zmq_msg_close (&request); / 做些“处理” sleep (1); / 返回应答 zmq_msg_t reply; zmq_msg_init_size (&reply, 5); memcpy (zmq_msg_d

18、ata (&reply), World, 5); zmq_send (responder, &reply, 0); zmq_msg_close (&reply); C语言:printf()/fprintf()/sprintf()举例(2) while (1) / 生成数据 int zipcode, temperature, relhumidity; zipcode = randof (100000); temperature = randof (215) - 80; relhumidity = randof (50) + 10; / 向所有订阅者发送消息 char update 20; spr

19、intf (update, %05d %d %d, zipcode, temperature, relhumidity); s_send (publisher, update); C语言:printf()/fprintf()/sprintf()举例(3) FILE *stream; void main( void ) int i = 10; double fp = 1.5; char s = this is a string; char c = n; stream = fopen( fprintf.out, w ); fprintf( stream, %s%c, s, c ); fprintf

20、( stream, %dn, i ); fprintf( stream, %fn, fp ); fclose( stream ); system( type fprintf.out ); C语言:scanf()/fscan()/sscanf() fscanf()会自参数stream的文件流中读取字符串,再根据参数format字符串来转换并格式化数据 scanf()会将输入的数据根据参数format字符串来转换并格式化数据 sscanf()会将参数str的字符串根据参数format字符串来转换并格式化数据。格式转换形式请参考scanf()。转换后的结果存于对应的参数内。C语言: scanf()/

21、fscan()/sscanf()举例(1) int main(void) int i; float fp; char c, s81; printf(Enter an integer, a real number, a character and a string : n); if (scanf(%d %f %c %s, &i, &fp, &c, s) != 4) printf(Not all of the fields were assignedn); else printf(integer = %dn, i); printf(real number = %fn, fp); printf(ch

22、aracter = %cn, c); printf(string = %sn,s); C语言: scanf()/fscan()/sscanf()举例(2) int main(void) char *tokenstring = 15 12 14; int i; float fp; char sSIZE; char c; /* Input various data */ printf(No. of conversions=%dn, sscanf(tokenstring, %s %c%d%f, s, &c, &i, &fp); /* If there were no space between %s and %c, */ /* sscanf would read the fir

温馨提示

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

评论

0/150

提交评论