FreeModbus Slave 改进的eMbPoll()【worldsing 笔记】

eMbPoll()的作用是FreeMod协议通信过程中不断查询事件对列有无完速数据桢,并进行地址和CRD验证,最后运行和回复主机。

为了减小代码尺寸对eMbPoll进行改进:

原版:

   1:  
   2: eMBErrorCode
   3: eMBPoll( void )
   4: {
   5:     static UCHAR   *ucMBFrame;
   6:     static UCHAR    ucRcvAddress;
   7:     static UCHAR    ucFunctionCode;
   8:     static USHORT   usLength;
   9:     static eMBException eException;
  10:  
  11:     int             i;
  12:     eMBErrorCode    eStatus = MB_ENOERR;
  13:     eMBEventType    eEvent;
  14:  
  15:     /* Check if the protocol stack is ready. */
  16:     if( eMBState != STATE_ENABLED )
  17:     {
  18:         return MB_EILLSTATE;
  19:     }
  20:  
  21:     /* Check if there is a event available. If not return control to caller.
  22:      * Otherwise we will handle the event. */
  23:     if( xMBPortEventGet( &eEvent ) == TRUE )
  24:     {
  25:         switch ( eEvent )
  26:         {
  27:         case EV_READY:
  28:             break;
  29:  
  30:         case EV_FRAME_RECEIVED:
  31:             eStatus = peMBFrameReceiveCur( &ucRcvAddress, &ucMBFrame, &usLength );
  32:             if( eStatus == MB_ENOERR )
  33:             {
  34:                 /* Check if the frame is for us. If not ignore the frame. */
  35:                 if( ( ucRcvAddress == ucMBAddress ) || ( ucRcvAddress == MB_ADDRESS_BROADCAST ) )
  36:                 {
  37:                     ( void )xMBPortEventPost( EV_EXECUTE );
  38:                 }
  39:             }
  40:             break;
  41:  
  42:         case EV_EXECUTE:
  43:             ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF];
  44:             eException = MB_EX_ILLEGAL_FUNCTION;
  45:             for( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ )
  46:             {
  47:                 /* No more function handlers registered. Abort. */
  48:                 if( xFuncHandlers[i].ucFunctionCode == 0 )
  49:                 {
  50:                     break;
  51:                 }
  52:                 else if( xFuncHandlers[i].ucFunctionCode == ucFunctionCode )
  53:                 {
  54:                     eException = xFuncHandlers[i].pxHandler( ucMBFrame, &usLength );
  55:                     break;
  56:                 }
  57:             }
  58:  
  59:             /* If the request was not sent to the broadcast address we
  60:              * return a reply. */
  61:             if( ucRcvAddress != MB_ADDRESS_BROADCAST )
  62:             {
  63:                 if( eException != MB_EX_NONE )
  64:                 {
  65:                     /* An exception occured. Build an error frame. */
  66:                     usLength = 0;
  67:                     ucMBFrame[usLength++] = ( UCHAR )( ucFunctionCode | MB_FUNC_ERROR );
  68:                     ucMBFrame[usLength++] = eException;
  69:                 }
  70:                 if( ( eMBCurrentMode == MB_ASCII ) && MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS )
  71:                 {
  72:                     vMBPortTimersDelay( MB_ASCII_TIMEOUT_WAIT_BEFORE_SEND_MS );
  73:                 }                
  74:                 eStatus = peMBFrameSendCur( ucMBAddress, ucMBFrame, usLength );
  75:             }
  76:             break;
  77:  
  78:         case EV_FRAME_SENT:
  79:             break;
  80:         }
  81:     }
  82:     return MB_ENOERR;
  83: }

 

改进后的eMbPoll():

   1:  
   2: void eMBPoll( void ){
   3:   
   4:   static UCHAR   *ucMBFrame;
   5:   static UCHAR    ucFunctionCode;
   6:   static USHORT   usLength;
   7:   static eMBException eException;
   8:   eMBEventType    eEvent;
   9:   UCHAR i;
  10:   USHORT usCRC16;
  11:   if(xMBPortEventGet( &eEvent) == TRUE ){                             //桢事件判断
  12:     if(eEvent == EV_FRAME_RECEIVED){    
  13:       if(usRcvBufferPos < MB_SER_PDU_SIZE_MIN)                        //最小桢判断
  14:         return;
  15:       if(usMBCRC16((UCHAR *)ucRTUBuf, usRcvBufferPos ) != 0)          //CRC判断
  16:         return;
  17:       if(IS_VALID_ADD){                                               //地址    
  18:         ucMBFrame = (UCHAR *) &ucRTUBuf[MB_SER_PDU_PDU_OFF];    
  19:         usLength = (USHORT)( usRcvBufferPos - MB_SER_PDU_PDU_OFF - MB_SER_PDU_SIZE_CRC);
  20:         ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF];
  21:         eException = MB_EX_ILLEGAL_FUNCTION;
  22:         for(i = 0; i < MB_FUNC_HANDLERS_MAX; i++ ){                  //执行功能码
  23:           if( xFuncHandlers[i].ucFunctionCode == 0 ){
  24:             return;
  25:           }
  26:           else if( xFuncHandlers[i].ucFunctionCode == ucFunctionCode ){
  27:             eException = xFuncHandlers[i].pxHandler( ucMBFrame, &usLength );
  28:             break;                               
  29:           }
  30:       }
  31:       if(IS_NOT_BROADCAST){                                        //回复主机
  32:         if( eException != MB_EX_NONE ){                            //错误码         
  33:           usLength = 0;
  34:           ucMBFrame[usLength++] = ( UCHAR )( ucFunctionCode | MB_FUNC_ERROR );
  35:           ucMBFrame[usLength++] = eException;
  36:         } 
  37:         if(eRcvState == STATE_RX_IDLE){                            //发送
  38:           pucSndBufferCur = ( UCHAR * ) ucMBFrame - 1;
  39:           pucSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucMBAddress;
  40:           usSndBufferCount = usLength + 1;      
  41:           usCRC16 = usMBCRC16( ( UCHAR * ) pucSndBufferCur, usSndBufferCount );
  42:           ucRTUBuf[usSndBufferCount++] = ( UCHAR )( usCRC16 & 0xFF );
  43:           ucRTUBuf[usSndBufferCount++] = ( UCHAR )( usCRC16 >> 8 );    
  44:           eSndState = STATE_TX_XMIT;
  45:           vMBPortSerialEnable( FALSE, TRUE );
  46:           }//发送结束
  47:         }//回复结束
  48:       }//地址判断
  49:     }//桢事件判断
  50:   }
  51: }

 

改进说明:

1、eMbPoll()调用一次即可运行功能码和回复主机;

2、省去独立的接收函数peMBFrameReceiveCur( &ucRcvAddress, &ucMBFrame, &usLength ); 而直接操作,(其实里面对算出数据桢的启始位置、和长度);

3、省去发送函数peMBFrameSendCur( ucMBAddress, ucMBFrame, usLength ); 而直接操作;

4、省去返回值,因为调用处没有使用;

5、对功能的遍历i改成unsigned char类型,省去ucRcvAddress和eMBErrorCode    eStatus = MB_ENOERR; 变量,

6、功能兼容原版本。

 

eMbPoll的经典之处在于功能的运行,——》函数指针,这部分在其它笔记中记录。

转载于:https://www.cnblogs.com/worldsing/p/worldsing_FreeModbus_10.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Freemodbus Slave是一种开源的MODBUS通信协议从站实现,用于在工业自动化系统中实现与主站的通信。下面是关于Freemodbus Slave学习的一些建议。 首先,要了解MODBUS通信协议的基础知识。MODBUS是一种常用的用于工业领域的通信协议,它定义了从站和主站之间的通信规则和数据格式。学习MODBUS的基础知识可以帮助理解Freemodbus Slave的实现原理。 其次,阅读Freemodbus Slave的文档和用户手册。官方提供了详细的文档和用户手册,其中包含了安装、配置以及使用Freemodbus Slave的详细说明。仔细阅读这些文档可以帮助理解Freemodbus Slave的各个功能和参数设置。 然后,实践操作和编程。使用开发板或者模拟器,将Freemodbus Slave添加到自己的工程中进行实验和测试。通过实践操作和编程,可以更好地理解Freemodbus Slave的使用方法和功能。 此外,参考社区和论坛的资源。Freemodbus有一个积极的开发者社区,这里有很多经验丰富的开发者和用户分享他们的经验和解决方案。在这些社区和论坛中进行交流和讨论,可以获得更多关于Freemodbus Slave的学习资源和帮助。 最后,不断练习和提升。通过不断实践和使用Freemodbus Slave,深入了解其各种功能和使用场景。并且保持学习的态度,关注最新的更新和发布,不断提高自己的技能和知识。 总结来说,学习Freemodbus Slave需要掌握MODBUS通信协议的基础知识,阅读官方文档和用户手册,进行实践操作和编程,参考社区和论坛的资源,持续练习和提升。通过这些步骤,可以逐渐掌握Freemodbus Slave的使用方法和技巧。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值