ImageVerifierCode 换一换
格式:DOCX , 页数:17 ,大小:49.61KB ,
资源ID:4008691      下载积分:2 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/4008691.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(FreeModbus学习笔记.docx)为本站会员(b****3)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

FreeModbus学习笔记.docx

1、FreeModbus学习笔记FreeModbus学习笔记一、 FreeModbus简介FreeMODBUS一个奥地利人写的Modbus协议。它是一个针对嵌入式应用的一个免费(自由)的通用MODBUS协议的移植。Modbus是一个工业制造环境中应用的一个通用协议。Modbus通信协议栈包括两层:Modbus应用层协议,该层定义了数据模式和功能;另外一层是网络层。FreeMODBUS 提供了RTU/ASCII 传输模式及TCP协议支持。FreeModbus遵循BSD许可证,这意味着用户可以将FreeModbus应用于商业环境中。目前版本FreeModbus-V1.5提供如下的功能支持:表1 Fre

2、eModbus-V1.5功能支持代码描述是否支持备注Master主机否Slave从机是MB_RTURTU模式是MB_ASCIIASCII模式是MB_TCPTCP模式是0x01读线圈是0x02读离散输入是0x03读保持寄存器是0x04读输入寄存器是0x05写单个线圈是0x06写单个寄存器是0x07读异常状态否0x08诊断否0x0B获取事件计数器否0x0C获取事件记录否0x0F写多个线圈是0x10写多个寄存器是0x11报告从机ID是协议与文档不一致0x14读文件记录否0x15写文件记录否0x16屏蔽写寄存器否0x17读/写多个寄存器是0x18写FIFO否0x2B封装接口传输否0x2B/0x0DCA

3、Nopen参考请求与应答否0x2B/0x0E读设备身份表示否二、 FreeModbus对硬件的需求FreeModbus协议对硬件的需求非常少基本上任何具有串行接口,并且有一些能够容纳modbus数据帧的RAM的微控制器都足够了。 一个异步串行接口,能够支持接收缓冲区满和发送缓存区空中断。 一个能够产生RTU传输所需要的t3.5字符超时定时器的时钟。对于软件部分,仅仅需要一个简单的事件队列。在使用操作系统的处理器上,可通过单独定义一个任务完成Modbus时间的查询。小点的微控制器往往不允许使用操作系统,在那种情况下,可以使用一个全局变量来实现该事件队列(Atmel AVR 移植使用这种方式实现)

4、。实际的存储器需求决定于所使用的Modbus模块的多少。下表列出了所支持的功能编译后所需要的存储器。ARM是使用GNUARM编译器3.4.4使用-O1选项得到的。AVR项数值是使用WinAVR编译器3.4.5使用-Os选项编译得到的。表2 FreeModbus对硬件的需求ModuleARM CodeARMRAM(static)AVR CodeAVR RAM(static)Modbus RTU (Required)1132Byte272Byte1456Byte266ByteModbus ASCII (Optional)1612Byte28Byte1222Byte16ByteModbus Func

5、tions 11180Byte34Byte1602Byte34ByteModbus Core (Required)924Byte180Byte608Byte75BytePorting Layer (Required 2)1756Byte16Byte704Byte7ByteTotals7304Byte530Byte5592Byte398Byte1 实际大小决定于可支持的Modbus功能码的多少。功能码可以在头文件mbconfig.h中进行配置。2 决定于硬件。三、 FreeModbus的移植1、 物理层接口文件的修改在物理层,用户只需完成串行口及超时定时器的配置即可。具体应修改接口文件ports

6、erial.c及porttimer.c。 portserial.c中函数的修改:1) void vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable )此函数的功能为设置串口状态。有两个参数:xRxEnable及xTxEnable。当xRxEnable为真时,应使能串口接收及接收中断。在RS485通讯系统中,还要注意将RS485接口芯片设为接收使能状态;当xTxEnable为真时,应使能串口发送及发送中断。在RS485通讯系统中,还要注意将RS485接口芯片设为发送使能状态。2) void vMBPortClose( void )此函数的功能是

7、关闭Modbus通讯端口,具体的,应在此函数中关闭通讯端口的发送使能及接收使能。3) BOOL xMBPortSerialInit(UCHAR ucPORT,ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity)此函数的功能是初始化串行通讯端口。有四个参数:ucPORT、ulBaudRate、ucDataBits及eParity。参数ucPORT可以忽略;参数ulBaudRate是通讯端口的波特率,应根据此数值设置所使用硬件端口的波特率;参数ucDataBits为通讯时所使用的数据位宽,注意,若使用RTU模式,则有ucDataBits=8,

8、若使用ASCII模式,则有ucDataBits=7,应根据此参数设置所使用硬件端口的数据位宽;eParity为校验方式,eParity=MB_PAR_NONE为无校验,此时硬件端口应设置为无校验方式及两个停止位,eParity=MB_PAR_ODD为奇校验,此时硬件端口应设置为奇校验方式及一个停止位,eParity= MB_PAR_EVEN为偶校验,此时硬件端口应设置为偶校验方式及一个停止位。函数返回值务必为TRUE。4) BOOL xMBPortSerialPutByte(CHAR ucByte)此函数的功能为通讯端口发送一字节数据。参数为:ucByte,待发送的数据。应在此函数中编写发送一

9、字节数据的函数。注意,由于使用的是中断发送,故只需将数据放到发送寄存器即可。函数返回值务必为TRUE。5) BOOL xMBPortSerialGetByte( CHAR * pucByte )此函数的功能为通讯端口接收一字节数据。参数为:* pucByte,接收到的数据。应在此函数中编写接收的函数。注意,由于使用的是中断接收,故只需将接收寄存器的值放到* pucByte即可。函数返回值务必为TRUE。6) void prvvUARTTxReadyISR(void)发送中断函数。此函数无需修改。只需在用户的发送中断函数中调用此函数即可,同时,用户应在调用此函数后,清除发送中断标志位。7) vo

10、id prvvUARTRxISR(void)发送中断函数。此函数无需修改。只需在用户的接收中断函数中调用此函数即可,同时,用户应在调用此函数后,清除接收中断标志位。 portserial.c中函数的修改:1) BOOL xMBPortTimersInit( USHORT usTim1Timerout50us )此函数的功能为初始化超时定时器。参数为:usTim1Timerout50us,50us的个数。用户应根据所使用的硬件初始化超时定时器,使之能产生中断时间为usTim1Timerout50us*50us的中断。函数返回值务必为TRUE。2) void vMBPortTimersEnable

11、( )此函数的功能为使能超时定时器。用户需在此函数中清除中断标志位、清零定时器计数值,并重新使能定时器中断。3) void vMBPortTimersDisable( )此函数的功能为关闭超时定时器。用户需在此函数中清零定时器计数值,并关闭定时器中断。4) void TIMERExpiredISR( void )定时器中断函数。此函数无需修改。只需在用户的定时器中断中调用此函数即可,同时,用户应在调用此函数后清除中断标志位。2、 应用层回函数的修改在应用层,用户需要定义所需要使用的寄存器,并修改对应的回函数。回函数有如下几个:1) eMBErrorCodeeMBRegInputCB( UCHA

12、R * pucRegBuffer, USHORT usAddress, USHORT usNRegs )输入寄存器回函数。* pucRegBuffer为要添加到协议中的数据,usAddress为输入寄存器地址,usNRegs为要读取寄存器的个数。用户应根据要访问的寄存器地址usAddress将相应输入寄存器的值按顺序添加到pucRegBuffer中。2) eMBErrorCodeeMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode )保持寄存器回函数。* pu

13、cRegBuffer为要协议中的数据,usAddress为输入寄存器地址,usNRegs为访问寄存器的个数,eMode为访问类型(MB_REG_READ为读保持寄存器,MB_REG_WRITE为写保持寄存器)。用户应根据要访问的寄存器地址usAddress将相应输入寄存器的值按顺序添加到pucRegBuffer中,或将协议中的数据根据要访问的寄存器地址usAddress放到相应保持寄存器中。3) eMBErrorCodeeMBRegCoilsCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNCoils,eMBRegisterMode e

14、Mode )读写线圈回函数。* pucRegBuffer为要添加到协议中的数据,usAddress为线圈地址,usNCoils为要访问线圈的个数,eMode为访问类型(MB_REG_READ为读线圈状态,MB_REG_WRITE为写线圈)。用户应根据要访问的线圈地址usAddress将相应线圈的值按顺序添加到pucRegBuffer中,或将协议中的数据根据要访问的线圈地址usAddress放到相应线圈中。4) eMBErrorCodeeMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete )读离散

15、线圈回函数。* pucRegBuffer为要添加到协议中的数据,usAddress为线圈地址,usNDiscrete为要访问线圈的个数。用户应根据要访问的线圈地址usAddress将相应线圈的值按顺序添加到pucRegBuffer中。3、 应用层初始化及协议访问用户只需在主函数中调用协议初始化代码,及消息处理函数即可。需用户调用的函数有如下几个:1) eMBErrorCodeeMBInit( eMBMode eMode, UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity )协议初始化函数。eMode为

16、所要使用的模式,用户可选MB_RTU(RTU模式)、MB_ASCII(ASCII模式)或MB_TCP(TCP模式);ucSlaveAddress为从机地址,用户根据需要,取值为1247(0为广播地址,248255协议保留);ulBaudRate为通信波特率,用户根据需要选用,但务必使主机能支持此波特率;eParity为校验方式,用户根据需要选用,但务必使主机能支持此校验方式。2) eMBErrorCodeeMBSetSlaveID( UCHAR ucSlaveID, BOOL xIsRunning,UCHAR const *pucAdditional, USHORT usAdditionalL

17、en )从机ID设置函数。注意,ID表示的是设备的类型,不同于ucSlaveAddress(从机地址)。对同一通讯系统中,可以有相同的ucSlaveID,但不可以有相同的ucSlaveAddress。ucSlaveID为一字节的设备ID号;xIsRunning为设备的运行状态,0xFF为运行,0x00为停止;*pucAdditional为设备的附加描述,根据需要添加;usAdditionalLen为附加描述的长度(按字节计算)。此函数不是必须调用的。但当一个Modbus通讯系统中有不同种设备时,应调用此函数添加对应设备的描述。3) eMBErrorCodeeMBPoll( void )轮询事件

18、查询处理函数。用户需在主循环中调用此函数。对于使用操作系统的程序,应单独创建一个任务,使操作系统能周期调用此函数。四、 FreeModbus初始化及运行流程FreeModbus是基于消息队列的协议。协议通过检测相应的消息来完成对应功能。协议栈的初始化及运行流程如下:1) 首先调用eMBErrorCodeeMBInit( eMBMode eMode, UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity )完成物理层设备的初始化,主要包括:BOOL xMBPortSerialInit( UCHAR ucPO

19、RT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity )串口初始化,设定波特率、数据位数、校验方式;BOOL xMBPortTimersInit( USHORT usTim1Timerout50us )定时器初始化,设定T35定时所需要的定时器常数。2) 调用(此处非必需)eMBErrorCodeeMBSetSlaveID( UCHAR ucSlaveID, BOOL xIsRunning,UCHAR const *pucAdditional, USHORT usAdditionalLen )指定设备ID。3) 调用eMBError

20、CodeeMBEnable(void)使能协议栈,主要包括:static pvMBFrameStart pvMBFrameStartCur(函数指针)协议栈开始,将eRcvState设为STATE_RX_INIT状态,调用void vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable )使能接收,调用void vMBPortTimersEnable( )使能超时定时器。4) 在3中使能了超时定时器,故经过T35时间后,发生第一次超时中断,在中断中,向协议栈发送消息EV_READY(Startup finished),并调用void vMBPor

21、tTimersDisable( )关闭超时定时器,同时将eRcvState设为STATE_RX_IDLE。此时,协议栈可以接收串口数据。注意,此处首先启用一次超时定时器是因为初始化完成时,串口有可能已经有数据,因为无法判断第一个数据是请求的开始,故等待T35,接收下一帧请求。5) 此时,主函数调用eMBErrorCodeeMBPoll( void )检测事件。6) 若发生串口接收中断,且eRcvState为STATE_RX_IDLE(4中已将eRcvState设为STATE_RX_IDLE),则向接收缓存中存入接收到的字符,同时将eRcvState设为STATE_RX_RCV状态,并清零超时定

22、时器。在下一个数据来到时,不断将数据存入接收缓存,并清零超时定时器。7) 如果没有接收完成,则不可能发生超时中断。发生超时中断,说明T35时间内未收到新的串口数据,根据Modbus协议的规定,这指示着一帧请求数据接收完成。在中断中,向协议栈发送消息EV_FRAME_RECEIVED(Frame received),等待协议栈处理此消息。8) 主函数调用eMBErrorCodeeMBPoll( void )检测到事件EV_FRAME_RECEIVED后,调用static peMBFrameReceive peMBFrameReceiveCur简单判断请求帧数据,并向协议栈发送消息EV_EXECU

23、TE(Execute function)。9) 主函数调用eMBErrorCodeeMBPoll( void )检测到事件EV_EXECUTE后,根据相应的请求代码查找处理该功能的函数指针来处理该功能。若不是广播消息,则调用static peMBFrameSend peMBFrameSendCur发送回复消息,在此函数中,只把要回复的数据复制到了串口缓存中,同时将eSndState设为STATE_TX_XMIT(Transmitter is in transfer state),并通过调用void vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEna

24、ble )使能发送中断。注意,发送中断使能后,由于串口发送寄存器本来就是空的,故在使能后将进入发送中断中。10) 发送中断中,且eSndState为STATE_TX_XMIT(9中已将eSndState设为STATE_TX_XMIT),则将串口缓存中的数据发送出去,同时不断对发送字符个数统计,当发送完成后,向协议栈发送消息EV_FRAME_SENT(Frame sent)。11) 主函数调用eMBErrorCodeeMBPoll( void )检测到事件EV_FRAME_SENT后,不处理此消息。12) 当串口接收到数据后,协议栈将重复6-11处理消息。五、 一些理解1. 关于mbrtu.c文

25、件的理解 宏定义与变量mbrtu.c文件中定义了RTU模式下的宏定义、全局变量与功能函数。所包含的宏定义与全局变量定义如下:/* - Defines -*/#define MB_SER_PDU_SIZE_MIN 4 /*! Minimum size of a Modbus RTU frame. */#define MB_SER_PDU_SIZE_MAX 256 /*! Maximum size of a Modbus RTU frame. */#define MB_SER_PDU_SIZE_CRC 2 /*! Size of CRC field in PDU. */#define MB_SER

26、_PDU_ADDR_OFF 0 /*! Offset of slave address in Ser-PDU. */#define MB_SER_PDU_PDU_OFF 1 /*! Offset of Modbus-PDU in Ser-PDU. */* - Type definitions -*/typedef enum STATE_RX_INIT, /*! Receiver is in initial state. */ STATE_RX_IDLE, /*! Receiver is in idle state. */ STATE_RX_RCV, /*! Frame is beeing re

27、ceived. */ STATE_RX_ERROR /*! If the frame is invalid. */ eMBRcvState;typedef enum STATE_TX_IDLE, /*! Transmitter is in idle state. */ STATE_TX_XMIT /*! Transmitter is in transfer state. */ eMBSndState;/* - Static variables -*/static volatile eMBSndState eSndState;static volatile eMBRcvState eRcvSta

28、te;volatile UCHAR ucRTUBufMB_SER_PDU_SIZE_MAX;static volatile UCHAR *pucSndBufferCur;static volatile USHORT usSndBufferCount;static volatile USHORT usRcvBufferPos;首先在宏定义中,指明了该模式下所支持的最小请求帧长度为4(1字节地址+1字节命令+2字节校验),最大请求帧长度为256,CRC为两字节,地址为第一字节,PDU开始于第二字节。在全局变量中,只定义了一个串口缓存数组ucRTUBufMB_SER_PDU_SIZE_MAX。由于发

29、送与接收不是同步的,故可采用该缓存数组实现Modbus协议。在接收过程中,将所接收到的数据直接存放于缓存ucRTUBuf中,在发送过程中,通过指针*pucSndBufferCur来访问该数组。 eMBErrorCodeeMBRTUInit( UCHAR ucSlaveAddress, UCHAR ucPort, ULONG ulBaudRate, eMBParity eParity )此函数为RTU模式的初始化函数。此函数中判断串行口初始化是否成功(通过判断串行口初始化函数的返回值实现。当然,查看返回值必然先调用该函数,从而完成端口初始化),如果成功,则根据波特率计算T35,初始化超时定时器。

30、 voideMBRTUStart( void )此函数为RTU模式开始函数。函数主要功能是,将接收状态eRcvState设为STATE_RX_INIT(Receiver is in initial state),使能接收同时关闭发送,使能超时定时器。 voideMBRTUStop( void )此函数为RTU模式终止函数。函数主要功能是,关闭接收与发送,关闭超时定时器。 eMBErrorCodeeMBRTUReceive( UCHAR * pucRcvAddress, UCHAR * pucFrame, USHORT * pusLength )此函数为RTU接收数据帧信息提取函数。函数主要功能是,将接收帧(存放于缓存)的地址指针赋给指针变量pucRcvAddress,将PDU编码首地址赋给指针* pucFrame,将PDU长度地址赋给指针变量pusLength。使用指针访问缓存数组,而不是额外开辟缓存存放帧信息,大大减少了内存的开支。 eMBErrorCodeeMBRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength )此函数为RTU回复帧信息组织函数。函数的功能是,此函数

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1