micropython modBus

for TB of NEUI, also supporot TYB board

报文

ADU包括:地址 + PDU,应用数据单元 PDU包括:功能码+数据+CRC,协议数据单元

功能码

0x01: 读线圈寄存器 0x02: 读离散输入寄存器 0x03: 读保持寄存器 0x04: 读输入寄存器 0x05: 写单个线圈寄存器 0x06: 写单个保持寄存器 0x0f: 写多个线圈寄存器 0x10: 写多个保持寄存器

数据类型

  • 线圈寄存器:实际上就可以类比为开关量,每个bit都对应一个信号的开关状态。所以一个byte就可以同时控制8路的信号。比如控制外部8路io的高低。 线圈寄存器支持读也支持写,写在功能码里面又分为写单个线圈寄存器和写多个线圈寄存器。

  • 离散输入寄存器:如果线圈寄存器理解了这个自然也明白了。离散输入寄存器就相当于线圈寄存器的只读模式,他也是每个bit表示一个开关量,而他的开关量只能读取输入的开关信号,是不能够写的。比如我读取外部按键的按下还是松开。

  • 保持寄存器:这个寄存器的单位不再是bit而是两个byte,也就是可以存放具体的数据量的,并且是可读写的。比如我我设置时间年月日,不但可以写也可以读出来现在的时间。写也分为单个写和多个写,所以功能码有对应的三个:0x03 0x06 0x10.

  • 输入寄存器:只剩下这最后一个了,这个和保持寄存器类似,但是也是只支持读而不能写。一个寄存器也是占据两个byte的空间。类比我我通过读取输入寄存器获取现在的AD采集值。对应的功能码也就一个 0x04

功能码 0x01 读线圈寄存器

此功能码的数据格式为:

  • 请求端:寄存器起始地址+数据数量,对应上面的功能码也就是:0x01 0x00 0x0f 0x00 0x25,此处功能码为 0x01, 寄存器地址为0x000f,数据量为0x25
  • 响应端:寄存器数据,0x25对应27个状态量,占用5个字节,对应上面的功能码也就是:0x01 0xAA 0x55 0xAA 0x55 0xAA,此处0x55 AA表示不同的开关状态。从低位到高位读,每一位对应一个断路器的状态,0为分,1为合

功能码 0x02 读离散输入寄存器

此功能码的数据格式为:

  • 请求端:寄存器起始地址+数据数量,对应上面的功能码也就是:0x02 0x00 0x0f 0x00 0x25,此处功能码为 0x01, 寄存器地址为0x000f,数据量为0x25
  • 响应端:寄存器数据,0x25对应27个状态量,占用5个字节,对应上面的功能码也就是:0x02 0xAA 0x55 0xAA 0x55 0xAA,此处0x55 AA表示不同的开关状态。从低位到高位读,每一位对应一个断路器的状态,0为分,1为合

功能码 0x03 读保持寄存器

此功能码的数据格式为:

  • 请求端:寄存器起始地址+数据数量,对应上面的功能码也就是:0x03 0x00 0x0f 0x00 0x03,此处功能码为 0x01, 寄存器地址为0x000f,数据量为0x25
  • 响应端:寄存器数据,0x25对应27个状态量,占用5个字节,对应上面的功能码也就是:0x03 0x06 0x00 0x0D 0x00 0x0E 0x00 0x0F,此处0x00 0x0D 0x00 0x0E 0x00 0x0F表示3个数据值,0x06表示数据区字节数量

功能码 0x04 读输入寄存器

此功能码的数据格式为:

  • 请求端:寄存器起始地址+数据数量,对应上面的功能码也就是:0x04 0x00 0x0f 0x00 0x03,此处功能码为 0x01, 寄存器地址为0x000f,数据量为0x25
  • 响应端:寄存器数据,0x25对应27个状态量,占用5个字节,对应上面的功能码也就是:0x04 0x06 0x00 0x0D 0x00 0x0E 0x00 0x0F,此处0x00 0x0D 0x00 0x0E 0x00 0x0F表示3个数据值,0x06表示数据区字节数量

demo

串口以hex格式发送: 0A 03 00 01 00 07 54 b3 收到 0A 03 02 00 64 1C 6E