FreeModbus协议是一个基于MODBUS协议的开源实现,实现了从机部分的功能。代码不长,移植也十分方便。
数据链路层
在此层上,MODBUS是主从结构,一个总线上只能有一个主机,允许有247个从机,所有的通信都是由主机发起的。主机有两种发送模式,一种是单向,另一种是广播。MODBUS的地址空间一共有256个,第0个用于广播,248-255保留,剩余247个分配给从机,而主机是没有地址的。
MODBUS的数据单元(protocol data unit, PDU)由功能码和数据组成,而在物理层上的一帧则是在PDU前加上地址,在PDU后加上CRC校验组成。
有两种串行传输模式。一种是RTU(remote terminal unit),另一种是ASCII。RTU应用的更多一些,在 specification 中,明确规定,RTU是必须实现的,而ASCII只是可选的。
RTU的优势在于信息比ASCII更紧凑,也就是传输的更快。RTU中每一个字节是11 bits,由1个起始位,8个数据位,1个奇偶校验位,一个停止位。默认是偶校验位。
在MODBUS中,是用时间间隔来区分每一帧的,由此可以联想到,单片机实现的时候一定要用定时器。每一帧的间隔要大于3.5倍的字符,每两个字节之间不能大于1.5个字符,否则会认为出错。
在波特率小于19200的时候,这两个规则必须实现。当大于19200的时候,t3.5取为1750us,t1.5取为750us。
在每一帧的最后是CRC16校验。校验的c实现,在 specification 上已经给出。起始位,校验位,结束位不参与CRC校验。
从机的状态转换图如下
这可以用状态机实现。
应用层
应用层是一种请求和响应的模式,功能是由功能码指出。值得一提的是MODBUS还可以通过TCP/IP协议的502端口来实现通信。
PLC中数据分为四种,线圈,数字量输入,输入寄存器和保持寄存器。前两种是可以位访问,后两种是字访问。对于每一种数据,其数据可以分别寻址,从0-65535。
特别指出,这里地址是以MODBUS而言的。与设备中的寄存器地址有别。
寄存器信息地址(PLC地址)
寄存器信息地址指的是存放于控制器中的地址,这些控制器可以使PLC,也可以是触摸屏,或是文本显示器。例如40001,30002等,这些地址一般使用10进制描述。
寄存器寻址地址(协议地址)
寄存器寻址地址指的是通信时使用的寄存器地址,例如信息地址40001对应寻址地址0x0000,40002对应寻址地址0x0001,寄存器寻址地址一般使用16进制描述。再如,信息寄存器40003对应寻址地址0002,信息寄存器30003对应寻址地址0002,虽然两个信息寄存器通信时使用相同的地址,但是需要使用不同的命令才可以访问,所以访问时不存在冲突。
功能码
一共有127个功能码,其中部分是公用的,其他可以用户自己定义。
现在举一例
功能1 读寄存器值
这个功能可以读1-2000个连续的寄存器值。读时需要制定起始寄存器地址,寄存器数量。如果请求的格式正确,则返回寄存器数量,和每一位寄存器值,对于不是8的倍数的寄存器数量请求,则添0补全。