最近被拉去支援硬件部分,又写了几天对接嵌入式的上位机程序 _(ˊཀˋ」∠)_

和下位机通信是用 modbus 协议的。趁机学习了一下这个上古协议。(奇怪的知识又增加了

modbus 是用 req/res 的模式来通信的。和 http 是一样的,如果要拿传感器信息只能轮询

关于 modbus 协议的一大特点,就是支持设备并连,可以通过一个串口控制最多 256 个设备(每次发送请求时要发送目标地址)

由于 modbus.org 不支持 https 。所以就不放标准文档的连接了(迫真,上古协议)

以这个读取状态的请求为例 03 (0x03) Read Holding Registers

Name Length Value
Function code 1 Byte 0x03
Starting Address 2 Bytes 0x0000 to 0xFFFF
Quantity of Registers 2 Bytes 1 to 125 (0x7D)

每个请求要有 Function code 字段。用到的 Function code 是有标准的定义的。(当然是可以不按照标准实现)

当然不同的 Function code 对应的参数也不同。

这个协议的读写是直接写到对应地址里的。

比如有一个地址为 0x01 的存温度,地址为 0x02 存湿度

由于这两个地址是连续的。可以一口气全部读出来

我们先来发送一个 0x03 的请求

当然 Starting Address0x01Quantity of Registers0x02(一共读两个: 0x010x02

然后请求转换成这样一段东西:['0x03', '0x00', '0x01', '0x00', '0x02'] (我应该不用解释这一串是怎么生成的吧。。。)

这个叫 pdu (Protocol Data Unit)也就是 Function code 加上 Function code 对应的 Data

之后把 pdu emmmmm 。之后分成多种情况。这个和你的传输方式有关。modbus 可以使用RTU(串口传输)也可以使用 TCP 来传输。

如果是 RTU 传输,加入目标地址,加入 crc 校验字段,然后就可以直接发送出去了

Name Value
Slave Address 1 byte
Function 1 byte
Data 0 up to 252 bytes
CRC 2 byte

如果使用 TCP 就多出了很多字段

Name Value
Transaction identifier 2 bytes
Protocol identifier 2 bytes
Length 2 bytes
Unit identifier 1 byte
Function code 1 byte
Data n bytes

modbus 也就这点东西了,其实没什么。

我使用 golang 的库来使用 modbus

modbus 还可以的。就是,如果个厂商能按照 modbus 标准来实现就好了(我写的时候,坑人的硬件厂商没有按照 modbus 标准实现)

这协议要是支持订阅某个地址的值,然后当数值变化的时候自动推送消息就好了(设置个最小推送时间间隔,这样就可以不用轮询了)