表2.1.2 读线圈寄存器-响应
|
Hex
|
从机地址
|
11
|
功能码
|
01
|
返回字节数
|
05
|
数据1(线圈0013H-线圈001AH)
|
CD
|
数据2(线圈001BH-线圈0022H)
|
6B
|
数据3(线圈0023H-线圈002AH)
|
B2
|
数据4(线圈0032H-线圈002BH)
|
0E
|
数据5(线圈0037H-线圈0033H)
|
1B
|
CRC校验高字节
|
45
|
CRC校验低字节
|
E6
|
线圈0013H到线圈001AH的状态为CDH,二进制值为11001101,该字节的最高字节为线圈001AH,最低字节为线圈0013H。线圈001AH到线圈0013H的状态分别为ON-ON-OFF-OFF-ON-ON-OFF-ON。
表2.1.3 线圈0013H到001A状态
001AH
|
0019H
|
0018H
|
0017H
|
0016H
|
0015H
|
0014H
|
0013H
|
ON
|
ON
|
OFF
|
OFF
|
ON
|
ON
|
OFF
|
ON
|
最后一个数据字节中,线圈0033H到线圈0037状态为1BH(二进制00011011),线圈0037H是左数第4位,线圈0033H为该字节的最低字节,线圈0037H至线圈0033H的状态分别为ON-ON-OFF-ON-ON,剩余3位使用0填充。
表2.1.4 线圈0033H到线圈0037状态
003AH
|
0039H
|
0038H
|
0037H
|
0036H
|
0035H
|
0034H
|
0033H
|
填充
|
填充
|
填充
|
ON
|
ON
|
OFF
|
ON
|
ON
|
2.2 读离散输入寄存器 02H
1) 说明
读离散输入寄存器状态。
2) 查询
从机地址为11H。离散输入寄存器的起始地址为00C4H,结束寄存器地址为00D9H。总共访问32个离散输入寄存器。
表 2.2.1 读离散输入寄存器——查询
|
Hex
|
从机地址
|
11
|
功能码
|
02
|
寄存器地址高字节
|
00
|
寄存器地址低字节
|
C4
|
寄存器数量高字节
|
00
|
寄存器数量低字节
|
16
|
CRC校验高字节
|
BA
|
CRC校验低字节
|
A9
|
3) 响应
响应各离散输入寄存器状态,分别对应数据区中的每位值,1 代表ON;0 代表OFF。第一个数据字节的LSB(最低字节)为查询的寻址地址,其他输入口按顺序在该字节中由低字节向高字节排列,直到填充满8位。下一个字节中的8个输入位也是从低字节到高字节排列。若返回的输入位数不是8的倍数,则在最后的数据字节中的剩余位至该字节的最高位使用0填充。
表2.2.1 读输入寄存器-响应
|
Hex
|
从机地址
|
11
|
功能码
|
02
|
返回字节数
|
03
|
数据1(00C4H-00CBH)
|
AC
|
数据2(00CCH-00D3H)
|
DB
|
数据3(00D4H-00D9H)
|
35
|
CRC校验高字节
|
20
|
CRC校验低字节
|
18
|
离散输入寄存器00D4H到00D9H的状态为35H (二进制00110101)。输入寄存器00D9H为左数第3位,输入寄存器00D4为最低位,输入寄存器00D9H到00D4H的状态分别为ON-ON-OFF-ON-OFF-ON。00DBH寄存器和00DAH寄存器被0填充。
表2.2.2 离散输入寄存器00C4H到00DBH状态
00CBH
|
00CAH
|
00C9H
|
00C8H
|
00C7H
|
00C6H
|
00C5H
|
00C4H
|
0
|
0
|
1
|
1
|
0
|
1
|
0
|
1
|
00D3H
|
00D2H
|
00D1H
|
00D0H
|
00CFH
|
00CEH
|
00CDH
|
00CCH
|
1
|
1
|
1
|
0
|
1
|
0
|
1
|
1
|
00DBH
|
00DAH
|
00D9H
|
00D8H
|
00D7H
|
00D6H
|
00D5H
|
00D4H
|
填充
|
填充
|
1
|
1
|
0
|
1
|
0
|
1
|
公司业务需要,用到
modbus
协议
,本质上很简单,只是第一次接触,被这些词语搞得云里雾里的。这里
整理
一下,方便以后查询:
0x01:
读
线圈
寄存器
0x02:
读
离散
输入
寄存器
0x03:
读
保持
寄存器
0x04:
读
输入
寄存器
0x05: 写单个
线圈
寄存器
0x06: 写单个保持
寄存器
0x0f: 写多个
线圈
寄存器
0x10: 写多个保持
寄存器
如上所示一共8种功能码。这其中有涉及到
线圈
、
离散
输入
、保持、
输入
四种
寄存器
。
线圈
寄存器
:实际上就可以类比为开关量(继电器状态),每一个bit对应一个信号的开关状态。所以
ModBus
是Modicon公司为其PLC通讯而开发的一种
通讯协议
。如今Modicon公司已经被施耐德收购成为了施耐德旗下品牌。从1979年问世至今,已经成为工业通讯领域的业界标准。
ModBus
具有两种串行传输模式,ASCII 和 RTU。它们定义了数据如何打包、解码的不同方式。支持
Modbus
协议
的设备一般都支持 RTU 格式。通信双方必须同时支持上述模式中的一种。
MODBUS
寄存器
分类
01H
-
读
线圈
状态1)描述:
读
从机
线圈
寄存器
,位操作,可
读
单个或者多个;
2)发送指令:
假设从机地址位0x01,
寄存器
开始地址0x0023,
寄存器
结束抵制0x0038,总共
读
取21个
线圈
。
协议
图如下:3)响应:
返回数据的每一位对应
线圈
状态,1-ON,0-OFF,如下图;
上表中data1表示0x0023-0x002a的
线圈
状态,data1的最低位代表最低地址的
线圈
状态,可以理解为小端模式
本文主要介绍了
Modbus
读
取输出
线圈
的状态
02H
功能码的询问报文和响应报文的格式以及含义,也通过编码实现
读
取
线圈
状态示例,希望对你理解
Modbus
如何
读
取
线圈
状态有点帮助。
读
保持
寄存器
。可
读
取单个或多个保持
寄存器
。
2) 查询
从机地址为11H。保持
寄存器
的起始地址为006BH,结束地址为006DH。该次查询总共访问3个保持
寄存器
。
表2.3.1
读
保持
寄存器
-查询
由于自己所购买的传感器
读
取需要的数据是
modbus
RTU04功能码形式(
读
取
输入
寄存器
的值),晚上找了好多资料关于
modbus
RTU04功能码的代码几乎没有,也困扰了自己很久,所以在此补充一份,同时也感谢胡工对我的帮助,顺利
读
取到
寄存器
数据,下面的代码希望对大家有帮助。
/*-----------
modbus
04功能码------------*/
void MainWindow::on_m04Btn_clicked()
if(master==nullptr)return;//主站为空 退出
Modbus
是一种串行通信
协议
,是Modicon于1979年,为使用可编程逻辑控制器(PLC)而发表的。
MODBUS
是工业领域通信
协议
的业界标准,并且现在是工业电子设备之间相当常用的连接方式。
OSI7层模型
线圈
寄存器
支持
读
也支持写,写在功能码里面又分为写单个
线圈
寄存器
和写多个
线圈
寄存器
。这个
寄存器
的单位不再是bit而是两个byte,也就是可以存放具体的数据量的,并且是可
读
写的。一般对应参数设置,比如我我设置时间年月日,不但可以写也可以
读
出来现在的时间。写也分为单个写和多个写,所以功能码有对应的三个:0x03 0x06 0x10。
离散
输入
寄存器
就相当于
线圈
寄存器
的只
读
模式,他也是每个bit表示一个开关量,而他的开关量只能
读
取
输入
的开关信号,是不能够写的。一个
寄存器
也是占据两个byte的空间。
一 、开发思路
我这里开发的平台是新唐M031,它是Cortex-M0的内核、32位单片机。因为要和上位机进行RS485通讯,所以选用了
Modbus
-RTU来作为
通讯协议
。我这是用串口接收中断+定时器中断来接收一帧数据,然后
modbus
从机程序自己手撸。
二、
Modbus
介绍
modbus
没什么好介绍的,熟悉下功能码就ok了。上链接 https://www.cnblogs.com/endv/p/8650491.html
三、 串口初始化及...