早先学51时,宋老师的书上就有Modbus这方面的知识,可是当时实验环境不足也没去深究,现在做项目用到了RS485这类传感器和Modbus协议,特地来记录下。
一、传感器介绍
使用的传感器是一款光照度传感器,如下图所示。
该传感器一共有五根线,颜色与功能有下表所示对应关系。
颜色 | 功能 |
---|---|
棕色线 | 电源正(12-24V) |
黑色线 | 电源负(12-24V) |
黄色线 | 485-A |
蓝色线 | 485-B |
注意,485的A和B千万不要接反了!
设备默认地址为0x01
该传感器的只能通过0x03指令读取光照度信息,光照度数据一共32位,高16位在地址为0x07
的寄存器中,低16位在地址为0x08
的寄存器中。
二、RS485介绍
1、RS485特点
- 数据信号采用差分传输方式,可以有效的解决共模干扰问题
- 逻辑“1”以两线之间的电压差为
+(0.2~6)V
表示,逻辑“0”以两线间的电压差为-(0.2~6)V
来表示,是一种典型的差分通信
- 逻辑“1”以两线之间的电压差为
- 最大距离可达 1200 米
- 最大传输速度可以达到 10Mb/s 以上
- 它的传输速率和传输距离是成反比的,只有在 100Kb/s 以下的传输速度,才能达到最大的通信距离,如果需要传输更远距离可以使用中继。
- 允许多个收发设备接到同一条总线上
- 可以在总线上进行联网实现多机通信,总线上允许挂多个收发器,从现有的 RS485芯片来看,有可以挂 32、 64、 128、 256 等不同个设备的驱动器
- RS485 的接口非常简单, 与 RS232 所使用的 MAX232 是类似的,只需要一个 RS485转换器,就可以直接与单片机的 UART 串口连接起来,并且使用完全相同的异步串行通信协议。
- 但是由于 RS485 是差分通信,因此接收数据和发送数据是不能同时进行的,也就是说它是一种半双工通信。(所以后面有了控制输入和输出方向的dir位!)
2、RS485典型硬件电路
其中,485-RX和485-TX可直接与单片机的串口相连。485-DIR接至普通输出IO口即可,用来控制通信方向:默认一直低电平(处于接收状态),当发送时将其拉高,发送完毕再拉低!
三、Modbus通信协议介绍
1、Modbus介绍
UART、 I2C、 SPI 这些通信协议,都是最底层的协议,是“位”级别的协议。Modbus这种通信协议是字节级别的,叫做应用层通信协议。该协议描述了控制器请求访问其它设备的过程,如何回应来自其它设备的请求,以及怎样侦测错误记录,它制定了通信数据的格局和内容的公共格式。
在进行多机通信的时候, Modbus 协议规定每个控制器必须要知道它们的设备地址,识别按照地址发送过来的数据,决定是否要产生动作,产生何种动作,如果要回应,控制器将生成的反馈信息用 Modbus 协议发出。
2、RTU 协议帧数据
Modbus 有两种通信传输方式,一种是 ASCII 模式,一种是 RTU 模式。在实际场合中使用的比较多的当数RTU协议帧模式了。一帧RTU格式如下图所示:
Modbus 的 RTU模式规定不同数据帧之间的间隔是 3.5个字节通信时间以上(通常设置为5ms)。
设备地址:每个设备都有一个自己的地址,当设备接收到一帧数据后,程序首先对设备地址字节进行判断比较,如果与自己的地址不同,则对这帧数据直接不予理会,如果与自己的地址相同,就要对这帧数据进行解析。
如果地址是 0x00,则认为是一个广播命令,就是所有的从机设备都要执行的指令。
功能代码:在第二个字节功能代码字节中, Modbus 规定了部分功能代码。我们常用的是0x03:读取一个或连续的寄存器
以及0x06:写入单个寄存器
。该项目中使用的光照度传感器,我们主要是在程序中读取该传感器的数据,因此本文着重介绍0x03
功能码。
数据:跟在功能代码后边的是 n 个 8bit 的数据。这个 n 值的到底是多少,是功能代码来确定的,不同的功能代码后边跟的数据数量不同。当主机向从机(传感器)发送读取数据的请求命令时,主机发送的数据 n
的组成部分就是: 2 个字节的寄存器起始地址,加 2 个字节的寄存器数量 N。如下图所示:
当从机接收到主机的请求命令,回应主机发送的命令时,从机数据 n 的组成部分是: 1 个字节的字节数,因为我们回复的寄存器的值是 2 个字节,所以这个字节数也就是 2N 个,再加上 2N 个寄存器的值。如下图所示:
可能这里还会有点绕,不过没关系。到后面结合我们实际的传感器数据,再来看这些规定也许就会一切明朗了。对了,需要提到的一个事情是:在 Modbus 协议里寄存器的地址和数值都是 16 位的(两个字节)。
CRC校验:CRC 校验函数把一帧数据除最后两个字节外,前边所有的字节进行特定的算法计算,计算完后生成了一个 16bit的数据,作为 CRC 校验码,添加在一帧数据的最后。接收方接收到数据后,同样会把前边的字节进行 CRC 计算,计算完了再和发过来的 16bit 的 CRC 数据进行比较,如果相同则认为数据正常,没有出错,如果比较不相同,则说明数据在传输中发生了错误,这帧数据将被丢弃,就像没收到一样,而发送方会在得不到回应后做相应的处理错误处理。
关于具体的CRC校验算法,如果实在看不懂,也可不必深究,先会用!
四、传感器通信实例
下面将使用两个Modbus调试上位机,演示实际的Modbs通信过程。两款上位机均可从<这里>获取。提取码:fkc9
1、通用的Modbus调试精灵
界面如下图所示:
通过RS485转串口设备,将传感器接到电脑选择对应的COM口,其他设置如上图所示,然后点击打开串口。在读寄存器区写入寄存器地址为:7,数量为2。(即读取0x07和0x08两个寄存器的内容)在发送窗口写入01 03 00 07 00 02 75 CA
,点击读出,便会接收到01 03 04 00 00 00 00 5F BA 0B
下面将分别详细解释发送和接收的每个字节含义。
发送
内容 | 含义 |
---|---|
01 | 设备地址 |
03 | 功能码 |
00 | 要读取的起始地址高位 |
07 | 要读取的起始地址低位 |
00 | 寄存器数量高位 |
02 | 寄存器数量低位 |
75 | CRC校验高位 |
CA | CRC校验低位 |
接收
内容 | 含义 |
---|---|
01 | 设备地址 |
03 | 功能码 |
04 | 读取的字节数 |
00 | 0x07地址的高8位 |
00 | 0x07地址的低8位 |
00 | 0x08地址的高8位 |
5F | 0x08地址的低8位 |
BA | CRC校验高位 |
0B | CRC校验低位 |
所以我们读取到的光照强度位:0x42,即95Lux
这里再次体会前面的协议规定中的主机发送请求,从机发送回应。还有前面提到的在 Modbus 协议里寄存器的地址和数值都是 16 位的(两个字节)。
2、专用的光照强度Modbus调试上位机
这个当然就是和这个传感器配套的上位机咯~
但是协议和上面介绍的通用一毛一样,可以比对学习。
emmmm,整个协议的分析和数据的读取到这里基本告一段落。