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