OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 7637|回复: 5

Modbus Master主机模式协议分析

[复制链接]

7

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
89
金钱
89
注册时间
2015-10-2
在线时间
7 小时
发表于 2018-7-22 16:40:27 | 显示全部楼层 |阅读模式
该代码是基于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,那么则清除主机忙状态。
到此为止,我们完成了主机从发送数据到接收数据并且处理完成的分析。

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

7

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
89
金钱
89
注册时间
2015-10-2
在线时间
7 小时
 楼主| 发表于 2018-7-22 16:41:38 | 显示全部楼层
这个个人的一些见解,如有不妥,请大神们指正!!!
回复 支持 反对

使用道具 举报

7

主题

188

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
385
金钱
385
注册时间
2018-7-19
在线时间
126 小时
发表于 2018-9-29 15:40:02 | 显示全部楼层
大佬,能不能详细说一下对于这个事件处理,还有异常捕获,我现在移植这个主机部分,需要把操作系统去掉,在移植过程中portevent_m.c子程序我几乎都屏蔽掉了
回复 支持 反对

使用道具 举报

2

主题

474

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6077
金钱
6077
注册时间
2018-6-27
在线时间
524 小时
发表于 2018-11-6 15:15:03 | 显示全部楼层
学习学习,学习学习。
回复 支持 反对

使用道具 举报

0

主题

8

帖子

0

精华

新手上路

积分
22
金钱
22
注册时间
2019-12-8
在线时间
3 小时
发表于 2019-12-29 22:20:37 | 显示全部楼层
kkkkkkkkkkkkk
回复 支持 反对

使用道具 举报

0

主题

8

帖子

0

精华

新手上路

积分
22
金钱
22
注册时间
2019-12-8
在线时间
3 小时
发表于 2019-12-29 22:20:59 | 显示全部楼层
kkkkkkkkkkkkk
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 22:16

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表