freemodbus-rtu在单片机上使用时很难搞清数据从外部接收过来经历了哪些函数,这里做一个记录。
一般情况下我们的程序是在main的循环中调用eMBPoll函数,该函数对eEvent进行分支处理,这是处理流程(主流程)。
然后看数据接入流程,
假设我们的数据从USART1上接收,那么就找到USART1的中断函数USART1_IRQHandler
,这个函数名是固定的,但可能会被宏定义为其他的名字,比如MB_USART_IRQHandler
,MB_USART_IRQHandler
调用prvvUARTRxISR()
进而调用pxMBFrameCBByteReceived
,pxMBFrameCBByteReceived
是函数指针,RTU实现下它实际指向的函数为xMBRTUReceiveFSM
,xMBRTUReceiveFSM
调用xMBPortSerialGetByte
从USART1.RX上获取一个字节,根据接收状态eRcvState将一字节存入ucRTUBuf,同时开启定时器,定时执行xMBRTUTimerT35Expired
,定时时间大概刚好是接收一个字节的时间,也就是每接收一个字节执行一次,xMBRTUTimerT35Expired
根据接收状态改变eEvent,也就是eMBPoll的分支条件。
回到eMBPoll,如果eVent为EV_FRAME_RECEIVED,则调用peMBFrameReceiveCur
,peMBFrameReceiveCur
也是一个函数指针,在rtu实现中指向eMBRTUReceive
,eMBRTUReceive
中对ucRTUBuf进行CRC校验,也就是是否接收到完整一帧数据,同时将完整一帧数据放进参数ucMBFrame,然后将eVent设为EV_EXECUTE,使下一次eMBPoll循环进入数据解析分支。具体调用就是xFuncHandlers[i].pxHandler( ucMBFrame, &usLength )
,xFuncHandlers
是结构体数组,该结构体有两个成员,一个是功能码,另一个是对应的处理函数。至此数据的接收处理就完整闭环了。