modbus协议及modbus_RTU的C51程序

查看完整版本: [-- modbus协议及modbus RTU的C51程序--]

电子工程师之家-> 51单片机论坛-> modbus协议及modbus RTU的C51程序[打印本页]登录-> 注册-> 回复主

题-> 发表主题

一线工人2007-11-15 21:44 modbus协议及modbus RTU的C51程序

完整的程序请下载[attachment=1488]

Modbus通讯协议

Modbus协议最初由Modicon公司开发出来,在1979年末该公司成为施耐德自动化(Schneider Automation)部门的一部分,现在Modbus已经是工业领域全球最流行的协议。此协议支持传统的RS-232、RS-422、RS-485和以太网设备。许多工业设备,包括PLC,DCS,智能仪表等都在使用Modbus协议作为他们之间的通讯标准。有了它,不同厂商生产的控制设备可以连成工业网络,进行集中监控。

当在网络上通信时,Modbus协议决定了每个控制器须要知道它们的设备地址,识别按地址发来的消息,决定要产生何种行动。如果需要回应,控制器将生成应答并使用Modbus协议发送给询问方。

Modbus 协议包括ASCII、RTU、TCP等,并没有规定物理层。此协议定义了控制器能够认识和使用的消息结构,而不管它们是经过何种网络进行通信的。标准的Modicon控制器使用RS232C实现串行的Modbus。Modbus的ASCII、RTU协议规定了消息、数据的结构、命令和就答的方式,数据通讯采用Maser/Slave方式,Master端发出数据请求消息,Slave端接收到正确消息后就可以发送数据到Master端以响应请求;Master端也可以直接发消息修改Slave端的数据,实现双向读写。

Modbus 协议需要对数据进行校验,串行协议中除有奇偶校验外,ASCII模式采用LRC校验,RTU模式采用16位CRC校验,但TCP模式没有额外规定校验,因为TCP协议是一个面向连接的可靠协议。另外,Modbus采用主从方式定时收发数据,在实际使用中如果某Slave站点断开后(如故障或关机),Master端可以诊断出来,而当故障修复后,网络又可自动接通。因此,Modbus协议的可靠性较好。

下面我来简单的给大家介绍一下,对于Modbus的ASCII、RTU和TCP协议来说,其中TCP和RTU协议非常类似,我们只要把RTU协议的两个字节的校验码去掉,然后在RTU 协议的开始加上5个0和一个6并通过TCP/IP网络协议发送出去即可。所以在这里我仅介绍一下Modbus的ASCII和RTU协议。

下表是ASCII协议和RTU协议进行的比较:协议

开始标记

结束标记

校验

传输效率

程序处理

ASCII

:(冒号)

CR,LF

LRC

直观,简单,易调试

RTU

CRC

不直观,稍复杂

通过比较可以看到,ASCII协议和RTU协议相比拥有开始和结束标记,因此在进行程序处理时能更加方便,而且由于传输的都是可见的ASCII字符,所以进行调试时就更加的直观,另外它的LRC校验也比较容易。但是因为它传输的都是可见的ASCII字符,RTU传输的数据每一个字节ASCII都要用两个字节来传输,比如RTU传输一个十六进制数0xF9,ASCII 就需要传输’F’’9’的ASCII码0x39和0x46两个字节,这样它的传输的效率就比较低。所以一般来说,如果所需要传输的数据量较小可以考虑使用ASCII协议,如果所需传输的数据量比较大,最好能使用RTU协议。

下面对两种协议的校验进行一下介绍。

1、LRC校验

LRC域是一个包含一个8位二进制值的字节。LRC值由传输设备来计算并放到消息帧中,接收设备在接收消息的过程中计算LRC,并将它和接收到消息中LRC域中的值比较,如果两值不等,说明有错误。

LRC校验比较简单,它在ASCII协议中使用,检测了消息域中除开始的冒号及结束的回车换行号外的内容。它仅仅是把每一个需要传输的数据按字节叠加后取反加1即可。下面是它的VC代码:

BYTE GetCheckCode(const char * pSendBuf, int nEnd)//获得校验码

{

BYTE byLrc = 0;

char pBuf[4];

int nData = 0;

for(i=1; i

{

//每两个需要发送的ASCII码转化为一个十六进制数

pBuf [0] = pSendBuf ;

pBuf [1] = pSendBuf [i+1];

pBuf [2] = '\0';

sscanf(pBuf,"%x",& nData);

byLrc += nData;

}

byLrc = ~ byLrc;

byLrc ++;

return byLrc;

}

2、CRC校验

CRC域是两个字节,包含一16位的二进制值。它由传输设备计算后加入到消息中。接收设备重新计算收到消息的CRC,并与接收到的CRC域中的值比较,如果两值不同,则有误。

CRC是先调入一值是全“1”的16位寄存器,然后调用一过程将消息中连续的8位字节各当前寄存器中的值进行处理。仅每个字符中的8Bit数据对CRC有效,起始位和停止位以及奇偶校验位均无效。

CRC 产生过程中,每个8位字符都单独和寄存器内容相或(OR),结果向最低有效位方向移动,最高有效位以0填充。LSB被提取出来检测,如果LSB为1,寄存器单独和预置的值或一下,如果LSB为0,则不进行。整个过程要重复8次。在最后一位(第8位)完成后,下一个8位字节又单独和寄存器的当前值相或。最终寄存器中的值,是消息中所有的字节都执行之后的CRC值。

CRC添加到消息中时,低字节先加入,然后高字节。下面是它的VC代码:

WORD GetCheckCode(const char * pSendBuf, int nEnd)//获得校验码

{

WORD wCrc = WORD(0xFFFF);

for(int i=0; i

{

wCrc ^= WORD(BYTE(pSendBuf));

for(int j=0; j<8; j++)

{

if(wCrc & 1)

{

wCrc >>= 1;

wCrc ^= 0xA001;

}

else

{

wCrc >>= 1;

}

}

}

return wCrc;

}

对于一条RTU协议的命令可以简单的通过以下的步骤转化为ASCII协议的命令:1、把命令的CRC校验去掉,并且计算出LRC校验取代。

2、把生成的命令串的每一个字节转化成对应的两个字节的ASCII码,比如0x03转化成0x30,0x33(0的ASCII码和3的ASCII码)。

3、在命令的开头加上起始标记“:”,它的ASCII码为0x3A。

4、在命令的尾部加上结束标记CR,LF(0xD,0xA),此处的CR,LF表示回车和换行的ASCII 码。

所以以下我们仅介绍RTU协议即可,对应的ASCII协议可以使用以上的步骤来生成。

下表是Modbus支持的功能码:

功能码

名称

作用

01

读取线圈状态

取得一组逻辑线圈的当前状态(ON/OFF)

02

读取输入状态

取得一组开关输入的当前状态(ON/OFF)

03

读取保持寄存器

在一个或多个保持寄存器中取得当前的二进制值

04

读取输入寄存器

在一个或多个输入寄存器中取得当前的二进制值

05

强置单线圈

强置一个逻辑线圈的通断状态

06

预置单寄存器

把具体二进值装入一个保持寄存器

07

读取异常状态

取得8个内部线圈的通断状态,这8个线圈的地址由控制器决定08

回送诊断校验

把诊断校验报文送从机,以对通信处理进行评鉴

09

编程(只用于484)

使主机模拟编程器作用,修改PC从机逻辑

10

控询(只用于484)

可使主机与一台正在执行长程序任务从机通信,探询该从机是否已完成其操作任务,仅在含有功能码9的报文发送后,本功能码才发送

11

读取事件计数

可使主机发出单询问,并随即判定操作是否成功,尤其是该命令或其他应答产生通信错误时

12

读取通信事件记录

可是主机检索每台从机的ModBus事务处理通信事件记录。如果某项事务处理完成,记录会给出有关错误

13

编程(184/384 484 584)

可使主机模拟编程器功能修改PC从机逻辑

14

探询(184/384 484 584)

可使主机与正在执行任务的从机通信,定期控询该从机是否已完成其程序操作,仅在含有功能13的报文发送后,本功能码才得发送

15

强置多线圈

强置一串连续逻辑线圈的通断

16

预置多寄存器

把具体的二进制值装入一串连续的保持寄存器

17

报告从机标识

可使主机判断编址从机的类型及该从机运行指示灯的状态

18

(884和MICRO 84)

可使主机模拟编程功能,修改PC状态逻辑

19

重置通信链路

发生非可修改错误后,是从机复位于已知状态,可重置顺序字节20

读取通用参数(584L)

显示扩展存储器文件中的数据信息

21

写入通用参数(584L)

把通用参数写入扩展存储文件,或修改之

22~64

保留作扩展功能备用

65~72

保留以备用户功能所用

留作用户功能的扩展编码

73~119

非法功能

120~127

保留

留作内部作用

128~255

保留

用于异常应答

在这些功能码中较长使用的是1、2、3、4、5、6号功能码,使用它们即可实现对下位机的数字量和模拟量的读写操作。

1、读可读写数字量寄存器(线圈状态):

计算机发送命令:[设备地址] [命令号01] [起始寄存器地址高8位] [低8位] [读取的寄存器数高8位] [低8位] [CRC校验的低8位] [CRC校验的高8位]

例:[11][01][00][13][00][25][CRC低][CRC高]

意义如下:

<1>设备地址:在一个485总线上可以挂接多个设备,此处的设备地址表示想和哪一个设备通讯。例子中为想和17号(十进制的17是十六进制的11)通讯。

<2>命令号01:读取数字量的命令号固定为01。

<3>起始地址高8位、低8位:表示想读取的开关量的起始地址(起始地址为0)。比如例子中的起始地址为19。

<4>寄存器数高8位、低8位:表示从起始地址开始读多少个开关量。例子中为37个开关量。

<5>CRC校验:是从开头一直校验到此之前。在此协议的最后再作介绍。此处需要注意,CRC校验在命令中的高低字节的顺序和其他的相反。

设备响应:[设备地址] [命令号01] [返回的字节个数][数据1][数据2]...[数据n][CRC校验的低8位] [CRC校验的高8位]

例:[11][01][05][CD][6B][B2][0E][1B][CRC低][CRC高]

意义如下:

<1>设备地址和命令号和上面的相同。

<2>返回的字节个数:表示数据的字节个数,也就是数据1,2...n中的n的值。

<3>数据1...n:由于每一个数据是一个8位的数,所以每一个数据表示8个开关量的值,每一位为0表示对应的开关断开,为1表示闭合。比如例子中,表示20号(索引号为19)开关闭合,21号断开,22闭合,23闭合,24断开,25断开,26闭合,27闭合...如果询问的开关量不是8的整倍数,那么最后一个字节的高位部分无意义,置为0。

<4>CRC校验同上。

2、读只可读数字量寄存器(输入状态):

和读取线圈状态类似,只是第二个字节的命令号不再是1而是2。

3、写数字量(线圈状态):

计算机发送命令:[设备地址] [命令号05] [需下置的寄存器地址高8位] [低8位] [下置的数据高8位] [低8位] [CRC校验的低8位] [CRC校验的高8位]

例:[11][05][00][AC][FF][00][CRC低][CRC高]

意义如下:

<1>设备地址和上面的相同。

<2>命令号:写数字量的命令号固定为05。

<3>需下置的寄存器地址高8位,低8位:表明了需要下置的开关的地址。

<4>下置的数据高8位,低8位:表明需要下置的开关量的状态。例子中为把该开关闭合。注意,此处只可以是[FF][00]表示闭合[00][00]表示断开,其他数值非法。

<5>注意此命令一条只能下置一个开关量的状态。

设备响应:如果成功把计算机发送的命令原样返回,否则不响应。

4、读可读写模拟量寄存器(保持寄存器):

计算机发送命令:[设备地址] [命令号03] [起始寄存器地址高8位] [低8位] [读取的寄存器数高8位] [低8位] [CRC校验的低8位] [CRC校验的高8位]

例:[11][03][00][6B][00][03][CRC低][CRC高]

意义如下:

<1>设备地址和上面的相同。

<2>命令号:读模拟量的命令号固定为03。

<3>起始地址高8位、低8位:表示想读取的模拟量的起始地址(起始地址为0)。比如例子中的起始地址为107。

<4>寄存器数高8位、低8位:表示从起始地址开始读多少个模拟量。例子中为3个模拟量。注意,在返回的信息中一个模拟量需要返回两个字节。

设备响应:[设备地址] [命令号03] [返回的字节个数][数据1][数据2]...[数据n][CRC校验的低8位] [CRC校验的高8位]

例:[11][03][06][02][2B][00][00][00][64][CRC低][CRC高]

意义如下:

<1>设备地址和命令号和上面的相同。

<2>返回的字节个数:表示数据的字节个数,也就是数据1,2...n中的n的值。例子中返回了3个模拟量的数据,因为一个模拟量需要2个字节所以共6个字节。

<3>数据1...n:其中[数据1][数据2]分别是第1个模拟量的高8位和低8位,[数据3][数据4]是第2个模拟量的高8位和低8位,以此类推。例子中返回的值分别是555,0,100。

<4>CRC校验同上。

5、读只可读模拟量寄存器(输入寄存器):

和读取保存寄存器类似,只是第二个字节的命令号不再是2而是4。

6、写单个模拟量寄存器(保持寄存器):

计算机发送命令:[设备地址] [命令号06] [需下置的寄存器地址高8位] [低8位] [下置的数据高8位] [低8位] [CRC校验的低8位] [CRC校验的高8位]

例:[11][06][00][01][00][03][CRC低][CRC高]

意义如下:

<1>设备地址和上面的相同。

<2>命令号:写模拟量的命令号固定为06。

<3>需下置的寄存器地址高8位,低8位:表明了需要下置的模拟量寄存器的地址。

<4>下置的数据高8位,低8位:表明需要下置的模拟量数据。比如例子中就把1号寄存器的值设为3。

<5>注意此命令一条只能下置一个模拟量的状态。

设备响应:如果成功把计算机发送的命令原样返回,否则不响应。

modbus.c

#include "main.h"

//字地址0 - 255 (只取低8位)

//位地址0 - 255 (只取低8位)

/* CRC 高位字节值表*/

const uint8 code auchCRCHi[] = {

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,

0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,

0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,

0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,

0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,

0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,

0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,

0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,

0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40

} ;

/* CRC低位字节值表*/

const uint8 code auchCRCLo[] = {

0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,

0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,

0x43, 0x83, 0x41, 0x81, 0x80, 0x40

} ;

uint8 testCoil; //用于测试位地址1

uint16 testRegister; //用于测试字址址16

uint8 localAddr = 1; //单片机控制板的地址

uint8 sendCount; //发送字节个数

uint8 receCount; //接收到的字节个数

uint8 sendPosi; //发送位置

uint16 crc16(uint8 *puchMsg, uint16 usDataLen)

{

uint8 uchCRCHi = 0xFF ; /* 高CRC字节初始化*/

uint8 uchCRCLo = 0xFF ; /* 低CRC 字节初始化*/

uint32 uIndex ; /* CRC循环中的索引*/

while (usDataLen--) /* 传输消息缓冲区*/

{

uIndex = uchCRCHi ^ *puchMsg++ ; /* 计算CRC */ uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ; uchCRCLo = auchCRCLo[uIndex] ;

}

return (uchCRCHi << 8 | uchCRCLo) ;

}//uint16 crc16(uint8 *puchMsg, uint16 usDataLen) //开始发送

void beginSend(void)

{

b485Send = 1; //设为发送

sendPosi = 0;

if(sendCount > 1)

sendCount--;

ACC = sendBuf[0];

TB8 = P;

SBUF = sendBuf[0];

}//void beginSend(void)

//读线圈状态

void readCoil(void)

{

uint8 addr;

uint8 tempAddr;

uint8 byteCount;

uint8 bitCount;

uint16 crcData;

uint8 position;

uint8 i,k;

uint8 result;

uint16 tempData;

uint8 exit = 0;

//addr = (receBuf[2]<<8) + receBuf[3];

//tempAddr = addr & 0xfff;

addr = receBuf[3];

tempAddr = addr;

//bitCount = (receBuf[4]<<8) + receBuf[5]; //读取的位个数bitCount = receBuf[5];

byteCount = bitCount / 8; //字节个数

if(bitCount%8 != 0)

byteCount++;

for(k=0;k

{//字节位置

position = k + 3;

sendBuf[position] = 0;

for(i=0;i<8;i++)

{

getCoilVal(tempAddr,&tempData);

sendBuf[position] |= tempData << i;

tempAddr++;

if(tempAddr >= addr+bitCount)

{ //读完

exit = 1;

break;

}

}

if(exit == 1)

break;

}

sendBuf[1] = 0x01;

sendBuf[2] = byteCount;

byteCount += 3;

crcData = crc16(sendBuf,byteCount);

sendBuf[byteCount] = crcData >> 8;

byteCount++;

sendBuf[byteCount] = crcData & 0xff;

sendCount = byteCount + 1;

beginSend();

}//void readCoil(void)

//读寄存器

void readRegisters(void)

{

uint8 addr;

uint8 tempAddr;

uint16 result;

uint16 crcData;

uint8 readCount;

uint8 byteCount;

uint8 finsh; //1完成0出错

uint16 i;

uint16 tempData = 0;

//addr = (receBuf[2]<<8) + receBuf[3];

//tempAddr = addr & 0xfff;

addr = receBuf[3];

tempAddr = addr;

//readCount = (receBuf[4]<<8) + receBuf[5]; //要读的个数readCount = receBuf[5];

byteCount = readCount * 2;

for(i=0;i

{

getRegisterVal(tempAddr,&tempData);

sendBuf[i+3] = tempData >> 8;

sendBuf[i+4] = tempData & 0xff;

}

sendBuf[1] = 3;

sendBuf[2] = byteCount;

byteCount += 3;

crcData = crc16(sendBuf,byteCount); sendBuf[byteCount] = crcData >> 8; byteCount++;

sendBuf[byteCount] = crcData & 0xff;

sendCount = byteCount + 1; beginSend();

}//void readRegisters(void)

//强制单个线圈

void forceSingleCoil(void)

{

uint8 addr;

uint8 tempAddr;

uint16 tempData;

uint8 onOff;

uint8 i;

//addr = (receBuf[2]<<8) + receBuf[3]; //tempAddr = addr & 0xfff;

addr = receBuf[3];

tempAddr = addr;

//onOff = (receBuf[4]<<8) + receBuf[5]; onOff = receBuf[4];

//if(onOff == 0xff00)

if(onOff == 0xff)

{ //设为ON

tempData = 1;

}

//else if(onOff == 0x0000)

else if(onOff == 0x00)

{ //设为OFF

tempData = 0;

}

setCoilVal(tempAddr,tempData);

for(i=0;i

{

sendBuf = receBuf;

}

sendCount = receCount;

beginSend();

}//void forceSingleCoil(void)

//设置多个寄存器

void presetMultipleRegisters(void)

{

uint8 addr;

uint8 tempAddr;

uint8 byteCount;

uint8 setCount;

uint16 crcData;

uint16 tempData;

uint8 finsh; //为1时完成为0时出错

uint8 i;

//addr = (receBuf[2]<<8) + receBuf[3];

//tempAddr = addr & 0xfff;

addr = receBuf[3];

tempAddr = addr & 0xff;

//setCount = (receBuf[4]<<8) + receBuf[5]; setCount = receBuf[5];

byteCount = receBuf[6];

for(i=0;i

{

tempData = (receBuf[i*2+7]<<8) + receBuf[i*2+8];

setRegisterVal(tempAddr,tempData);

}

sendBuf[0] = localAddr;

sendBuf[1] = 16;

sendBuf[2] = addr >> 8;

sendBuf[3] = addr & 0xff;

sendBuf[4] = setCount >> 8;

单独传感器标准MODBUS485通讯协议

A、读取数据(标准modbus协议) 地址默认为0x01,可以更改 1、读取数据 主机呼: 0103 00 0000 01 840A 从机答: 0103 02 XX XX XX XX 上面02,XX等均为一个字节。数据为两个字节,高位字节在前。每帧的开头和结尾至少有3。5个字节时间的间隔. 2。读设备地址 0020 CRC (4个字节)(读取:00 20 0068) 00 20 Adress CRC (5个字节) 3.写设备地址 00 10 Adress CRC (5个字节)(地址设为01:00 10 01 BD C0) 00 10CRC?(4个字节)(返回:00 1000 7C) 说明: 1.读写地址命令的地址位必须是00。 2。Adress为1个字节,范围为0-255。 用户在为主机编程时,除了站号(地址)和CRC校验码之外,其它字节的字符均采用上面的内容不变。主机格式中的读取点数为01。从机回答帧中的功能码(03)和读单元字节数(01)不变。

计算CRC码的步骤: 1、预置16位寄存器为十六进制FFFF(即全为1)。称此寄存器为CRC寄存器; 2、把第一个8位数据与16位CRC寄存器的低位相异或,把结果放于CRC寄存器; 3、把寄存器的内容右移一位(朝低位),用0填补最高位,并检查右移后的移出位; 4、如果最低位为0:重复第3步(再次移位) 如果最低位为1:CRC寄存器与多项式A001(10100000 0000 0001)进行异或; 5、重复步骤3和4,直到右移8次,这样整个8位数据全部进行了处理; 6、重复步骤2到步骤5,进行下一步8位数据的处理; 7、最后得到的CRC寄存器即为CRC码; 8、将CRC结果放入信息帧时,将高低位交换,低位在前。 //************************************************************************************************ //**名称:CRC16 //**说明:CRC效验函数 //**形参:*p效验帧的指针帧长 datalen //**返回值:效验字 //************************************************************************************************ unsignedint CRC16(unsigned char * p, uint16 datalen ) { unsigned char CRC16Lo,CRC16Hi,CL,CH,SaveHi,SaveLo; int i,Flag; CRC16Lo =0xFF; CRC16Hi= 0xFF; CL = 0x01; CH= 0xA0; for(i=0;i>= 1 ; //高位右移一位,低位右移一位if ((SaveHi &0x01) ==0x01) //如果高位字节最后一位为1 CRC16Lo|=0x80 ; //则低位字节右移后前面补1否则自动补0 if ((SaveLo&0x01) ==0x01) //如果LSB为1,则与多项式码进行异或 { CRC16Hi^= CH;CRC16Lo ^= CL;} } }

modbus_通讯协议_实例

上海安标电子有限公司 ——PC39A接地电阻仪通信协议 通信协议: 波特率:9600数据位:8校验位:无停止位:1 上位机(计算机): 字节号 1 2 3 4 5 6 7 8 意义ID Command 数据地址V alue CRC 注:1 ID:1个字节,由单机来定(0~255) 2 Command:1个字节,读:3或4,写:6 3 数据地址:2个字节,寄存器地址,读从100开始,写从200开始 4 V alue:2个字节,读:个数(以整型为单位),写:命令/ 数据(以整型为单位) 5 CRC:计算出CRC 下位机(PC39A): 读数据,若正确 字节号 1 2 3 3+N (N=个数*2) 3+N+1 3+N+2 意义ID Command=3 / 4 数据个数数据CRC 注:1 ID:1个字节,由单机来定(0~255) 2 Command:1个字节,收到的上位机命令 3数据个数:1个字节,返回数据个数(以字节为单位) 4 V alue:N个字节,是返回上位机的数据 5 CRC:计算出CRC 写命令,若正确 返回收到的数据: 若错误 字节号 1 2 3 4 5 意义ID Command 数据CRC 注:1 ID:1个字节,由单机来定(0~255) 2 Command:1个字节,收到的上位机命令或上0x80, 如收到3,返回0x83 3数据:1个字节,错误的指令 错误指令 1:表示command不存在 2:表示数据地址超限 4 CRC:计算出CRC

例如读PC39A 电流数据: 机器地址为12,电流的数据地址100,数据为15.45(A) (一个整型数据) 主机: ID Command 数据地址 V alue CRC 16进制 0x0c 0x03 0x0064 0x0001 CRC_H CRC_L 10进制 12 3 100 1 CRC_H CRC_L 从机返回 如正确: ID Command 数据个数(以字节为单位) V alue CRC 16进制 0x0c 0x03 0x002 0x0609 CRC_H CRC_L 10进制 12 3 2 1545 CRC_H CRC_L 如错误: ID Command 数据 CRC 16进制 0x0c 0x83 0x02 CRC_H CRC_L 10进制 12 131 2 CRC_H CRC_L 例如发PC39A 启动命令: 机器地址为12,命令的地址200,数据为25000(25000表示启动) 主机: ID Command 数据地址 V alue CRC 16进制 0x0c 0x06 0x00c8 0x61a8 CRC_H CRC_L 10进制 12 6 200 25000 CRC_H CRC_L 从机返回 如正确: ID Command 数据地址 V alue CRC 16进制 0x0c 0x06 0x00c8 0x61a8 CRC_H CRC_L 10进制 12 6 200 25000 CRC_H CRC_L 如错误: ID Command 数据 CRC 16进制 0x0c 0x86 0x02 CRC_H CRC_L 10进制 12 134 2 CRC_H CRC_L 0011 10000110 错误码0x83 功能码0x06错误码0x86

Modbus协议中文版(比较完善)

GB/T ××××—×××× 前言 -----------串行链路和TCP/IP上的MODBUS标准介绍 该标准包括两个通信规程中使用的MODBUS应用层协议和服务规范: ·串行链路上的MODBUS MODBUS串行链路取决于TIA/EIA标准:232-F和485-A。 ·TCP/IP上的MODBUS MODBUS TCP/IP取决于IETF标准:RFC793和RFC791有关。 串行链路和TCP/IP上的MODBUS是根据相应ISO层模型说明的两个通信规程。 下图强调指出了该标准的主要部分。绿色方框表示规范。灰色方框表示已有的国际标准(TIA/EIA和IETF标准)。 Modbus 协议规范 45页 MODBUS应用层MODBUS报文传输在TCP/IP 上的实现指南49页 在TCP/IP上的MODBUS映射 TCP IETF RFC 793 MODBUS报文IP IETF RFC 791 传输在串行链路 上的实现指南 45页 串行链路主站/从站以太网II/802.3 IEEE 802.2 TIA/EIA-232-F TIA/EI A-485-A 以太网物理层 MODBUS标准分为三部分。第一部分(“Modbus协议规范”)描述了MODBUS事物处理。第二部分(“MODBUS报文传输在TCP/IP上的实现指南”)提供了一个有助于开发者实现TCP/IP上的MODBUS应用层的参考信息。第三部分(“MODBUS报文传 输在串行链路上的实现指南”)提供了一个有助于开发者实现串行链路上的MODBUS 应用层的参考信息。

GB/T ××××—××××第一部分:Modbus协议 1

modbus协议及modbus_RTU的C51程序

查看完整版本: [-- modbus协议及modbus RTU的C51程序--] 电子工程师之家-> 51单片机论坛-> modbus协议及modbus RTU的C51程序[打印本页]登录-> 注册-> 回复主 题-> 发表主题 一线工人2007-11-15 21:44 modbus协议及modbus RTU的C51程序 完整的程序请下载[attachment=1488] Modbus通讯协议 Modbus协议最初由Modicon公司开发出来,在1979年末该公司成为施耐德自动化(Schneider Automation)部门的一部分,现在Modbus已经是工业领域全球最流行的协议。此协议支持传统的RS-232、RS-422、RS-485和以太网设备。许多工业设备,包括PLC,DCS,智能仪表等都在使用Modbus协议作为他们之间的通讯标准。有了它,不同厂商生产的控制设备可以连成工业网络,进行集中监控。 当在网络上通信时,Modbus协议决定了每个控制器须要知道它们的设备地址,识别按地址发来的消息,决定要产生何种行动。如果需要回应,控制器将生成应答并使用Modbus协议发送给询问方。 Modbus 协议包括ASCII、RTU、TCP等,并没有规定物理层。此协议定义了控制器能够认识和使用的消息结构,而不管它们是经过何种网络进行通信的。标准的Modicon控制器使用RS232C实现串行的Modbus。Modbus的ASCII、RTU协议规定了消息、数据的结构、命令和就答的方式,数据通讯采用Maser/Slave方式,Master端发出数据请求消息,Slave端接收到正确消息后就可以发送数据到Master端以响应请求;Master端也可以直接发消息修改Slave端的数据,实现双向读写。 Modbus 协议需要对数据进行校验,串行协议中除有奇偶校验外,ASCII模式采用LRC校验,RTU模式采用16位CRC校验,但TCP模式没有额外规定校验,因为TCP协议是一个面向连接的可靠协议。另外,Modbus采用主从方式定时收发数据,在实际使用中如果某Slave站点断开后(如故障或关机),Master端可以诊断出来,而当故障修复后,网络又可自动接通。因此,Modbus协议的可靠性较好。 下面我来简单的给大家介绍一下,对于Modbus的ASCII、RTU和TCP协议来说,其中TCP和RTU协议非常类似,我们只要把RTU协议的两个字节的校验码去掉,然后在RTU 协议的开始加上5个0和一个6并通过TCP/IP网络协议发送出去即可。所以在这里我仅介绍一下Modbus的ASCII和RTU协议。

modbus协议

编号:_______________本资料为word版本,可以直接编辑和打印,感谢您的下载 modbus协议 甲方:___________________ 乙方:___________________ 日期:___________________

1 . MODBUS 规约 MODBUS规约是MODICOM 公司开发的一个为很多厂商支持的开放规约 Modbus协议是应用于电子控制器上的一种通用语言。通过此协议,控制器相互之间、控制器经由网络(例如以太网)和其它设备之间可以通信。它已经成为一通用工业标准。有了它,不同厂商生产的控制设备可以连成工业网络,进行集中监控。 此协议定义了一个控制器能认识使用的消息结构,而不管它们是经过何种网络进行通 信的。它描述了控制器请求访问其它设备的过程,如果回应来自其它设备的请求,以及怎样 侦测错误并记录。它制定了消息域格局和内容的公共格式。 当在Modbus网络上通信时,此协议决定了每个控制器须要知道它们的设备地址,识别按地址发来的消息,决定要产生何种行动。如果需要回应,控制器将生成反馈信息并用Modbus协议发出。在其它网络上,包含了Modbus协议的消息转换为在此网络上使用的帧或包结构。这种转换也扩展了根据具体的网络解决节地址、路由路径及错误检测的方法。 标准的Modbus 口是使用RS-232C兼容串行接口,它定义了连接口的针脚、电缆、信号 位、传输波特率、奇偶校验。控制器能直接或经由Modem组网。 控制器通信使用主一从技术,即仅设备(主设备)能初始化传输(查询)。其它设备(区设备)根据主设备查询提供的数据做出相应反应。典型的主设备:主机和可编程仪表。典型的从设备:可编程控制器。 主设备可单独和从设备通信, 也能以广播方式和所有从设备通信。如果单独通信,从设住回消息作为回应,如果是以广播方式查询的,则不作任何回应。Modbus协议建立了匕 设备查询的格式:设备(或广播)地址、功能代码、所有要发送的数据、错误检测域。 从设备回应消息也由Modbus协议构成,包括确认要行动的域、任何要返回 的数据、和错误检测域。如果在消息接收过程中发生错误,或从设备不能执行其 命令,从设备将建立错误消息并把它作为回应发送出去。 在其它网络上,控制器使用对等技术通信,故任何控制都能初始和其它控制器的通信。 这样在单独的通信过程中,控制器既可作为主设备也可作为从设备。提供的多个内部通道可 允许同时发生的传输进程。 在消息位,Modbus协议仍提供了主一从原则,尽管网络通信方法是“对等”。

ZNJC2 RS485通讯 modbus 协议

_ MODBUS 通讯协议说明 1. 通讯相关的参数 2.通讯说明 2.1 数据格式说明 控制器采用RS-485总线,协议符合ModBus 规约,数据格式有标准MODBUS-RTU 、 非标准MODBUS-RTU(16进制)和ASC(ASC Ⅱ码)3种格式。 数据传输均采用8位数据位、1位停止位、无奇偶校验位。波特率可设为2400、4800、9600和19200 bit/s 。 通讯传送分为独立的信息头,和发送的编码数据。以下的通讯传送方式定义与RTU 通讯规约相兼容: 2.2 非标准MODBUS-RTU(16进制)数据格式详细说明 下面以RTU(16进制)数据格式进行详细说明,ASC Ⅱ码数据格式只是把16进制代码 转换成ASC Ⅱ码字符。 地址码:这个字节表明由用户设定地址码的从机将接收由主机发送来的信息。并且每个从机都有具有唯一的地址码,并且响应回送均以各自的地址码开始。主机发送的地址码表明将发送到的从机地址,而从机发送的地址码表明回送的从机地址。 功能码:通讯传送的第二个字节。ModBus 通讯规约定义功能号为01H 到7FH 。本控制器利用其中的一部分功能码。作为主机请求发送,通过功能码告诉从机执行什么动作。作为从机响应,从机发送的功能码与从主机发送来的功能码一样,并表明从机已响应主机进行操作。如果从机发送的功能码的

最高位 (比如功能码大于7FH),则表明从机没有响应操作或发送出错。 数据区:数据区是根据不同的功能码而不同。 CRC码:二字节的错误检测码。 当通讯命令发送至仪器时,符合相应地址码的设备接通讯命令,并除去地址码,读取信息,如果没有出错,则执行相应的任务;然后把执行结果返送给发送者。返送的信息中包括地址码、执行动作的功能码、执行动作后结果的数据以及错误校验码。如果出错就不发送任何信息。 2.2.2 信息帧格式: (1)地址码: 地址码是信息帧的第一字节(8位),从1到255。这个字节表明由用户设置地址的从机将接收由主机发送来的信息。每个从机都必须有唯一的地址码,并且只有符合地址码的 从机才能响应回送。当从机回送信息时,相当的地址码表明该信息来自于何处。 (2)功能码: 主机发送的功能码告诉从机执行什么任务。表2列出的功能码都有具体的含义及操作。 (3 数据区包含需要从机执行什么动作或由从机采集的返送信息。这些信息可以是数值、参考地址等等。例如,功能码告诉从机读取寄存器的值,则数据区必需包含要读取寄存器 的起始地址及读取长度。对于不同的从机,地址和数据信息都不相同。 (4)错误校验码: 主机或从机可用校验码进行判别接收信息是否出错。有时,由于电子噪声或其它一些干扰,信息在传输过程中会发生细微的变化,错误校验码保证了主机或从机对在传送过程 中出错的信息不起作用。这样增加了系统的安全和效率。错误校验采用CRC-16校验方法。 注: 信息帧的格式都基本相同:地址码、功能码、数据区和错误校验码。 2.2.3 错误校验 参与冗余循环码(CRC)计算的包括:地址码、功能码、数据区的字节。 冗余循环码包含2个字节,即16位二进制。CRC码由发送设备计算,放置于发送信息的尾部。接收信息的设备再重新计算接收到信息的 CRC码,比较计算得到的CRC码是否与接收到的相符,如果两者不相符,则表明出错。 CRC码的计算方法是,先预置16位寄存器全为1。再逐步把每8位数据信息进行处理。在进行CRC码计算时只用8位数据位,起始位及停止位,如有奇偶校验位的话也包括奇偶校验位,都不参与CRC码计算。 在计算CRC码时,8位数据与寄存器的数据相异或,得到的结果向低位移一字节,用0填补最高位。再检查最低位,如果最低位为1,把寄存器的内容与预置数相异或,如果最低位为0,不进行异或运算。 这个过程一直重复8次。第8次移位后,下一个8位再与现在寄存器的内容相异或,这个过程与以上一样重复8次。当所有的数据信息处理完后,最后寄存器的内容即为CRC码值。 计算CRC码的步骤为: (1).预置16位寄存器为十六进制FFFF(即全为1)。称此寄存器为CRC寄存器; (2).把第一个8位数据与16位CRC寄存器的低位相异或,把结果放于CRC寄存器; (3).把寄存器的内容右移一位(朝低位),用0填补最高位,检查最低位(注意:这时的最低位指移位前 的最低位,不是移位后的最低位); (4).如果最低位为0:重复第3步(再次移位)

MODBUS协议说明文档

MODBUS通讯协议说明 1、概述 Modbus 协议是应用于电子控制器上的一种通用语言。通过此协议,控制器相互之间、控制器经由网络(例如以太网)和其它设备之间可以通信。它已经成为一通用工业标准。有了它,不同厂商生产的控制设备可以连成工业网络,进行集中监控。 本文档通信协议说明详细地描述了MODBUS设备的输入和输出命令、信息和数据,以便第三方使用和开发。 1.1通信协议的作用 使信息和数据在上位机(主站)和MODBUS设备之间有效地传递,允许访问MODBUS设备的所有测量数据。 MODBUS设备可以实时采集现场各种数据值,具备一个RS485通讯口,能满足MODBUS监控系统的要求。 MODBUS设备通信协议采用MODBUS RTU协议,本协议规定了应用系统中主机与MODBUS 设备之间,在应用层的通信协议,它在应用系统中所处的位置如下图所示: 本协议所处的位置 从机: 1.2 物理接口: 连接上位机的主通信口,采用标准串行RS485通讯口,使用压接底座。 信息传输方式为异步方式,主要配置参数,一般默认:起始位1位,数据位8位,停止位1位,无校验,数据传输缺省速率为9600b/s 2、MODBU通信协议详述 2.1 协议基本规则 以下规则确定在回路控制器和其他串行通信回路中设备的通信规则。 1)所有回路通信应遵照主/从方式。在这种方式下,信息和数据在单个主站和从站(监控设备)之间传递。 2)主站将初始化和控制所有在通信回路上传递的信息。 3)无论如何都不能从一个从站开始通信。 4)所有环路上的通信都以“打包”方式发生。一个包裹就是一个简单的字符串(每个字符串8位),一个包裹中最多可含255个字节。组成这个包裹的字节构成标准异步串行数据,并按8位数据位,1位停止位,无校验位的方式传递。串行数据流由类似于RS232C中使用的设备产生。 5)所有回路上的传送均分为两种打包方式: A) 主/从传送 B) 从/主传送 6)若主站或任何从站接收到含有未知命令的包裹,则该包裹将被忽略,且接收站不予响应。

基于Modbus协议实现单片机与PLC之间的通讯

基于Modbus协议实现单片机与PLC之间的通讯 来源:PLC&FA 作者:蔡晓燕赵兴群万遂人董鹏云 关键词:可编程控制器 Modbus 通讯协议 1 引言 HMI(人机界面)以其体积小,高性能,强实时等特点,越来越多的应用于工业自动化系统和设备中。它有字母、汉字、图形和图片等不同的显示,界面简单友好。配有长寿命的薄膜按钮键盘,操作简单。它一般采用具有集成度高、速度快、高可靠且价格低等优点的单片机[1]作为其核心控制器,以实现实时快速处理。PLC和单片机结合不仅可以提PLC的数据处理能力,还可以给用户带来友好简洁的界面。本文以Modbus通讯协议为例,详细讨论了一个人机系统中,如何用C51实现单片机和PLC之间通讯的实例。 2 Modbus通讯协议[4] Modbus协议是应用于电子控制器上的一种通用语言。通过此协议,控制器相互之间、控制器经由网络和其它设备之间可以通信。 Modbus协议提供了主—从原则,即仅一设备(主设备)能初始化传输(查询)。其它设备(从设备)根据主设备查询提供的数据作出相应反应。主设备查询的格式:设备地址(或广播,此时不需要回应)、功能代码、所有要发送的数据、和一错误检测域。从设备回应消息包括确认地址、功能码、任何要返回的数据、和一错误检测域。如果在消息接收过程中发生一错误,或从设备不能执行其命令,从设备将建立一错误消息并把它作为回应发送出去。 控制器能设置为两种传输模式:ASCII和RTU,在同样的波特率下,RTU可比ASCII方式传送更多的数据,所以采用KTU模式。 (1) 典型的RTU消息帧 典型的RTU消息帧如表1所示。

RTU消息帧的地址域包含8bit。可能的从设备地址是0...127(十进制)。其中地址0是用作广播地址,以使所有的从设备都能认识。主设备通过将要联络的从设备的地址放入消息中的地址域来选通从设备。当从设备发送回应消息时,它把自己的地址放入回应的地址域中,以便主设备知道是哪一个设备作出回应。 RTU消息帧中的功能代码域包含了8bits,当消息从主设备发往从设备时,功能代码域将告之从设备需要执行哪些行为;当从设备回应时,它使用功能代码域来指示是正常回应(无误)还是有某种错误发生(称作异议回应,一般是将功能码的最高位由0改为1)。 从主设备发给从设备消息的数据域包含附加的信息:从设备必须用于进行执行由功能代 码所定义的行为。这包括了像不连续的寄存器地址,要处理项的数目,域中实际数据字节数。如果没有错误发生,从从设备返回的数据域包含请求的数据。如果有错误发生,此域包含一异议代码,主设备应用程序可以用来判断采取下一步行动。 当选用RTU模式作字符帧时,错误检测域包含一16Bits值(用两个8位的字符来实现)。错误检测域的内容是通过对消息内容进行循环冗长检测(CRC)方法得出的。CRC域附加在消息的最后,添加时先是低字节然后是高字节。 (2) 所有的Modbus功能码 Modbus的功能码定义如表2所示。

Modbus RTU通讯协议

要实现Modbus RTU通信, 一、需要STEP 7-Micro/WIN32 V3.2以上版本的编程软件,而且须安装STEP 7-Micro/WIN32 V3.2 Instruction Library(指令库)。Modbus RTU功能是通过指令库中预先编好的程序功能块实现的。 Modbus RTU从站指令库只支持CPU上的通信0口(Port0) 基本步骤: 1. 检查Micro/WIN的软件版本,应当是STEP 7-Micro/WIN V3.2以上版本。 2. 检查Micro/WIN的指令树中是否存在Modbus RTU从站指令库(图1),库中应当 包括MBUS_INIT和MBUS_SLAVE两个子程序。 如果没有,须安装Micro/WIN32 V3.2的Instruction Library(指令库)软件包; 1. 西门子编程时使用SM0.1调用子程序MBUS_INIT进行初始化,使用SM0.0调用 MBUS_SLAVE,并指定相应参数。 关于参数的详细说明,可在子程序的局部变量表中找到; 调用Modbus RTU通信指令库图中参数意义如下: a. 模式选择:启动/停止Modbus,1=启动;0=停止 b. 从站地址:Modbus从站地址,取值1~247 c. 波特率:可选1200,2400,4800,9600,19200,38400,57600,115200 d. 奇偶校验:0=无校验;1=奇校验;2=偶校验 e. 延时:附加字符间延时,缺省值为0 f. 最大I/Q位:参与通信的最大I/O点数,S7-200的I/O映像区为128/128, 缺省值为128 g. 最大AI字数:参与通信的最大AI通道数,可为16或32 h. 最大保持寄存器区:参与通信的V存储区字(VW) i. 保持寄存器区起始地址:以&VBx指定(间接寻址方式) j. 初始化完成标志:成功初始化后置1

MODBUS协议(功能码及报文解析)

MODBUS协议 Modbus是一种串行通信协议,是Modicon于1979年,为使用可编程逻辑控制器(PLC)而发表的。事实上,它已经成为工业领域通信协议标准,并且现在是工业电子设备之间相当常用的连接方式。M odbus比其他通信协议使用的更广泛的主要原因有: 公开发表并且无版税要求 相对容易的工业网络部署 对供应商来说,修改移动原生的位或字节没有很多限制 Modbus允许多个设备连接在同一个网络上进行通信,举个例子,一个由测量温度和湿度的装置,并且将结果发送给计算机。在数据采集与监视控制系统(SCADA)中,Modbus通常用来连接监控计算机和remote terminal unit (RTU)。 Modbus协议目前存在用于串口、以太网以及其他支持互联网协议的网络的版本。 大多数Modbus设备通信通过串口EIA-485物理层进行[1]。 对于串行连接,存在两个变种,它们在数值数据表示不同和协议细节上略有不同。Modbus RTU是一种紧凑的,采用二进制表示数据的方式,Modbus ASCII是一种人类可读的,冗长的表示方式。这两个变种都使用串行通讯(serial communication)方式。RTU格式后续的命令/数据带有循环冗余校验的校验和,而ASCII格式采用纵向冗余校验的校验和。被配置为RTU变种的节点不会和设置为ASCII变种的节点通信,反之亦然。

对于通过TCP/IP(例如以太网)的连接,存在多个Modbus/TCP 变种,这种方式不需要校验和的计算。 对于所有的这三种通信协议在数据模型和功能调用上都是相同的,只有封装方式是不同的。 Modbus 有一个扩展版本 Modbus Plus(Modbus+或者MB+),不过此协定是Modicon专有的,和 Modbus不同。它需要一个专门的协处理器来处理类似HDLC的高速令牌旋转。它使用1Mbit/s的双绞线,并且每个节点都有转换隔离装置,是一种采用转换/边缘触发而不是电压/水平触发的装置。连接Modbus Plus到计算机需要特别的接口,通常是支持ISA(SA85),PCI或者PCMCIA总线的板卡。 Modbus协议是一个 master/slave 架构的协议。有一个节点是master 节点,其他使用Modbus协议参与通信的节点是 slave 节点。每一个 slave 设备都有一个唯一的地址。在串行和MB+网络中,只有被指定为主节点的节点可以启动一个命令(在以太网上,任何一个设备都能发送一个Modbus命令,但是通常也只有一个主节点设备启动指令)。 一个ModBus命令包含了打算执行的设备的Modbus地址。所有设备都会收到命令,但只有指定位置的设备会执行及回应指令(地址 0例外,指定地址 0 的指令是广播指令,所有收到指令的设备都会执行,不过不回应指令)。所有的Modbus命令包含了检查码,以确定到达的命令没有被破坏。基本的ModBus命令能指令一个RTU改变

什么是ModBusRTU通讯协议

什么是ModBusRTU通讯协议 Modbus协议最初由Modicon公司开发出来,在1979年末该公司成为施耐德自动化(Schneider Automation)部门的一部分,现在Modbus已经是工业领域全球最流行的协议。此协议支持传统的RS-232、RS-422、RS-485和以太网设备。许多工业设备,包括PLC,DCS,智能仪表等都在使用Modbus协议作为他们之间的通讯标准。有了它,不同厂商生产的控制设备可以连成工业网络,进行集中监控。 当在网络上通信时,Modbus协议决定了每个控制器须要知道它们的设备地址,识别按地址发来的消息,决定要产生何种行动。如果需要回应,控制器将生成应答并使用Modbus协议发送给询问方。 Modbus协议包括ASCII、RTU、TCP等,并没有规定物理层。此协议定义了控制器能够认识和使用的消息结构,而不管它们是经过何种网络进行通信的。标准的Modicon控制器使用RS232C实现串行的Modbus。Modbus的ASCII、RTU协议规定了消息、数据的结构、命令和就答的方式,数据通讯采用Maser/Slave方式,Master端发出数据请求消息,Slave端接收到正确消息后就可以发送数据到Master端以响应请求;Master端也可以直接发消息修改Slave 端的数据,实现双向读写。

Modbus协议需要对数据进行校验,串行协议中除有奇偶校验外,ASCII模式采用LRC校验,RTU模式采用16位CRC校验,但TCP模式没有额外规定校验,因为TCP协议是一个面向连接的可靠协议。另外,Modbus采用主从方式定时收发数据,在实际使用中如果某Slave站点断开后(如故障或关机),Master端可以诊断出来,而当故障修复后,网络又可自动接通。因此,Modbus协议的可靠性较好。 对于Modbus的ASCII、RTU和TCP协议来说,其中TCP和RTU协议非常类似,我们只要把RTU协议的两个字节的校验码去掉,然后在RTU协议的开始加上5个0和一个6并通过TCP/IP 网络协议发送出去即可。 (一)、通讯传送方式: 通讯传送分为独立的信息头,和发送的编码数据。以下的通讯传送方式定义也与ModBusRTU通讯规约相兼容: 初始结构= ≥4字节的时间 地址码= 1 字节 功能码= 1 字节 数据区= N 字节 错误校检= 16位CRC码

基于tcpip协议的Modbus

基于tcp/ip协议的modbus 业以太网与Modbus TCP/IP 一以太网的标准 以太网是一种局域网。早期标准为IEEE802.3,数据链路层使用CSMA/CD,10Mb/s 速度物理层有: (1)10Base5粗同轴电缆,RG-8,一段最长为500m; (2)10Base2细同轴电缆,RG-58,一段最长为185m; (3)10Base T双绞线,UTP或STP,一段最长为100m。 快速以太网为100Mb/s,标准为802.3a,介质为100Base Tx双绞线、100Base Fx光纤。 目前10/100M以太网使用最为普遍,很多企事业用户已实现100M到以太网桌面,确实体验到高速“冲浪”的快感,另外从距离而言,非屏蔽双绞线(UTP)为100m,多模光纤可达2~3km,单模光纤可大于100km。千兆以太网1000Mb/s为802.3z/802.3ab,万兆以太网10Gb/s 为802.3ae,将为新一轮以太网的发展带来新的机遇与冲击。 二工业以太网与商用以太网的区别 什么是工业以太网?技术上,它与IEEE802.3兼容,故从逻辑上可把商用网和工业网看成是一个以太网,而用户可根据现场情况,灵活装配自己的网络部件,但从工业环境的恶劣和抗干扰的要求,设计者希望采用市场上可找到的以太网芯片和媒介,兼顾考虑下述工业现场的特殊要求:首先要考虑高温、潮湿、振动;二是对工业抗电磁干扰和抗辐射有一定要求,如满足EN50081-2、EN50082-2标准,而办公室级别的产品未经这些工业标准测试,表1列出了一些常用工业标准。为改善抗干扰性和降低辐射,工业以太网产品多使用多层线路板或双面电路板,且外壳采用金属如铸铝屏蔽干扰;三是电源要求,因集线器、交换机、收发器多为有源部件,而现场电源的品质又较差,故常采用双路直流电或交流电为其供电,另外考虑方便安装,工业以太网产品多数使用DIN导轨或面板安装;四是通信介质选择,在办公室环境下多数配线使用UTP,而在工业环境下推荐用户使用STP(带屏蔽双绞线)和光纤。

(完整版)MODBUS通讯协议-RTU要点

Modbus 通讯协议 (RTU传输模式)本说明仅做内部参考,详细请参阅英文版本。

第一章Modbus协议简介 Modbus 协议是应用于电子控制器上的一种通用语言。通过此协议,控制器相互之间、控制器经由网络(例如以太网)和其它设备之间可以通信。它已经成为一通用工业标准。有了它,不同厂商生产的控制设备可以连成工业网络,进行集中监控。 此协议定义了一个控制器能认识使用的消息结构,而不管它们是经过何种网络进行通信的。它描述了一控制器请求访问其它设备的过程,如果回应来自其它设备的请求,以及怎样侦测错误并记录。它制定了消息域格局和内容的公共格式。 当在一Modbus网络上通信时,此协议决定了每个控制器须要知道它们的设备地址,识别按地址发来的消息,决定要产生何种行动。如果需要回应,控制器将生成反馈信息并用Modbus协议发出。在其它网络上,包含了Modbus协议的消息转换为在此网络上使用的帧或包结构。这种转换也扩展了根据具体的网络解决节地址、路由路径及错误检测的方法。 协议在一根通讯线上使用应答式连接(半双工),这意味着在一根单独的通讯线上信号沿着相反的两个方向传输。首先,主计算机的信号寻址到一台唯一的终端设备(从机),然后,在相反的方向上终端设备发出的应答信号传输给主机。协议只允许在主计算机和终端设备之间,而不允许独立的设备之间的数据交换,这就不会在使它们初始化时占据通讯线路,而仅限于响应到达本机的查询信号。 1.1 传输方式 传输方式是一个信息帧内一系列独立的数据结构以及用于传输数据的有限规则,以RTU 模式在Modbus总线上进行通讯时,信息中的每8位字节分成2个4位16进制的字符,每个信息必须连续传输下面定义了与Modebus 协议– RTU方式相兼容的传输方式。 代码系统 ?8位二进制,十六进制数0...9,A...F ?消息中的每个8位域都是一个两个十六进制字符组成 每个字节的位 ?1个起始位 ?8个数据位,最小的有效位先发送 ?1个奇偶校验位,无校验则无 ?1个停止位(有校验时),2个Bit(无校验时) 错误检测域 ?CRC(循环冗长检测)

MODBUS-RTU通讯协议简介

MODBUS-RTU通讯协议简介 2008-10-10 17:27 1.1 Modbus协议简述 ACRXXXE系列仪表使用的是Modbus-RTU通讯协议,MODBUS协议详细定义了校验码、数据序列等,这些都是特定数据交换的必要内容。MODBUS协议在一根通讯线上使用主从应答式连接(半双工),这意味着在一根单独的通讯线上信号沿着相反的两个方向传输。首先,主计算机的信号寻址到一台唯一的终端设备(从机),然后,终端设备发出的应答信号以相反的方向传输给主机。 Modbus协议只允许在主机(PC,PLC等)和终端设备之间通讯,而不允许独立的终端设备之间的数据交换,这样各终端设备不会在它们初始化时占据通讯线路,而仅限于响应到达本机的查询信号。 1.2 查询—回应周期 1.2.1 查询 查询消息中的功能代码告之被选中的从设备要执行何种功能。数据段包含了从设备要执行功能的任何附加信息。例如功能代码03是要求从设备读保持寄存器并返回它们的内容。数据段必须包含要告之从设备的信息:从何寄存器开始读及要读的寄存器数量。错误检测域为从设备提供了一种验证消息内容是否正确的方法。 1.2.2 回应 如果从设备产生一正常的回应,在回应消息中的功能代码是在查询消息中的功能代码的回应。数据段包括了从设备收集的数据:如寄存器值或状态。如果有错误发生,功能代码将被修改以用于指出回应消息是错误的,同时数据段包含了描述此错误信息的代码。错误检测域允许主设备确认消息内容是否可用。 1.3 传输方式 传输方式是指一个数据帧内一系列独立的数据结构以及用于传输数据的有限规则,下面定义了与Modbus 协议– RTU方式相兼容的传输方式。 每个字节的位: · 1个起始位 · 8个数据位,最小的有效位先发送 ·无奇偶校验位 · 1个停止位 错误检测(Error checking):CRC(循环冗余校验) 1.4 协议 当数据帧到达终端设备时,它通过一个简单的“端口”进入被寻址到的设备,该设备去掉数据帧的“信封”(数据头),读取数据,如果没有错误,就执行数据所请求的任务,然后,它将自己生成的数据加入到取得的“信封”中,把数据帧返回给发送者。返回的响应数据中包含了以下内容:终端从机地址(Address)、被执行了的命令(Function)、执行命令生成的被请求数据(Data)和一个校验码(Check)。发生任何错误都不会有成功的响应,或者返回一个错误指示帧。 1.4.1 数据帧格式 Address Function Data Check 8-Bits 8-Bits N x 8-Bits 16-Bits 1.4.2 地址(Address)域 地址域在帧的开始部分,由一个字节(8位二进制码)组成,十进制为0~255,

RS485通信和Modbus协议实例分析

18.1 RS485通信 实际上在RS485之前RS232就已经诞生,但是RS232有几处不足的地方: 1、接口的信号电平值较高,达到十几V,容易损坏接口电路的芯片,而且和TTL电平不兼容,因此和单片机电路接起来的话必须加转换电路。 2、传输速率有局限,不可以过高,一般到几十Kb/s就到极限了。 3、接口使用信号线和GND与其他设备形成共地模式的通信,这种共地模式传输容易产生干扰,并且抗干扰性能也比较弱。 4、传输距离有限,最多只能通信几十米。 5、通信的时候只能两点之间进行通信,不能够实现多机联网通信。 针对RS232接口的不足,就不断出现了一些新的接口标准,RS485就是其中之一,他具备以下的特点:1、我们在讲A/D的时候,讲过差分信号输入的概念,同时也介绍了差分输入的好处,最大的优势是可以抑制共模干扰。尤其工业现场的环境比较复杂,干扰比较多,所以通信如果采用的是差分方式,就可以有效的抑制共模干扰。而RS485就是一种差分通信方式,它的通信线路是两根,通常用A和B或者D+和D-来表示。逻辑“1”以两线之间的电压差为+(0.2~6)V表示,逻辑“0”以两线间的电压差为-(0.2~6)V来表示,是一种典型的差分通信。 2、RS485通信速度快,最大传输速度可以达到10Mb/s以上。 3、RS485内部的物理结构,采用的是平衡驱动器和差分接收器的组合,抗干扰能力也大大增加。 4、传输距离最远可以达到1200米左右,但是他的传输速率和传输距离是成反比的,只有在100Kb/s 以下的传输速度,才能达到最大的通信距离,如果需要传输更远距离可以使用中继。 5、可以在总线上进行联网实现多机通信,总线上允许挂多个收发器,从现有的RS485芯片来看,有可以挂32、64、128、256等不同个设备的驱动器。 RS485的接口非常简单,和RS232所使用的MAX232是类似的,只需要一个RS485转换器,就可以直接和我们单片机的UART串行接口连接起来,并且完全使用的是和UART一致的异步串行通信协议。但是由于RS485是差分通信,因此接收数据和发送数据是不能同时进行的,也就是说它是一种半双工通信。那我们如何判断什么时候发送,什么时候接收呢? RS485类的芯片很多,这节课我们以MAX485为例讲解RS485通信,如图18-1所示。 图18-1 MAX485硬件接口 MAX485是美信(Maxim)推出的一款常用RS485转换器。其中5脚和8脚是电源引脚,6脚和7脚就是485通信中的A和B两个引脚,而1脚和4脚分别接到我们单片机的RXD和TXD引脚上,直接使用单片机UART进行数据接收和发送。而2脚和3脚就是方向引脚了,其中2脚是低电平使能接

很好的威纶通MODBUSRTU通讯协议与变频器通讯案例

很好的威纶通 M O D B U S R T U通讯协议与变频器通讯案例 公司标准化编码 [QQX96QT-XQQB89Q8-NQQJ6Q8-MQM9N]

本文研究的是触摸屏通过MODBUS RTU通讯协议与变频器通讯实现变频器的控制。触摸屏采用威纶通TK6070IP,变频器用汇川MD380通用系列。通过触摸屏编程软件,编辑控制画面实现变频器的启动、停止、速度调节、多段速速度设置,通过宏指令实现工程值与实际值的转换。 一、MODBUS RTU 简介: 为了在自动化系统之间、自动化系统和所连接的分散的现场设备之间进行信息交换,如今串行现场总线被主要用作通讯系统。成千上万的应用已经强烈地证明了通过使用现场总线技术,可以节省多至40%的接线、调试及维护的费用。仅仅使用两根电线就可以传送现场设备的所有相关信息,比如输入和输出数据、参数、诊断数据。过去使用的现场总线往往是制造商的特定现场总线,并且同其它现场总线不兼容。如今使用的现场总线几乎是完全公开和标准化的。这就意味者用户可以以最合理的价格选择最好的产品,而不用依赖于每个独立的制造商。Modbus RTU是一种国际的、开放的现场总线标准。作为一种很容易实现的现场总线协议,在全世界范围内,Modbus得到了成功的应用。应用领域包括生产过程中的自动化、过程控制和楼宇自控。MODBUS RTU通讯协议的报文如图1。 图1 MODBUS RTU 通讯协议的报文功能码如下: 01H 读取线圈状态。从执行机构上读取线圈(单个位)的内容; 02H 读取离散量输入。从执行机构上读取离散量输入(多个位)的内容; 03H 读取保持寄存器。从执行机构上读取保持寄存器(16位字)的内容; 04H 读取输入寄存器。从执行机构上读取输入寄存器(16位字)的内容; 05H 强置单线圈。写数据到执行机构的线圈(单个位)为“通”(“1”)或“断”(“0”); 06H 预置单寄存器。写数据到执行机构的单个保持寄存器(16位字); 0FH 强置多线圈。写数据到执行机构的几个连续线圈(单个位)为“通”(“1”) 或“断”(“0”); 10H 预置多寄存器。写数据到执行机构的几个连续的保持寄存器(16位字)。 二、威纶通编程软件介绍: EB8000软件中MODBUS协议的设备类型为0x、1x、3x、4x、5x、6x,还有 3x_bit,4x_bit,6x_bit,0x_multi_coils等,下面分别说明这些设备类型在MODBUS协议中支持哪些功能码。 0x:是一个可读可写的设备类型,相当于操作PLC的输出点。该设备类型读取位状态的时候,发出的功能码是01H,写位状态的时候发出的功能码是05H。写多个寄存器时发出的功能码是0fH。

相关文档
最新文档