1. openModbus
Modbus相关概念,网上一大堆,可以参考外文网站http://www.simplymodbus.ca/TCPclient.htm
2. OSI七层模型
Modubs协议与RS485协议组合涉及OSI七层模型的应用层、数据链路层、物理层。
Modubs协议属于数据链路层协议,即在物理层基础之上实现原始比特的可靠传输。
比如物理层的通信媒介为485,那么原始比特传输一般是1个起始位,8个数据位,2个停止位,有无校验位都可。为了实现可靠传输,需要数据链路协议收发帧。
3. Modbus分类
modbus分为RTU、ASCII、TCPIP三大类,一般使用RTU通讯方式。RTU方式一般采用RS-485作为物理层;TCPIP由于物理层的不同,网络线缆,与RTU报文区别是多了头部信息。
4. 单播与广播
modbus从链路控制的角度属于主(Master)/从(Slave)方式。
单播即报文中的地址字段指定所需要访问的设备,该设备收到请求后作出对应的应答。
广播即主站向总线所有设备发出广播报文,所有从设备都不做应答,报文中地址为0则为广播请求。
所以主机报文中,如果地址字段为0,那么代表广播,如果是1-247,代表从机地址,表示主机向哪一个从即请求数据,注意主机是没有地址的。
5. 主从站逻辑
主站如果为监控,那么就需要实时查询从站数据,这个逻辑根据具体功能码制定。
从站,系统一上电就进入空闲状态,空闲态一直监听总线报文,当收到一个完整的报文时,首先校验报文的正确性,再检查报文是否是发给该设备的,如果是请求本设备的,则先完成请求的操作,然后准备好应答报文,如果出错则将出错信息发送给主站。如果收到的是主站广播请求,则仅仅处理相应请求,不做任何应答。
不管是主站还是从站,收到报文后,先验证报文的准确性。
6.大端传输
Modbus协议基于485总线上发送数据时,一般首先发送最高字节,比如发送0x6789,先发送0x67,再发送0x89。即大端传输。
7. 传输浮点数据
由于Modbus的04或03功能码一个寄存器占用2个字节数据,如果传输float型数据时,float是4个字节,需要在协议中规定偏移和系数得到浮点值。比如传浮点值F,那么就可以规定此值偏移为b, 系数为k,传的两个字节数据组合后的值为x,那么F=k(x+b)。通过这样的方式,使2个字节表示了4个字节的float数据.
8. Modbus报文开始与结束
Modbus ASCII 报文由冒号 (":")开始 和换行符 (CR/LF) 结尾构成。
Modbus RTU采用下面方式判断一桢数据的有效性和结束。
如果Modbus采用一问一答方式,主机发起请求,从机执行请求并且应答。由于此协议没有结束标记,因此收发双方靠时延确定是否接收完成。请求或应答消息帧前后必须以3.5个以上的字符时间以间隔:
起始空闲(至少3.5个字符空闲)
消息帧
结束空闲(至少3.5个字符空闲)
消息帧发送前必须距上一帧消息间隔有3.5个字符时间的空闲,而在发完最后一个字符后,也必须以至少3.5个字符时间的空闲停顿表示消息的结束。也就是要保证两个帧间的间隔至少大于3.5个字符的空闲时间。可以通过这个来决定是否一帧数据收完。
整个消息帧必须作为一连续的流转输,如果在一个消息帧中间,两个字符间有超过1.5个字符时间的停顿时间,则接收方可以认为本帧错误。
3.5个和1.5个的字符空闲时间与通信波特率有关,计算方法如下:
1.5个字符间隔 = 1 / 9600 * 11 * 1.5 * 1000 = 1.7ms
3.5个字符间隔 = 1 / 9600 * 11 * 3.5 * 1000 = 4.01ms
上面假定波特率为9600,波特率含义是每秒传输的二进制位的个数,比如9600bps,意思就是说每1秒(也就是1000毫秒)传输9600个位,11表示RS485原始比特传输一个起始位、8个数据位、1个停止位、1个校验位,11*1.5表示1.5个字符有多少位,由于每一位需要1000/9600毫秒,那么1.5个字符就需要(11*1.5)*(1000/9600)毫秒。
一个modbus协议帧最长255字节,那么最长帧传输时间为255*1.7=433ms,假如一个协议帧长度为45字节,那么最长协议帧为45*1.7=76.5ms。如果把超时时间设置为传输时间的5~10倍,比如350ms。主机发起请求后,若从机300ms内未应答,则可以认为本次请求失败。
具体代码实现时,可以在接收到一个字节后就启动一个定时器,如果定时时间到(3.5个字符),就认为是一桢数据结束,由于常用MCU定时器硬件资源珍贵,一般采用系统systick时钟中断实现软件定时,每接收到一个字节就把一个全局变量清零,而在systick中断中不断自加此变量,如果次变量被自加到一定量没有并清零,说明已经有一段时间没有接收到数据了,通过这样的方式实现报文帧是否接收完成判断。