完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
分析的代码地址:https://github.com/lianggongkai/FreeModbus_Slave-Master-RTT-STM32该代码是基于RT-thread操作系统的主机通信程序。现将代码分析写下来,以便自己的移植操作以后后期的维护。1,首先要有一个线程(函数)进行主机发出请求。具体内部操作是:准备了 从机地址,数据帧指令,数据帧地址,数据帧长度,然后建立一个事件:EV_MASTER_FRAME_SENT,探后等待请求完成。 2,在eMBMasterPoll(void)函数中,Poll线程(函数),检测到有事件EV_MASTER_FRAME_SENT发生,则进行该事件的执行。该事件的执行过程是:peMBMasterFrameSendCur()函数。该函数是一个函数指针,指向了eMBMasterRTUSend(),实际上是调用了RTU层的发送函数。实际上第1步进行的准备工作操作的数据帧地址都是在RTU层的静态缓冲区。第2步进行的发送也是在这个静态缓冲区进行的。函数eMBMasterRTUSend()执行过程:首先检测一下当前的接收状态机是 空闲状态,则在静态数据缓冲区进行数据的操作,写入数据长度,写入CRC校验码。最后一步设置发送状态机的当前状态为开始传送状态为:STATE_M_TX_XMIT,并且开启发送口。 3,接下来的执行就是在中断服务程序中。中断服务程序中执行的回调函数也是一个状态机形式:实际就是:xMBMasterRTUTransmitFSM(),在该函数中的状态机执行情况:在 STATE_M_TX_XMIT状态只要没有发送结束将一直进行数据发送直到usMasterSndBufferCount数据为0。更新当前数据帧是否为广播地址,关闭发送口,开启接收口。同时设置发送状态机状态为:STATE_M_TX_XFWR。如果是广播地址则使能广播延时定时器,如果不是广播开启响应延时定时器。 4, 在定时器服务函数xMBMasterRTUtimerExpired中,根据第3步,当前发送状态机是STATE_M_TX_XFWR状态.如果当前数据帧是广播则直接设置当前发送状态机为STATE_M_TX_IDLE,空闲状态。同时关闭定时器。如果当前数据帧不是广播帧,则告诉监听进程数据发送错误,设置从机响应超时错误。同时设置主机发送状态机为空闲状态,同时关闭定时器。如果是主机当前的定时模式是:MB_TMODE_CONVERT_DELAY则关闭主机忙状态。 5 ,截止目前为止eRcvState(接收状态机)是STATE_M_RX_IDLE。发送状态机(eSndState)为STATE_M_TX_IDLE主机指令已经完成了送出动作。下一步应该就是,主机接收来自从机的回传数据。当串口接收中断到来,则调用prvvUARTRxISR() -> pxMBMasterFrameCBByteReceived() 而pxMBMasterFrameCBByteReceived作为一个回调函数,在mb_m.c文件中被初始化为:xMBMasterRTUReceiveFSM则mbrtu_m.c文件中的xMBMasterRTUReceiveFSM()函数最终被中断函数调用。 6, 现在进入xMBMasterRTUReceiveFSM()函数中分析。进入函数执行接收动作。如果是首次进入该函数,接受状态机为空闲模式STATE_M_RX_IDLE则关闭主机超时定时器,设置发送状态机为空闲,同时主机接收缓冲区位置指针(usMasterRcvBufferPos)置0。根据usMasterRcvBufferPos,在缓冲区ucMasterRTURcvBuf[],里面放置接收数据。同事设置接收状态机为接收状态STATE_M_RX_RCV。同时开启超时定时器。 还是在xMBMasterRTUReceiveFSM()函数中,接受状态机为空闲模式STATE_M_RX_RCV,只要缓冲区位置指针小于一帧数据的最大值,则一直往缓冲区写数据。否则大于一帧数据的最大值,则接收状态机置错误标志。下一步更新T3.5定时器。直到数据接收完成后。T3.5定时器超时到达,表示一帧数据完成。那么在xMBMasterRTUTimerExpired()中断服务函数中,根据接收状态机模式STATE_M_RX_RCV,则设置事件xMBMasterPortEventPost(EV_MASTER_FRAME_RECEIVED)。表示一帧数据接收完成。 7 ,现在根据当前事件EV_MASTER_FRAME_RECEIVED,在eMBMasterPoll()函数中,调用peMBMasterFrameReceiveCur(),进行长度检测和CRC检测,完成之后获取接收的数据帧中数据地址(pucRcvAddress),同事传出数据帧的缓冲区有效数据的帧地址给上层应用。将接收的数据帧地址和主机发送的地址进行比较,正确时候则设置事件:xMBMasterPortEventPost( EV_MASTER_EXECUTE ) 8, 仍然是根据当前事件EV_MASTER_EXECUTE ,在eMBMasterPoll()函数中,提取数据帧的功能码,根据功能码,调用对应功能码的函数指针。举例:如果一开始主机发送了读取从机地址为2,3X区域,区地址100的20个数据,那么返回的数据中,肯定提取到功能码04,然后根据04功能码对应的函数,进行对应的数据更新。如果功能码超出协议规定的范围,则抛出EV_MASTER_ERROR_PROCESS异常事件。 9, 如果真的有异常事件EV_MASTER_ERROR_PROCESS,那么则清除主机忙状态。 到此为止,我们完成了主机从发送数据到接收数据并且处理完成的分析。
|
|
相关推荐
3个回答
|
|
这个个人的一些见解,如有不妥,请大神们指正!!!
|
|
|
|
大佬,能不能详细说一下对于这个事件处理,还有异常捕获,我现在移植这个主机部分,需要把操作系统去掉,在移植过程中portevent_m.c子程序我几乎都屏蔽掉了
|
|
|
|
学习学习,学习学习。
|
|
|
|
只有小组成员才能发言,加入小组>>
689 浏览 0 评论
1102 浏览 1 评论
2469 浏览 5 评论
2803 浏览 9 评论
移植了freeRTOS到STMf103之后显示没有定义的原因?
2642 浏览 6 评论
使用eim外接fpga可是端口一点反应都没有有没有大哥指点一下啊
650浏览 9评论
648浏览 7评论
请教大神怎样去解决iMX6Q在linux3.0.35内核上做AP失败的问题呢
777浏览 6评论
622浏览 5评论
663浏览 5评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-20 02:40 , Processed in 1.004812 second(s), Total 84, Slave 65 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号