• 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的经典之处在于功能的运行,——》函数指针,这部分在其它笔记中记录。

  • 相关阅读:
    Gym
    数学公式头文件
    除法取模(比赛常用)
    ACM-ICPC 2017 Asia Urumqi A. Coins【期望dp】
    P1494 小Z的袜子 【普通莫队】
    Codeforces Round #642 (Div. 3) E—K-periodic Garland dp
    luogu P4568 [JLOI2011]飞行路线 最短路Dijkstra+dp
    luogu P2015 二叉苹果树 树形dp
    luogu P1462 通往奥格瑞玛的道路 二分+spfa
    luogu P1879 [USACO06NOV]Corn Fields G 状态压缩dp
  • 原文地址:https://www.cnblogs.com/worldsing/p/worldsing_FreeModbus_10.html
Copyright © 2020-2023  润新知