关注+星标公众号,不错过精彩内容
来源 | 瑞萨嵌入式小百科
1
学习Modbus的快速方法
1.1 寄存器速记
作为初学者,你阅读Modbus协议时会发现它的概念别扭、重复、不易区分,比如线圈状态(Coil Status)、离散输入状态(Discrete Input Status)、保持寄存器(Holding Register)、输入寄存器(Input Register)。
回到事情的本质,在工业控制PLC领域,涉及数字信号的输入、输出,模拟信号的输入、输出,如下图所示:
对于软件开发而言:
①想得到按键输入状态时,读取到的是一位数据。
②想控制LED时,需要输出一位数据,想读取LED当前状态时,也可以读取到一位数据。
③想读取模拟信号时,读取到的是多位数据,比如16位数据。
④想输出模拟信号时,写入的是多位数据,比如16位数据;也可以读取“模拟量输出”的当前值。
在上图中,“数字量输入DI”是只读的,“数字量输出DO”是可读可写的,“模拟量输入AI”是只读的,“模拟量输出AO”是可读可写的。
上图里的“模拟量输入AI”、“模拟量输出AO”都表示“多位数值”,这些“多位数值”无需局限于只表示“模拟量”,也可以表示“多位数字量”。把AI、AO的含义扩展后,如下图所示:
对于软件开发而言:
①想得到按键输入状态时,读取到的是一位数据。
②想控制LED时,需要输出一位数据,想读取LED当前状态时,也可以读取到一位数据。
③想读取参数时,读取到的“输入寄存器”,得到多位数据,比如16位数据。
④想设置参数时,写的是“保存寄存器”,写入的是多位数据,比如16位数据;也可以读“保存寄存器”。
在电子系统里,无论是单bit的数值、多bit的数值,都是保存在寄存器里。根据上图,这些寄存器可以分为4类:
寄存器种类 | 说明 | 与PLC类比 | 举例说明 |
线圈状态 (Coil Status) | 输出端口。可设定端口输出状态,也可以读取该位的输出状态。可分为两种不同的执行状态,例如保持型或边沿触发型。 | DO (数字量 输出) | 电磁阀输出、 MOSFEF输出、LED显示等 |
离散输入状态 (Discrete Input Status) | 输入端口。通过外部设定改变输入状态,可读但不可以写。 | DI (数字量 输入) | 拨码开关、接近开关等 |
保持寄存器(Holding Register) | 输出参数或保持参数,控制器运行时被设定的某些参数,可读可写。 | AO (模拟量 输出) | 模拟量输出设定值,PID运行参数,变量阀输出大小,传感器报警上限下限 |
输入寄存器(Input Register) | 输入参数。控制器运行时从外部设备获得的参数,但可读不可写。 | AI (模拟量 输入) | 模拟量输入 |
在Modbus中,多位操作时都是16位(2bytes)的,总结如下:
①bit操作涉及的寄存器有2类:线圈状态(可读可写)、离散输入状态(只读)。
②16bit操作的寄存器有2类:保存寄存器(可读可写)、输入寄存器(只读)。
一个设备里,可能有多个“线圈状态”、多个“离散输入状态”、多个“保存寄存器”、多个“输入寄存器”。怎么分辨某类寄存器中的某一个?它们有“寄存器地址”,如下图所示:
寄存器种类 | PLC寄存器 地址范围 | Modbus寄存器 地址范围 | 简称 | 读写 状态 |
线圈状态 | 00001~09999 | 0000H~FFFFH | 0x | 可读可写 |
离散输入状态 | 10001~19999 | 0000H~FFFFH | 1x | 只读 |
保持寄存器 | 40001~49999 | 0000H~FFFFH | 4x | 可读可写 |
输入寄存器 | 30001~39999 | 0000H~FFFFH | 3x | 只读 |
在上表中,“线圈状态”的寄存器N、“离散输入状态”的寄存器N,是两个不同的寄存器。
简单记忆方法:
①偶数类的寄存器”是可读可写的,比如“0x”和“4x”。
②“奇数类的寄存器”是只读的,比如“1x”和“3x”。
③“0x”和“1x”是bit寄存器。
④“3x”和“4x”是16bit寄存器。
1.2 协议速记
Modbus是一主多从的协议,如下图所示:
主控发出的数据里,必定含有如下信息:
①设备地址:你要访问从设备1,还是访问从设备2。
②访问哪类寄存器,是读还是写,只访问1个寄存器,还是多个寄存器:这被称为功能码。
③起始寄存器地址、寄存器数量:这在数据里定义。
④为了保证数据传输的可靠,还附带有CRC检验码。
以Modbus RTU协议为例,主控发出的数据包格式如下:
功能代码有哪些?常用的功能码如下:
①读线圈状态(01)
②读离散输入状态(02)
③写单个线圈(05)、写多个线圈(15)
④读保持寄存器(03)
⑤读输入寄存器(04)
⑥写单个保存寄存器(06)、写多个保存寄存器(16)
数据的格式,由功能代码确定。以“读线圈状态”为例,主控发出的请求、从设备返回的响应包,或者从设备返回的错误包,格式如下:
上图中,寄存器起始地址(“Starting Address”)是16位的,先传输高字节,再传输低字节。线圈数量(“Quantiti of coils”)也是16位的,先传输高字节,再传输低字节。
响应包回复多少个数据呢(上图中N为多少)?N= Quantiti of coils / 8,如果余数不等于0,则N再加1。比如Quantiti of coils=9,则返回2个字节。
在《Modbus_Application_Protocol_V1_1b3.pdf》中, 列出了如下功能表。根据次表,在结合《5.5 Moubus功能码详解》的示例,就可以对Modbus RTU协议有很好的理解了。
------------ END ------------
MPU使用GCC编译的过程
单片机和PHY芯片连接时的注意事项
瑞萨RA8系列教程 | RA8输出PWM实现方法