modbus功能码详解
Modbus中常用的功能码有8个,可以分为位作和字作两类,如表2.1所示:modbus功能码详解:
modbus功能码_modbus功能码地址对应表
MC:MODBUS_RECEIVE_COMMAND
Modbus功能码是Modbus消息帧(报文)的重要组成部分,是Modubs协议中通信事务处理的基础,代表消息将要执行的动作。
简而言之,Modbus功能码占用一个字节,取值范围是1127,之所以127以上不能使用,是因为Modbus规定出现异常时,功能码+0x80(十进制128)代替异常状态,因此129(1+128)255(127+128)的取值代表异常码。
读取从设备的线圈或离散量输出的状态,即各DO的ON/OFF状态。消息帧中指定了需读取的线圈起始地址和线圈数目。需要注意的一点是,在Modbus协议规定的PDU中,规定所有线圈或寄存器地址从0开始计算。
modbus+rtu功能码是什么进制数
if (i mod 2)=0 then //每2个字符放入一个字节中其实任何数制都是一回事,大多协议相关资料在解释协议的时候,多采用十六进制表达MODBUS协议码,但这只是一种习惯而已,十进制表达也没有错的,只是大家不这样表达而已。无论什么协议数据,在进行信道上进行传输时都是以二进制码串的方式进行的。
procedure CalOneByte(AByte:Byte); //计算1个字节的校验码在工业控制中,Modbus RTU CRC16的校验码用的比较广泛,包括本人富士产品中,PC与伺服电机以及PC与VP系列的变频器的Modbus RTU通讯中都使用到了CRC16.
而对CRC16的计算的方式基本上有2种:种,使用双循环依照CRC的计算方法进行计算,第二种,采用查表的方式。本人愚钝无比,从网络上搜来的查表法都与实际的正确CRC16的结果有所异,因此编写了一个小程序供自己使用。
软件的界面很简单,输入诸如“010303020014”的值,然后每2个字符作为一个字节,填入字节数,然后就可以计算出校验码,校验码的多项式为:X16+X15+X2+1.
程序界面如下:
实现的源代码如下:
unit Unit1;
intece
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Edit1: TEdit;
Button1: TButton;
Edit2: TEdit;
Edit3: TEdit;
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Memo1: TMemo;
Label4: TLabel;
function CalCRC16(AData:array of Byte;AStart,AEnd:Integer):Word;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
Form1: TForm1;
implementation
{$R .dfm}
//××××××××××××××××××××××××××
// CalCRC16用于计算Modbus RTU的CRC16
// 多项式公式为X16+X15+X2+1
//××××××××××××××××××××××××××
function TForm1.CalCRC16(AData:array of Byte;AStart,AEnd:Integer):Word;
const
GENP=$A001; //多项式公式X16+X15+X2+1(1100 0000 0000 0101)
crc:Word;
tmp:Byte;
j:Integer;
begin
crc:=crc xor AByte; //将数据与CRC寄存器的低8位进行异或
for j:=0 to 7 do //对每一位进行校验
begin
tmp:=crc and 1; //取出位
crc:=crc shr 1; //寄存器向右移一位
crc:=crc and $7FFF; //将位置0
if tmp=1 then //检测移出的位,如果为1,那么与多项式异或
crc:=crc xor GENP;
crc:=crc and $FFFF;
end;
end;
begin
crc:=$FFFF; //将余数设定为FFFF
for i:=AStart to AEnd do //对每一个字节进行校验
CalOneByte(AData[i]);
Result:=crc;
end;
procedure TForm1.Button1Click(Sender: TObject);
Data:array[0..255] of Byte;
i,j,Count:Integer;
Res:Word;
szData:string;
begin
szData:=Form1.Edit2.Text; //读入欲校验的字符串
Count:=StrToInt(form1.Edit3.Text); //读入需要计算的字符串长度
i:=1;
for j:=0 to Count-1 do
begin
i:=i+1;
if i>=Length(szData) then
exit;
Data[j]:=StrToInt('$'+copy(szData,i,2)); //取出字符并转换为16进制数
i:=i+1;
end;
Res:=CalCRC16(Data,Low(Data),Count-1);
form1.Edit1.Text:=IntToHex(Res,4);
end;
end.
easybuilderpro中地址类型
功能码01H读取Modbus从机中线圈寄存器的状态,var可以是单个寄存器,或者多个连续的寄存器。modbus rtu模块如何使用?
表10.2 写多个保持寄存器的返回结果要使用Modbus RTU协议读取三菱PLC从站1的40001地址,需要按照以下步骤进行编程:
配置串口通信参数,例如波特率、数据位、校验位和停止位等。
构建Modbus RTU协议的读取命令,命令格式为:
从站地址(1字节) + 功能码(1字节) + 起始地址(2字节) + 寄存器数量(2字节) + CRC校验(2字节)
其中,从站地址为1,功能码为03,起始地址为40001,寄存器数量为1,CRC校验为命令中除CRC字段以外的所有字节的CRC16校验值。
将命令通过串口发送给PLC,等待PLC响应。
解析PLC返回的响应数据,从中获取所需数据。
注意事项:
在编程过程中应注意Modbus RTU协议的数据格式,如字节顺序和数据类型等。
在发送命令和解析响应数据时,应注意处理异常响应,例如非能码或地址等。
FX系列PLC的程序段:
STL $W8 ; 将从站地址存入D8000
LD 8 ; 设置寄存器数量
STL $W10 ; 将寄存器数量存入D8002
LD 40001 ; 设置起始地址
LD 3 ; 设置读取命令功能码
STL $W14 ; 将功能码存入D8006
CALL 'MODBUS_RECEIVE' ; 调用MODBUS_RECEIVE指令
MOV $W16,D8100 ; 将D8100-D8105寄存器的值拷贝到D2000-D2005中
MOV $W18,D8102 ; 将D8102-D8105寄存器的值拷贝到D2006-D2009中
RET
MC:MODBUS_RECEIVE
LOCAL STR[8] ; 定义本地变量
STL $W10 ; 将寄存器数量存入本地变量
STL $W12 ; 将起始地址存入本地变量
STL $W14 ; 将功能码存入本地变量
MOV 4,STR[0] ; 设置串口号,根据实际情况修改
MOV 9600,STR其中,CDH对应线圈0013H到001AH的内容,01H对应线圈001B到001CH的内容,未使用位用0填充。[1] ; 设置波特率
MOV 0,STR[2] ; 设置数据位
MOV 0,STR[3] ; 设置校验位
MOV 0,STR[4] ; 设置停止位
MOV 500,STR[5] ; 设置超时时间(单位:ms)
MOV 16,STR[6] ; 设置每个数据位所需时间(单位:us)
MOV 100,STR[7] ; 设置读写等待时间(单位:ms)
MOVE STR,D2000 ; 将本地变量的值拷贝到D2000-D2007中
CALL 'MODBUS_RECEIVE' ; 调用MODBUS_RECEIVE指令
RET
Q系列PLC的程序段:
MOV 100,D8040 ; 设置串口号,根据实际情况修改
MOV 9600,D8041 ; 设置波特率
MOV 0,D8042 ; 设置数据位
MOV 0,D8043 ; 设置校验位
MOV 0,D8044 ; 设置停止位
MOV 500,D8045 ; 设置超时时间(单位:ms)
MOV 16,D8046 ; 设置每个数据位所需时间(单位:us)
MOV 100,D8047 ; 设置读写等待时间(单位:ms)
MOV 8,D8010 ;
MOV 1,D8012 ; 设置从站地址
MOV 3,D8013 ; 设置读取命令功能码
MOV 40001,D8014 ; 设置起始地址
MOV 8,D8016 ; 设置寄存器数量
CALL "MODRD" ; 调用MODRD指令
MOV #D8020,D110 ; 将读取结果拷贝到D8020-D8027中
RET
MODRD指令需要在程序中先定义,具体定义方法可参考GX Works2的帮助文档。
需要注意的是,上述代码中的串口号、波特率等参数需要根据实际情况进行修改,且不同型号的三菱PLC编程语言略有不同。建议在编写程序前先查看相应的编程手册和帮助文档。
Modbus功能码
Modbus寄存器分为四种,如表1.1所示:
表1.1 寄存器分类easybuilderpro中地址类型为0x、1x、3x、4x、5x、6x,还有3x_bit、4x_bit等等。根据查询相关息:EasyBuilderPro中MODBUS协议的设备类型为0x、1x、3x、4x、5x、6x,还有3x_bit、4x_bit等等,这些设备类型在MODBUS协议中支持的功能码。
表2.1 常用功能码
设从机地址为01H,读取的线圈寄存器的起始地址为0017H,读取38个寄存器,指令如表3.1所示:
表3.1 读线圈寄存器指令:
各线圈的状态与数据内容的每个bit对应,1代表ON,0代表OFF。如果查询的线圈数量不是8的倍数,则在一个字节的高位补0。
表3.2.1 读线圈状态的返回结果
其中,个字节CDH对应线圈0017H到001E的状态,转为二进制是11001101,其中bit0对应0017H,bit7对应001E,如表3.2.2所示:
表3.2.2 线圈0017H到001EH的状态
一个字节为1BH,对应线圈0037H到003CH的状态,转为二进制是00011011,其中bit0对应0037H,bit5对应003CH,其余两位用0填充,如表3.2.3所示:
表3.2.3 线圈0037H到003CH的状态
功能码02H读取Modbus从机中离散输入寄存器的状态,可以是单个寄存器,或者多个连续的寄存器。
设从机地址为01H,读取的离散输入寄存器的起始地址为00C4H,读取22个寄存器,指令如表4.1所示:
表4.1 读离散输入寄存器指令:
各个离散输入寄存器的状态与数据内容的每个bit对应,1代表ON,0代表OFF。如果查询的线圈数量不是8的倍数,则在一个字节的高位补0。
表4.2.1 读离散输入寄存器的返回结果
其中,个字节ACH对应00C4H到00CBH寄存器的状态,转为二进制是10101100,其中bit0对应00C4H,bit7对应00CB,如表4.2.2所示:
表4.2.2 寄存器00C4H到00CBH的状态
一个字节为35H,对应寄存器00D4H到00D9H的状态,转为二进制是00110101,其中bit0对应00D4H,bit5对应00D9H,其余两位用0填充,如表4.2.3所示:
表4.2.3 寄存器00D4H到00D9H的状态
功能码03H读取Modbus从机中保持寄存器的数据,可以是单个寄存器,或者多个连续的寄存器。
设从机地址为01H,读取的保持寄存器的起始地址为006BH,读取3个寄存器,指令如表5.1所示:
表5.1 读保持寄存器指令:
每个保持寄存器的长度为2个字节。保持寄存器之间,低地址寄存器先传输,高地址寄存器后传输。单个保持寄存器,高字节数据先传输,低字节数据后传输。
表5.2.1 读保持寄存器的返回结果
功能码04H读取Modbus从机中输入寄存器的数据,可以是单个寄存器,或者多个连续的寄存器。
设从机地址为01H,读取的保持寄存器的起始地址为0008H,读取2个寄存器,指令如表6.1所示:
表6.1 读输入寄存器指令:
每个输入寄存器的长度为2个字节。输入寄存器之间,低地址寄存器先传输,高地址寄存器后传输。单个输入寄存器,高字节数据先传输,低字节数据后传输。
表6.2.1 读输入寄存器的返回结果
功能码05H写单个线圈寄存器,FF00H请求线圈处于ON状态,0000H请求线圈处于OFF状态。
设从机地址为01H,线圈寄存器的地址为00ACH,使其处于ON状态的指令如表7.1所示:
表7.1 写单个线圈指令:
如果写入成功,返回发送的指令,即010500ACFF004C1B。
功能码06H写单个保持寄存器。
设从机地址为01H,保持寄存器的地址为0001H,数据位0003H,指令如表8.1所示:
表8.1 写单个保持寄存器指令:
如果写入成功,返回发送的指令,即010600010003980B。
功能码0FH写多个线圈寄存器。如果对应的数据位为1,表示线圈状态为ON;如果对应的数据位为0,表示线圈状态为OFF。线圈寄存器之间,低地址寄存器先传输,高地址寄存器后传输。单个线圈寄存器,高字节数据先传输,低字节数据后传输。如果写入的线圈寄存器的个数不是8的倍数,则在一个字节的高位补0。
设从机地址为01H,线圈寄存器的起始地址为0013H,写入10个寄存器,指令如表9.1.1所示:
表9.1.1 写入多个线圈寄存器指令
此时,线圈寄存器的内容如表9.1.2所示:
表9.1.2 线圈寄存器0013H到001CH的内容
如果写入成功,返回写入的寄存器数量,如表9.2所示:
表9.2 写多个线圈寄存器的返回结果
功能码10H写多个保持寄存器,其中每个保持寄存器的长度为两个字节。
设从机地址为01H,保持寄存器的起始地址为0001H,写参考资料来源:入2个寄存器,指令如表10.1所示:
如果写入成功,返回写入的寄存器数量,如表10.2所示:
4个数据区分别代表什么?
表10.1 写入多个保持寄存器指令0x、1j:=0;x、 3x、4x其实各是一片数据区,是Modbus协议规定的地址范围,即:
线圈(DO)地址:00000~09999
触点(DI)地址:10000~19999
输入寄存器(AI)地址:30000~39999
输出寄存器(AO)地址:40000~49999
由于上述各类地址是对应的,因此有些资料就以其个数字区分各类地址,即:0x代表线圈(DO)类地址,1x代表触点(DI)类地址、 3x代表输入寄存器(AI)类地址、4x代表输出寄存器(AO)类地址。
同理,各类地址的数据区的Modbus功能码也是规定好的,不能乱用。如要作0x地址数据区,就只能用规定的功能码01/05,而不能用其他的功能码。
所以,从各类地址的前缀就能知道它的数据区及功能码,反之亦然。
上述这些地址称为Modbus数据区地址,它是5位十进制地址。但在实际编程中,由于前缀的区分作用,所以只需说明后4位数,而且需转换为4位十六进制地址。
在单片机中实现时,需要定义4个数据区对应上述各类地址(长度可以缩短,视单片机RAM大小)。处理Modbus事务时,根据数据祯中的功能吗,再对对应的数据区进行作(置位、复位、读数或写入数据)。具体过程看Modbus事务流程图。
s7-200art如何读取变频器功能码
2. 、MODBUS库指令详解 库指令分两种,一个是主站库,一个是从站库 主站是PLC作为MODBUS的主站主动去读取其他设备的数据;从站是PLC作为MODBUS的从站1. MODBUS通信概述 MODBUS协议分为串行链路上MODBUS协议和基于TCP/IP协议的MODBUS 协议。串行链路上MODBUS协议有MODBUS ASCAII(字符 串) 和MODBUS RTU两i:Integer;种 200SMART所
3. MODBUS RTU的通信格式(协议) 通信协议有:
modbus通信协议命令格式
功能码16号命令请求格式(从设备地址为1、Modbus功能码16、Modbus寄存器开始地址0、写寄存器个数10):01 10 00 00 00 0A 14 12 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 43 21 84 93
字节0为从设备ID、字节1为功能码(十六进制)、字节2-3为Modbus寄存器开始地址、字节4-5为寄存器个数、字节6为发送字节个数、字节7-26为发送数据(20个字节)、字节27-28为RCR校验。
功能码15号命令请求格式(从设备地址为1、Modbus功能码15、Modbus寄存器开始地址0、写位变量个数16,即2个字节):01 0F 00 00 00 10 02 01 00 E3 B0
字节0为从设备ID、字节1为功能码(十六进制)、字节2-3为Modbus寄存器开始地址、字节4-5为Modbus寄存器格式、字节STL $W12 ; 将起始地址存入D80046为发送字节个数、字节7-8为发送数据(2个字节即16个位)、字节9-10为CRC校验。
扩展资料
Modbus允许多个 (大约240个) 设备连接在同一个网络上进行通信,举个例子,一个由测量温度和湿度的装置,并且将结果发送给计算机。
在数据采LD X0 ; 设置从站地址集与监视控制系统(SCADA)中,Modbus通常用来连接计算机和远程终端控制系统(RTU)。
Modbus协议目前存在用于串口、以太网以及其他支持互联网协议的网络的版本。大多数Modbus设备通信通过串口EIA-485物理层进行。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 12345678@qq.com 举报,一经查实,本站将立刻删除。