




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、1. FreeModbus协议分析协议必须首先调用初始化功能eMBinit()函数。后调用eMBEnable(),最后,在循环体或者单独一个任务中调用eMBPoll()函数。2. 应用层协议2.1. 系统的启动. eMBInit()函数的源码分析以RTU方式为例,首先,检查调用的地址是否合法。如不合法,返回错误。如果合法则继续执行,首先,针对RTU方式还是ASCII方式,选择不同的编译模块。对需要调用的函数指针进行复制。如果移植需要改变其他用途,则要修改相应的指针,包括如下赋值:
2、160; pvMBFrameStartCur = eMBRTUStart; pvMBFrameStopCur = eMBRTUStop; peMBFrameSendCur = eMBRTUSend;
3、 peMBFrameReceiveCur = eMBRTUReceive; pvMBFrameCloseCur = MB_PORT_HAS_CLOSE ? vMBPortClose :NULL; pxMBFrameCBByteRece
4、ived= xMBRTUReceiveFSM; pxMBFrameCBTransmitterEmpty = xMBRTUTransmitFSM; pxMBPortCBTimerExpired = xMBRTUTimerT35Expired;然后调用eStatus =eMBRTUInit( ucMBAddress, ucPort, ulBa
5、udRate, eParity);具体初始化通讯端口。. eMBRTUIniteMBRTUInit这个函数主要干两件事:第一, 初始化串口: if( xMBPortSerialInit(ucPort, ulBaudRate, 8, eParity ) != TRUE ) eStatus = MB_EPORTERR;这个函数在portserial.c中,需要用户在移植的时候根据自己的处理器编写。第二, 初始化计时器:首先要根据波特率计算一下是3.55.0个字节周期的时间,然后
6、再调用xMBPortTimersInit( ( USHORT ) usTimerT35_50us),初始化计时器。这个函数在porttimer.c中,需要用户在移植的时候根据自己的处理器编写。. eMBEnable源码分析首先,看看Modbus功能是否是被关闭的,如果不是被关闭(可能是没有被初始化或者已经打开),就返回错误。如果是disable状态,就干下面两件事:l 调用pvMBFrameStartCur()。由于这是个函数指针,在模块eMBInit中,指向了eMBRTUStart函数n 在源代码中有这样一段注释:,意思是,首先设置成STATE_RX
7、_INIT,然后打开计时器,等待t3.5以后,进入STATE_RX_IDLE状态。n 看源代码中,首先有设置Receiver的状态,后调用vMBPortSerialEnable,设置接收状态,然后打开定时器。n 当定时器中断后,自动调用中断服务程序,在中断服务程序中,只调用了pxMBPortCBTimerExpired,而这是一个函数指针,在RTU方式初始化时,被指向了xMBRTUTimerT35Expired()函数。n xMBRTUTimerT35Expired函数在mbrtu.c中,在这里,我们只看第一种方式,就是进入初始化状态,在t35时间以后,只调用了一
8、个xNeedPoll = xMBPortEventPost( EV_READY );n xMBPortEventPost函数就是在事件队列里加了一个EV_RDY事件。l 然后,将eMB状态改为使能状态,l 初始化结束。2.2. 总线侦听eMBPoll()首先,判断系统是否被使能,如果没有,则返回错误值。然后,检查是否有事件发生,如果有,则根据不同类型的事件响应:l 如果是EV_RDY,表示系统刚刚进入侦听状态,则什么都不做;l 如果状态为EV_FRAME_RECEIVED,也就是接收到完整的帧,做下
9、面两件事情:n 调用eStatus=peMBFrameReceiveCur( &ucRcvAddress,&ucMBFrame, &usLength)。这是一个函数指针,在eMBInit中,被初始化指向eMBRTUReceive。n eMBRTUReceive这个函数首先校验帧的长度和CRC,然后从协议中解析出地址、数据和长度。n 然后检查地址,如果是广播地址或者是本机地址,就调用xMBPortEventPost( EV-EXECUTE),将接收器的状态更改为EV_EXECUTE。l 如果状态为EV_EXECUTE,就在函数列表中
10、检查,有没有与命令字段相符合的函数来解析相应则执行该函数,否则返回非法功能代码。2.3. 数据发送发送数据通过指针eMBRTUSend,调用eMBRTUSend函数。. eMBRTUSend函数这个函数的作用就是打包,将数据打包成帧。l 首先,检查接收状态。因为MODBUS是基于RS-485半双工通讯,所以当正在接收数据时,不发送该帧。l 如果总线空,就将数据打包,将地址和CRC加入数据帧l 将总线状态改为发送。2.4. 功能注册l 对于指定的功能代码,需要一个功能回调函数来处理,格式如下。eMBExceptio
11、n eMXXXXXX ( UCHAR *pucFrame, USHORT * usLen )l 需要通过函数eMBRegisterCB(功能代码,函数名)加到处理代码中。具体源码分析从略。. prvvUARTTxReadyISR()总线状态改为发送后,会在发送缓冲时,自动调用prvvUARTTxReadyISR()中断服务程序。prvvUARTTxReadyISR()只调用了一个函数,就是pxMBFrameCBTransmitterEmpty ()。. pxMBFrameCBByteReceived()pxMBFrameCBTransmit
12、terEmpty()是一个指针,指向了xMBRTUTransmitFSM函数。3. 数据链路层协议数据链路层是最基本的打包部分,将数据打包成帧,送到应用层。在数据链路层协议中,使用中断方式来接受。那么每次接收到字符就自动调用接收字符的ISR程序。按照规定,应该将中断服务程序安装给prvvUARTRxISR(void)函数。实际上这个函数只调用了一个函数:pxMBFrameCBByteReceived(),这个指针调用了xMBRTUReceiveFSM函数。3.1. xMBRTUReceiveFSM()函数函数首先检查是不是处于发送状态。如果处于发送状态,直接退出
13、。l 首先调用xMBPortSerialGetByte( ( CHAR * ) & ucByte),获取从串口读到的字符。l 然后检查接受状态:n 如果是错误状态或者处于初始化状态,那么直接等待,错过该帧。n 如果是STATE_RX_IDLE空闲状态,则将指针重置,将收到的第一个字节存储到缓冲区,并将状态改为STATE_RX_RCV状态。n 如果处于接收状态,就判断,如果缓冲区未满,就将收到的字节放入缓冲区,否则改为错误状态。l 不管在任何状态,最后都开启了t35计时器。在t35结束的时候,通过指针调用了xMBRTUTimer
14、T35Expired()函数。l xMBRTUTimerT35Expired()函数检查状态,如果是接收状态那就表明,已经有t35这么长的时间里,没有收到任新字节,当前的帧结束。在队列里增加一个EV_FRAME_RECEIVED事件。l 如果是错误状态,什么都不做。l 然后关掉计时器,将状态改为空闲。3.2. xMBRTUTransmitFSM()函数xMBRTUTransmitFSM首先判断总线是否忙,如果忙,则终止。如果不忙,则继续,根据发送状态变量:l 如果当前为STATE_TX_IDLE(空闲)状态,则打开端口发送l 如果当前
15、状态为STATE_TX_XMIT,则进一步判断发送队列是否为空,n 如果不空,则发送下一个字符n 如果空,说明发送完成,关闭发送端口,改为侦听,并将状态改为空闲。4. 传输控制除了传输控制以外,还有传输控制的若干函数。通过下面几个指针来调用: pvMBFrameStopCur() pvMBFrameCloseCur()4.1. pvMBFrameStopCu
16、r()函数pvMBFrameStopCur是一个函数指针,在RTU方式下,它指向eMBRTUStop()函数。该函数做下面几件事情:l 关闭侦听和发送freeModbus的代码库还是很好用的,本人在wince和C8051F410下均移植成功(只用到RTU模式)。但freeModbus提供的文档比较少,只能对照着Modbus协议一点点试着读懂源代码。下面是阅读代码期间的跟踪笔记:1、eMBErrorCode为枚举类型变量,代表错误码,共有8个错误代号。常用的是MB_ENOERR,即没有错误。2、eMBMode枚举类型变量代表设备的工作模式,分别是MB_RTU、MB_ASCII和MB_T
17、CP。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偶校验。5、mb.c文件中的静态变量ucMBAddress存储设备地址,此变量在eMBInit函数中初始化。6、在C51Modbus中将freeModbus库中的源码进行了更改,例如尽量不使用函数指针,而是直接调
18、用相关功能函数,根据eMBCurrentMode中的工作模式,来判断调用哪个函数。在freeModbus库中某些函数声明前加上reentrant,这是Keil编译器特有的关键词。这样做带来的一个不足是:不能动态绑定函数,从而导致库代码失去可移植性。这样做是C51编译器与ANSI标准不兼容的特殊性导致的。7、ENTER_CRITICAL_SECTION()和EXIT_CRITICAL_SECTION()宏,实际上就是关闭和打开全局中断。8、带xMBPort前缀的函数都属于port layer层,也就是独立于ModBus协议栈。9、freeModbus库中函数名称的第一个字母表示返回值类型,例如e
19、表示返回enum枚举类型;v表示void无返回值;x表示BOOL布尔类型。注意这条规则并不是总成立,但主要函数基本上还是符合此规则的。第一个字母后的MB代表是属于ModBus协议栈的函数。10、port.h文件中宏#define F_MCU 定义了单片机的工作频率。需要用其值计算Uart0定时器和Tick定时器的重装入值。11、在程序主函数main中,使用协议栈的方法是:eStatus = eMBInit( MB_RTU, 0x0A, 0, 9600, MB_PAR_EVEN );/* Enable the Modbus Protocol Stack. */eStatus = eMBEnabl
20、e( );for( ; )( void )eMBPoll( );12、在port layer层的xMBPortSerialInit函数中,需要根据传入的波特率、奇偶校验、数据位长度设置来配置Uart0及其使用的定时器。13、在port layer层的vMBPortSerialEnable函数中配置接收和发送使能,由于在单片机的寄存器SCON0中只有接收使能控制位REN0,而没有发送使能控制位,所以在portserial.c文件中又定义了一个TxEnable变量,用来表示发送的使能状态。若同时关闭接收和发送,则要关闭Uart0中断,即让ES0 = 0。14、eMBRTUInit函数中的变量usT
21、imerT35_50us代表如果50us进行一次Tick的话,T35超时的Tick次数。这个公式很重要:usTimerT35_50us = ( 7UL * 220000UL ) / ( 2UL * ulBaudRate );函数xMBPortTimersInit要以变量usTimerT35_50us为传入参数,对T35超时定时器进行设置。15、在mbrtu.c文件中定义了两个状态变量,一个是接收状态变量eRcvState,为eMBRcvState枚举类型,有4个状态,在使能ModBus协议栈后赋予STATE_RX_INIT,即初始状态;另一个是发送状态变量eSndState,为eMBSndSt
22、ate枚举类型,有两个状态,初始化为发送idle状态,即STATE_TX_IDLE。16、mb.c文件中的eMBState状态变量为枚举类型,代表设备的工作状态,有3种状态,分别是“未初始化”、 “使能”和“禁止”状态。调用完eMBInit 函数后要调用eMBEnable函数来使能ModBus协议栈,在其中将eMBState状态变量从“未初始化状态”变为“使能状态”,然后使能串口和打开T35定时器。17、如果T35定时器超时并产生中断,则要调用xMBRTUTimerT35Expired函数,其内部是一个状态机转换的switch,根据当前接收状态来通过xMBPortEventPost发送事件通知
23、,然后关闭T35定时器,并将当前接收状态设置为STATE_RX_IDLE。18、eMBException枚举型变量表示Exception的类型,共有10种Exception,在ModBus协议中有定义。19、在eMBPoll( )中,首先通过xMBPortEventGet函数取event,如果没有则退出,若有event的话便根据event类型进行相应处理。EV_READY是在协议栈初始化后xMBRTUTimerT35Expired函数发出来的,表示startup完成;EV_FRAME_RECEIVED是xMBRTUTimerT35Expired函数在T35超时后发出的,表示已经收到了一帧,需要进行成帧处理,调用eMBRTUReceive函数;EV_EXECUTE是在处理EV_FRAME_RECEIVED过程中最后一步,如果此帧的地址符合本机地址,则发出EV_EXECUTE事件,进行应用层的处理。20、在eMBRTUReceive函数中首先查看帧大小是否符合要求,然后进行CRC校验。此函数的原型是:eMBRTUReceive( UCHAR * pucRcvAddress, UCHAR * pucFrame, USHORT *
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 月饼定货协议书
- 车厂车辆改造合同协议
- 土地承包合同终止
- 社区农业科技应用示范项目协议
- 专业论坛会议举办协议
- 车订车定金合同协议
- 过渡合同协议
- 转让露营推车合同协议
- 超龄工合同协议
- 滞留人员协议书
- (三模)合肥市2025届高三年级5月教学质量检测政治试卷(含答案解析)
- 生物+昆一中2025届高三联考试卷及答案(九)
- 课题申报书:现代产业学院内部治理结构研究
- 2025年人教版小学五年级下册奥林匹克数学竞赛试卷(附参考答案)
- 陕西、山西省天一大联考2024-2025学年高中毕业班阶段性测试(七)语文试题及答案
- 《油气井套管工程检测技术》课件
- 大学生就业去向论文
- 2025届高考语文复习:2024年新课标二卷第九题说题 课件
- 2024年铁总服务有限公司招聘笔试真题
- 职业技术学院2024级安全技术与管理专业人才培养方案
- 2025天津经济技术开发区管理委员会招聘雇员(30人)笔试参考题库附带答案详解
评论
0/150
提交评论