完整版freeModbus代码解读及移植笔记

上传人:鲁** 文档编号:560193799 上传时间:2023-05-08 格式:DOCX 页数:8 大小:20.69KB
返回 下载 相关 举报
完整版freeModbus代码解读及移植笔记_第1页
第1页 / 共8页
完整版freeModbus代码解读及移植笔记_第2页
第2页 / 共8页
完整版freeModbus代码解读及移植笔记_第3页
第3页 / 共8页
完整版freeModbus代码解读及移植笔记_第4页
第4页 / 共8页
完整版freeModbus代码解读及移植笔记_第5页
第5页 / 共8页
点击查看更多>>
资源描述

《完整版freeModbus代码解读及移植笔记》由会员分享,可在线阅读,更多相关《完整版freeModbus代码解读及移植笔记(8页珍藏版)》请在金锄头文库上搜索。

1、完整版freeModbus代码解读及移植笔记1. FreeModbus协议分析协议必须首先调用初始化功能eMBinit()函数。后调用 eMBEnable(),最后,在循环体或者单独一个任务中调用eMBPoll()函 数。2. 应用层协议2.1. 系统的启动2.1.1. eMBI nit()函数的源码分析以 RTU 方式为例,首先,检查调用的地址是否合法。如不合法, 返回错误。如果合法则继续执行,首先,针对RTU方式还是ASCII方式,选择不同的编译模块。 对需要调用的函数指针进行复制。如果移植需要改变其他用途, 则要修改相应的指针,包括如下赋值:pvMBFrameStartCur = eMB

2、RTUStart; pvMBFrameStopCur = eMBRTUStop; peMBFrameSendCur = eMBRTUSend; peMBFrameReceiveCur = eMBRTUReceive; pvMBFrameCloseCur = MB_PORT_HAS_CLOSE ?vMBPortClose :NULL; pxMBFrameCBByteReceived= xMBRTUReceiveFSM; pxMBFrameCBTransmitterEmpty = xMBRTUTransmitFSM; pxMBPortCBTimerExpired = xMBRTUTimerT35E

3、xpired; 然 后 调 用 eStatus =eMBRTUInit( ucMBAddress, ucPort, ulBaudRate, eParity);具体初始化通讯端口。2.1.2. eMBRTUIniteMBRTUI nit这个函数主要干两件事: 第一,初始化串口:if( xMBPortSerialInit(ucPort, ulBaudRate, 8, eParity ) != TRUE ) eStatus = MB_EPORTERR;这个函数在portserial.c中,需要用户在移植的时候根据自己的处 理器编写。第二,初始化计时器:首先要根据波特率计算一下是 3.55.0 个 字

4、节周期的时间,然 后再调用 xMBPortTimersInit( ( USHORT ) usTimerT35_50us),初始化计时器。这个函数在中,需要用户在移植 的时候根据自己的处理器编写。porttimer.c2.1.3. eMBE nable源码分析首先,看看 Modbus 功能是否是被关闭的,如果不是被关闭(可 能是没有被初始化或者已经打开),就返回错误。如果是disable状态,就干下面两件事:l调用pvMBFrameStartCur()。由于这是个函数指针,在模块 eMBInit 中,指向了 eMBRTUStart 函数n 在源代码中有这样一段注释:,意思是,首先设置成 STAT

5、E_RX_INIT ,然 后 打开 计时 器, 等待 t3.5 以后 , 进入 STATE_RX_IDLE 状态。n 看源代码中,首先有设置 Receiver 的状态,后调用 vMBPortSerialEnable,设置接收状态,然后打开定时器。n 当定时器中断后,自动调用中断服务程序,在中断服务程序中, 只调用了 pxMBPortCBTimerExpired 而这是一函数指针,在RTU 方式初始化时,被指向了xMBRTUTimerT35Expired()函数。n xMBRTUTimerT35Expired 函数在 mbrtu.c 中,在这里,我们 只看第一种方式,就是进入初始化状态,在 t3

6、5 时间以后,只调用了 个 xNeedPoll =xMBPortEventPost( EV_READY );n xMBPortEve ntPost函数就是在事件队列里加了一个EV_RDY事 件。l然后,将eMB状态改为使能状态,l 初始化结束。2.2 .总线侦听 eMBPoll()首先,判断系统是否被使能,如果没有,则返回错误值。 然后,检查是否有事件发生,如果有,则根据不同类型的事件响 应:l如果是EV_RDY,表示系统刚刚进入侦听状态,则什么都不做;l如果状态为EV_FRAME_RECEIVED,也就是接收到完整的帧, 做下面两件事情:n 调 用 eStatus=peMBFrameRece

7、iveCur( &ucRcvAddress,&ucMBFrame, &usLength)。这是一个函数指针,在eMBInit中,被初始化指向 eMBRTUReceive。n eMBRTUReceive这个函数首先校验帧的长度和CRC,然后从 协议中解析出地址、数据和长度。n 然后检查地址,如果是广播地址或者是本机地址,就调用 xMBPortEventPost( EV-EXECUTE) , 将接 收器 的 状态 更 改为 EV_EXECUTE。l如果状态为EV_EXECUTE,就在函数列表中检查,有没有与命令 字段相符合的函数来解析相应则执行该函数,否则返回非法功能代码。数据发送2.3.发送数据

8、通过指针eMBRTUSend,调用eMBRTUSend函数。2.3.1. eMBRTUSe nd函数 这个函数的作用就是打包,将数据打包成帧。l首先,检查接收状态。因为MODBUS是基于RS-485半双工通 讯,所以当正在接收数据时,不发送该帧。l如果总线空,就将数据打包,将地址和CRC加入数据帧l 将总线状态改为发送。2.4. 功能注册l 对于指定的功能代码,需要一个功能回调函数来处理,格式如下 eMBException eMXXXXXX ( UCHAR *pucFrame, USHORT *usLen )丨需要通过函数eMBRegisterCB(功能代码,函数名)加到处理代码 中。具体源码

9、分析从略。2.4.1. prvvUARTTxReadyISR()总线状态改为发送后, 会在发送 缓冲时, 自动调用 prvvUARTTxReadyISR()中断服务程序。prvvUARTTxReadyISR()只调 用了一个函数,就是 pxMBFrameCBTransmitterEmpty()。 2.4.2. pxMBFrameCBByteReceived() pxMBFrameCBTransmitterEmpty() 是一个指针,指向了 xMBRTUTransmitFSM函数。3数据链路层协议数据链路层是最基本的打包部分,将数据打包成帧,送到应用层。 在数据链路层协议中,使用中断方式来接受。

10、那么每次接收到字符就 自动调用接收字符的 ISR 程序。按照规定,应该将中断服务程序安装 给prvvUARTRxISR(void)函数。实际上这个函数只调用了一个函数: pxMBFrameCBByteReceived() , 这 个 指 针 调 用 了 xMBRTUReceiveFSM 函数。3.1. xMBRTUReceiveFSM()函数 函数首先检查是不是处于发送状态。如果处于发送状态,直接退 出。l 首先调用 xMBPortSerialGetByte( ( CHAR * ) & ucByte),获取 从串口读到的字符。l 然后检查接受状态:n 如果是错误状态或者处于初始化状态,那么直接

11、等待,错过该 帧。n如果是STATE_RX_IDLE空闲状态,则将指针重置,将收到的第 一个字节存储到缓冲区,并将状态改为STATE_RX_RCV状态。n 如果处于接收状态,就判断,如果缓冲区未满,就将收到的字 节放入缓冲区,否则改为错误状态。l不管在任何状态,最后都开启了 t35计时器。在t35结束的时候, 通过指针调用了函数。xMBRTUTimerT35Expired().这么长l xMBRTUTimerT35Expired()函数检查状态,如果是接收 状态那就表明,已经有t35EV_FRAME_RECEIVED 的时间里,没有收到任新字节,当前 的帧结束。在队列里增加一个事件。如果是错误

12、状态,什么都不做。丨然后关掉计时器,将状态改为空闲。l3.2. xMBRTUTra nsmitFSM(函数首先判断总线是否忙,如果忙, 则终止。如果不忙,则继续,根据xMBRTUTra nsmitFSM发送状态变 量:(空闲)状态,则打开端口发送I如果当前为STATE_TX_IDLE, 则进一步判断发送队列是否为空, l 如果当前状态为 STATE_TX_XMIT 如果不空,则发送下一个字符n如果空,说明发送完成,关闭发送端口,改为侦听,并将状态改 为空闲。n4. 传输控制除了传输控制以外,还有传输控制的若干函数。通过 下面几个指针来调用:pvMBFrameStopCur() pvMBFram

13、eCloseCur()函数 4.1. pvMBFrameStopCur()pvMBFrameStopCur 是一个函 数指针,在RTU方式下,它指向eMBRTUStop()函数。该函数做下面 几件事情:l 关闭侦听和发送freeModbus 的代码库还是很好用的,本人在 wince 和 C8051F410下均移植成功(只用到RTU模式)。但freeModbus提 供的文档比较少,只能对照着 Modbus 协议一点点试着读懂源代码。 下面是阅读代码期间的跟踪笔记:1、eMBErrorCode为枚举类型变量,代表错误码,共有8个错误 代号。常用的是MB_ENOERR,即没有错误。2、eMBMode

14、 枚举类型变量代表设备的工作模式,分别是 MB_RTU、MB_ASCII和 MB_TCP。3、eMBEventType 枚举类型变量定义了 event 的类型,分别是 EV_READY,代表 Startup 启动完成;EV_FRAME_RECEIVED 代表接 收到帧;EV_EXECUTE代表执行功能函数;EV_FRAME_SENT代表帧已发送。4 、 eMBParity 枚举类型变量代表奇偶校验选项,分别是 MB_PAR_NONE 无校验,MB_PAR_ODD 奇校验,和 MB_PAR_EVEN 偶校验。函数中初、 mb.c 文件中的静态变量存储设备地址,此变量在 eMBInitucMBAd

15、dress 5 始化。源码进行了更改,例如尽量不使用函 数指库中的C51Modbus中将freeModbus6、在中的工作模式,来判 断调用哪个 eMBCurrentMode 针,而是直接调用相关功能函数,根 据编译器特有的关键词。Keil库中某些函数声明前加上reentrant,这 是函数。在 freeModbus 这样做带来的一个不足是:不能动态绑定函 数,从而导致库代码失去可移植性。这样做是 C51 标准不兼容的特殊 性导致的。编译器与ANSI实 际 上 就 是 关 宏 , 和 EXIT_CRITICAL_SECTION() 、 7ENTER_CRITICAL_SECTION()闭和打开

16、全局中断。协议栈。层,也就是独立于 8、带 xMBPort 前缀的函数都属于 port layerModBusenum表示返回9、freeModbus库中函数名称的第一字母表示 返回值类型,例如e布尔类型。注意这条规则并不是总成立,v枚举类 型;表示void无返回值;BOOLx表示协议栈的但主要函数基本上还 是符合此规则的。第一个字母后的ModBusMB代表是属于函数。UartO需要用其值计算10、port.h文件中宏#define F_MCU定 义了单片机的工作频率。定时器的重装入值。Tick定时器和main中,使用协议栈的方法是:11、在程序主函数eStatus = eMBInit( MB_RTU, 0x0A, 0, 9600, MB_PAR_EVE

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 学术论文 > 其它学术论文

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号