从站主要是接收,被动响应,所以先分析接收机的状态:
接收状态机
接收状态包含以下几种:
STATE_RX_INIT, /*!< 接收机在初始态 */
STATE_RX_IDLE, /*!<接收机在空闲态 */
STATE_RX_RCV, /*!< 接收到一帧数据 */
STATE_RX_ERROR /*!< 错误数据帧 */
状态机转换图:
STATE_RX_INIT
eMBRTUStart()
启动T3.5定时
设置初态
STATE_RX_IDLE
T3.5超时
发送一个EV_READY事件
串口收到一
个字节
STATE_RX_RCV
串口收到一个新字
节,且总字节数不
超过最大帧长
T3.5超时
STATE_RX_ERROR
串口收到一个
新字节,但总
字节数超过最
大帧长
T3.5超时
发送一个EV_FRAME_RECEIVED事件
eMBEnable()
串口收到一个字节
重启T3.5 开始下一个T3.5延迟
串口收到一个新字节
状态机的转换不是由一个函数来确定的,是由多个函数共同作用的结果。主要要 T3.5 的定
时中断和串口的接收中断。
所以在程序一开始要对串口和定时器进行正确的设置。
当初始化完毕后,接收状态机初始态是 STATE_RX_INIT,同时 T3.5 定时器启动。如果在 T3.5
定时到来之前,串口收到了一个字节,则认为是还没准备好的情况下,总线发起的一次
Modbus 传输,此时这帧数据是不处理的,所以,要等到这一帧数据传送完(T3.5 超时)。
当发生 T3.5 超时事件时,说明总线上的数据帧已经传完,处于空闲状态,为发起下一帧数
据传输做好了准备。所以接收状态机转换为 STATE_RX_IDLE,同时发送一个 EV_READY 事件,
告诉 Modbus 以及准备好接收数据了。同时关闭 T3.5 定时。
在 STATE_RX_IDLE 状态下,只会接收串口数据来触发状态转换(定时被关闭)。当接收到一
个字节时,认为总线开始了一个新的数据帧的传输,把这个字节保存在 Modbus 数据缓冲区,
并将缓冲区指针加 1,并将接收状态机转换为 STATE_RX_RCV。
在 STATE_RX_RCV 状态下,接收到一个新字节,将该字节保存在缓冲区,并将缓冲区指针加
1,判断接收的字节总长是否>最大帧长,如果不大于,继续保持 STATE_RX_RCV 状态,等待
接收下一个字节或超时(接收完成)。当大于最大帧长,说明接收到了错误帧。状态转到
STATE_RX_ERROR。
在 STATE_RX_RCV 状态下,产生了一个 T3.5 超时,此时认为总线已经发送完成一个 Modbus
数 据 帧 , 将 状 态 转 换 到 STATE_RX_IDLE , 等 待 下 一 个 数 据 帧 到 来 。 同 时 触 发
EV_FRAME_RECEIVED 事件,告诉 ModbusPoll 已经成功接收一帧数据,可以解析并处理了。
在 STATE_RX_ERROR 状态下,接收到再多的字节都认为是错误的,所以一直停留在错误态,
直到来了一个 T3.5 超时事件,此时认为总线上错误的数据帧发送完毕,总线静默,为下一
个数据帧准备好!接收状态机转换为 STATE_RX_IDLE。