Modbus学习记录

Modbus

学习Modbus通信协议前先对一些基础知识进行了解

1、什么是协议?

  协议就是互相之间的约定,如果不让别人知道那就是暗号。现在就来定义一个新的最简单协议。例如,协议: “A” --“LED灭”、“B” --“报警”、 “C” --“LED亮”,设备接收到“A”控制一个LED灭,设备接收到“B”控制报警,设备接收到“A”控制一个LED亮。那么当收到对应的信息就执行相应的动作,这就是协议。
  协议在通信中又分为硬件层协议软件层协议

  1. 硬件层协议解决的是高低电平1和0的传输的问题,相当于公路,常见的有485总线、232总线
  2. 软件层协议解决在硬件层上有序的发送数据,相当于交通规则,不然就相当于在公路上乱开车,这是不允许的,常见的有TCP/IP、MODBUS等。

2、报文
  报文,即一帧数据,指的是你们通过约定每次发送的数据,一帧数据包含帧头,帧尾和校验码组成 数帧头包括接收方主机物理地址的定位以及其它息。帧数据区含有一个数据体。每帧数据之间存在间隔,间隔时间根据具体的时间来定,间隔时间用于接受端识别每一帧数据。在Modbus中分为查询报文和响应报文。

3、校验码
  校验码一般放在是由前面的数据通过某种算法得出的,用以检验该组数据的正确性。代码作为数据在向计算机或其它设备进行输入时,容易产生输入错误,为了减少这种输入错误,编码专家发明了各种校验检错方法,并依据这些方法设置了校验码。常用的校验有:累加和校验SUM字节异或校验XOR纵向冗余校验LRC循环冗余校验CRC等。

4、大小端
  这是因为在计算机系统中,是以字节为单位的,每个地址单元都对应着一个字节。一个字节为8位(bit)。在C语言中除了8位的char型之外,还有16位的short型,32位的long型(要看具体的编译器)。另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。具体如下:
大端模式:是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中。
小端模式:是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中。
在这里插入图片描述
5、本文中出现的术语和缩略语说明
在这里插入图片描述

Modbus协议简介

  前文说到协议就是互相之间的约定,那么这个约定可以是两个人之间的约定,我叫A设备发0x01,使B设备的LED1亮,我A设备发0x02,使B设备的LED2亮,这样规定的协议只能使A设备和B设备之间进行通信,无法做到与其他设备进行通信,没有统一性,那么有那个协议可以使所有人都是用一个通信协议,不同公司的设备都可以互相通信呢?MODBUS就是这样的一个常见的协议。

Modbus协议特点

  1、支持多种电气接口,如RS-232、RS-485等,还可以在各种介质上传送,如双绞线、光纤、无线等。
  2、单主/多从
  3、Modbus通信总是由主设备发起,当从设备没有收到来自主设备的请求时,不会主动发送数据。
  4、从设备之间不能相互通信,主设备同时只能启动一个Modbus访问事务处理。
  5、主设备向从设备发送报文有广播和单播两种方式。

Modbus的传输方式:RTU方式、ASC方式、TCP/IP方式

RTU方式:发送的时候十六进制的方式发送,效率相比于ASC高一倍
ASC方式:发送的时候拆分为ASCII码的方式发送,效率低,但好调试
TCP/IP方式:与RTU类似。
RTU方式发送(也叫十六进制方式)
  :要发0x03,就发送二进制0 0 0 0 0 0 1 1;
ASC方式发送(ASCII方式)
  :要发0x03,要先将0x03拆分为十位的‘0’和个位的‘3‘,就是拆成两个字符0和3,0和3有对应的ASCII码为0x30和0x33,依次发出去,即先发送0x30:0011 0000,再发0x33:0011 0011;

Modbus的主机寻址帧格式

RTU方式

Modbus-RTU模式下的查询报文与响应报文的传输格式如下:
在这里插入图片描述
RTU帧格式说明:

  • 地址:地址码为通讯传送的第一个字节。这个字节表明由用户设定地址码的从机将接收由主机发送来的信息。并且每个从机都有具有唯一的地址码,并且响应回送均以各自的地址码开始。主机发送的地址码表明将发送到的从机地址,而从机发送的地址码表明回送的从机地址。从机的地址范围1–247,0地址代表广播模式;
  • 功能:MODBUS约定了若干个功能码,就是主机找从机可能有若干个事情要做;
  • 数据:通过后面附加的数据来说清除,为了实现这个功能码所需要附加的一些信息,在不同的功能码里面这个数据码的解释是不一样的。
  • CRC校验:用于对前面的数据进行校验,经过CRC16计算后得到两字节存放到这里(注意CRC存放采用小端模式);
    CRC校验 例:03 01 00 13 00 25 0D F6
    03一字节代表发给03号设备,01一字节代表读取线圈寄存器,00 13两字节代表从线圈寄存器的第13位开始读取,00 25二字节代表从00 13位开始读取37个位,0D F6代表CRC校验码
  • 开始、结束:程序编写中会有一个问题在RTU方式中没有起始符和结束符,不知道数据长度到底有多长,所以规定发送接收数据寻址帧时,从机以接收数据停止时间达到3.5个字节以上代表寻找帧发送完成,并开始处理。例如:波特率9600bit/s,所以每位数据传输时间t =(1000000us)/9600 =104us
    因为1个字节发送需要10位,所以一个字节需要的时间是T=10t=1040us
    所以3.5T=3.5
    1040=3645us=4ms,停止时间大于4ms时从机就开始处理数据。
    (注意:主机发送时不能停止,并且发送间隔要大于4ms)。

采用Modbus-RTU方式传输实例:
  采用功能码01,定义了从设备地址为3,并读取从设备的Modbus地址00019—00055共计37个状态值。起始线圈地址为0x13,因为线圈地址从0开始计数。

查询报文如下:
在这里插入图片描述
响应报文如下:
在这里插入图片描述

ASC方式

  Modbus-ASC模式下的查询报文与响应报文的传输格式,与RTU模式并无大的区别,主要有以下几点:

  • 具有帧头帧尾;
  • 功能码与数据和RTU方式发送的东西一样,但发送是要拆分为2个ASCII码的方式发送;
  • 校验采用LRC校验:(地址+功能码+数据1+数据2+……+数据n)之和除以256后取余(这是这个数据就一定小于256),在取反加1,即余数的补码;
  •  备注:因为有实际的起始符和结束符,所以可以很方便的调试,但在实际中不用。
    
TCP/IP方式

  Modbus TCP协议与RTU协议非常类似,主要区别是,在RTU协议上加一个MBAP报文头,同时由于TCP是基于可靠连接的服务,RTU协议中的CRC校验码就不再需要,所以在Modbus TCP协议中是没有CRC校验码,用一句比较通俗的话说就是:Modbus TCP协议就是Modbus RTU协议在前面加上五个0以及一个6,然后去掉两个CRC校验码字节就OK.虽然这句话说得不是特别准确,但是也基本上这就是RTU与TCP之间的区别,。
  Modbus-TCP模式下的查询报文与响应报文的传输格式如下:
在这里插入图片描述
MBAP 报文头总长为 7 字节,

名称传输标识协议标识字节长度单元标识符
占用字节2221

MBAP报文头说明:

  1. 传输标识:标记某个Modbus查询/应答的传输过程。占两个字节。
  2. 协议标识:Modbus协议=0x00,再标记Modbus协议,设置为0x00。占两个字节。
  3. 字节长度:记录后续字节个数。占两个字节。
  4. 单元标识符:用以识别从机设备。占1个字节。

Modbus RTU与Modbus TCP指令查询报文的对比

MBAP报文头地址码功能码寄存器地址寄存器数量CRC校验
Modbus RTU010301 8E00 0425 DE
Modbus TCP00 00 00 00 00 06010301 8E00 04

  对上表的说明:
  由于Modbus-TCP模式是基于TCP连接的,不存在所谓的地址码,所以06后面一般都是“00”(当其作为Modbus网关服务器挂接多个RTU设备的时候,数值从01-247).即“00 03 01 8E 00 04”对应的是RTU中去掉校验码的指令,前面则是五个0以及一个6。其中6表示的是数据长度,即“00 03 01 8E 00 04”有6个字节长度。而当其为操作指令的时候,其指令是“00 00 00 00 00 09 01 10 01 8e 00 01 02 00 00”,其中“00 09”表示后面有9个字节。

采用Modbus-TCP方式传输实例:
  采用功能码01,定义了从设备14地址为 3,并读取从设备的 Modbus 地址 00019—00055 共计 37 个状态值。起始线圈地址为 0x13,因为线圈地址从 0 开始计数。

查询报文如下:
在这里插入图片描述
响应报文如下:
在这里插入图片描述

寄存器与功能码

在对功能码了解前先对Modbus的寄存器进行了解,
这其中有涉及到线圈离散输入保持输入四种寄存器。

  • 线圈寄存器:实际上就可以类比为开关量(继电器状态),每一个bit对应一个信号的开关状态。所以一个byte就可以同时控制8路的信号。比如控制外部8路io的高低。 线圈寄存器支持读也支持写,写在功能码里面又分为写单个线圈寄存器写多个线圈寄存器。对应下面的功能码也就是:0x01 0x05 0x0f
  • 离散输入寄存器:离散输入寄存器就相当于线圈寄存器的只读模式,他也是每个bit表示一个开关量,而他的开关量只能读取输入的开关信号,是不能够写的。比如我读取外部按键的按下还是松开。所以功能码也简单就一个读的 0x02
  • 保持寄存器:这个寄存器的单位不再是bit而是两个byte,也就是可以存放具体的数据量的,并且是可读写的。一般对应参数设置,比如我我设置时间年月日,不但可以写也可以读出来现在的时间。写也分为单个写和多个写,所以功能码有对应的三个:0x03 0x06 0x10
  • 输入寄存器:这个和保持寄存器类似,但是也是只支持读而不能写,一般是读取各种实时数据。一个寄存器也是占据两个byte的空间。类比我我通过读取输入寄存器获取现在的AD采集值。对应的功能码也就一个 0x04
常用的几个功能码如下:
    0x01: 读线圈寄存器
    0x02: 读离散输入寄存器
	0x03: 读保持寄存器
    0x04: 读输入寄存器
	0x05: 写单个线圈寄存器
    0x06: 写单个保持寄存器
	0x0f:  写多个线圈寄存器
    0x10: 写多个保持寄存器

寄存器地址分配如下:
在这里插入图片描述

常用的几个功能码的采用RTU模式传输的举例说明

1、01号命令,读可读写数字量寄存器(线圈状态):

计算机发送命令:[设备地址] [命令号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校验:是从开头一直校验到此之前。

设备响应:[设备地址] [命令号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、05号命令,写数字量(线圈状态):

计算机发送命令:[设备地址] [命令号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>注意此命令一条只能下置一个开关量的状态。

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

3、03号命令,读可读写模拟量寄存器(保持寄存器):

计算机发送命令:[设备地址] [命令号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校验同上。

4、06号命令,写单个模拟量寄存器(保持寄存器):

计算机发送命令:[设备地址] [命令号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>注意此命令一条只能下置一个模拟量的状态。

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

5、16号命令,写多个模拟量寄存器(保持寄存器):

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

例:[11][16][00][01][00][01][00][05] [CRC高] [CRC低]

意义如下:

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

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

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

<4>需下置的数据数量高8位,低8位:表明了需要下置的数据数量,这里为1。

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

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

设备响应:[设备地址] [命令号16] [需下置的寄存器地址高8位] [低8位] [数据数量高8位] [数据数量低8位] [CRC校验的高8位] [CRC校验的低8位],如上例返回:

[11][16][00][01][00][01] [CRC高] [CRC低]

Modbus仿真软件

  对于没有硬件设备的情况下想对Modbus协议进行编程的,可以使用仿真软件共有三个分别是:

  • 用于模拟主站设备的–Modbus Poll软件
  • 用于模拟从站设备的–Modbus Slave软件
  • 用于虚拟串口连接的Virtual Serial Port Driver软件

  其具体使用方法自行百度。

freemodbus 是一款开源的Modbus通信协议栈,用于实现Modbus通信协议的开发。通过学习freemodbus,我收获了许多知识和技能。 首先,在学习freemodbus时,我了解到了Modbus通信协议的基本原理和工作方式。Modbus是一种常用的串行通信协议,主要用于工业自动化领域中设备之间的通信。它使用简单的请求-响应机制进行数据传输,包括读取和写入寄存器等功能。通过freemodbus学习,我了解到了Modbus通信协议的组成结构、数据帧格式以及常用的功能码等。 其次,通过实践freemodbus的使用,我学会了如何在嵌入式系统中实现Modbus通信功能。freemodbus提供了一系列的接口函数,可以方便地实现Modbus主站和从站的功能,并支持多种串口通信方式,如RS485、TCP等。学习过程中,我熟悉了freemodbus的API函数的使用方法,掌握了创建、初始化和配置Modbus通信对象的技巧。 另外,通过使用freemodbus,我学到了一些调试和排错的技巧。在实际应用中,由于硬件、软件等多种因素的影响,可能会出现通信故障或数据错误的情况。通过freemodbus的调试工具和相关的日志输出,我学会了如何在开发过程中定位和解决各种问题,提高了软件开发的技能和经验。 总体来说,学习freemodbus是一次非常有益的经历。通过这个学习过程,我不仅掌握了Modbus通信协议的原理和应用,还提高了嵌入式软件开发的能力。我相信,在今后的工作中,我可以更好地应用freemodbus开发各种工业自动化设备和系统。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值