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

FreeModbus Slave 改进的eMbPoll()【worldsing 笔记】的更多相关文章

  1. FreeModbus Slave For AVR源代码 精简版2 【worldsing 笔记】

    FreeModbus 源码:点击下载 线圈BUG解决(后来发现不一定是BUG) 1.eMBException eMBFuncWriteCoil( UCHAR * pucFrame, USHORT * ...

  2. FreeModbus Slave RTU 精简版源代码【worldsing 笔记】

    RTU精简版本 测试环境:IAR for avr 5.40 + M128 目前只优化了ModBusPort.c和ModBusRTU.c ModBusPort.c     566 bytes of CO ...

  3. emWin(ucGui)数值显示例程 -【worldsing笔记】

    本例程下载:2.emWin5.26(ucGui)VS2008数字显示.zip   在emWin显示文本字符还是容易,我们也可以使用字符串和标准 C 库的函数来显示数值.然而,有时候这会是件困难的事.通 ...

  4. WS103C8例程——串口2【worldsing笔记】

    在超MINI核心板 stm32F103C8最小系统板上调试Usart2功能:用Jlink 6Pin接口连接WStm32f103c8的Uart2,PC机向mcu发送数据,mcu收到数据后数据加1,回传给 ...

  5. Keil Mdk5.0 破解包 和谐包【worldsing笔记】

    有关Keil MDK 5.0的介绍和下载 http://www.cnblogs.com/worldsing/p/3355911.html 下载地址 点击下载:http://pan.baidu.com/ ...

  6. Modbus Poll master-slave测试 Dtech USB转485(worldsing 笔记)

    1,简介 网站地址:http://www.modbustools.com/ 该网站提供了几个软件工具,可以运行于windows 2000/XP/Vista/7环境下,用来测试和仿真Modebus设备. ...

  7. QTbaWidget控件几个例程 【worldsing笔记】

    Qt Creator自带的 QTabWidget控件几个例程 在Qt Windos版本安装后,在Example目录可以找到与QTabWidget相关的工程Demo,如果按默认安装的话他们分别是:   ...

  8. emWin5.24 VS2008模拟LCD12864 stm32 RTX移植 【worldsing笔记】

      emWin for 12864 并口移植 源代码下载:RTX_emWin5.24_Keil_VS2008-20141122.zip   硬件环境: CPU: stm32f103ve LCD:st7 ...

  9. VS2008 工程中部分文件不参与编译 从生成中排除【Worldsing笔记】

    Visual Studio 2008 .VS2008.VC2008工程源文件配置.编译配置   有时编写代码时,往往存在这样的需求(或是希望有这样的功能):一个工程经过不共同的配置实现不同的版本或是功 ...

随机推荐

  1. Oracle 学习笔记 常用查询命令篇

    1.查询某个用户下有多少张表 有时候很有用  select count(*) from dba_tables t where t.owner='SCOTT';

  2. 关于hadoop的环境变量

    export PATH export JAVA_HOME=/opt/jdk1.7 export PATH=$PATH:$JAVA_HOME/bin 为什么/etc/profile 添加了环境变量had ...

  3. android开发无障碍app

    最近做一些为盲人提供服务的APP,还是挺有感触的,感谢手机和互联网的普及,他们的生活比以前丰富了很多. 通过读屏软件,盲人可以操作手机,上网浏览信息.读屏软件的工作原理很简单,就是读出屏幕上按钮.文本 ...

  4. OM Price Lists

      --select * --from org_organization_definitions; --execute fnd_client_info.set_org_context(111); -- ...

  5. POJ2892Tunnel Warfare (线段树)

    http://poj.org/problem?id=2892 记录每个区间端点的左连续及右连续 都是单点更新 用不着向下更新 还简单点 找错找了N久 最后发现将s[w<<1|1]写成s[w ...

  6. poj 2418 Hardwood Species (map)

    题目:http://poj.org/problem?id=2418 在poj 上交题总是有各种错误,再次感叹各个编译器. c++ AC代码,G++为超时,上代码: #include<cstdio ...

  7. Microsoft强大团队(源代码)管理工具--TFS2010 与vs结合

    今天看了与vs 集成原理工具 TFS 2010, 角色分配.项目管理.开发源代码管理.任务分配管理.测试文档管理及跟踪等管理流程.代码版本的分支与合并等等,功能好强大啊. 以下将其安装配置简要介绍(以 ...

  8. java高并发,如何解决,什么方式解决

    之前我将高并发的解决方法误认为是线程或者是队列可以解决,因为高并发的时候是有很多用户在访问,导致出现系统数据不正确.丢失数据现象,所以想到 的是用队列解决,其实队列解决的方式也可以处理,比如我们在竞拍 ...

  9. 【转】Android - Button(按钮)的响应点击事件的4种写法

    原文网址:http://www.yrom.net/blog/2011/12/12/android-4-onclicklistener-of-button/ Button控件setOnclickList ...

  10. NET下RabbitMQ实践[配置篇]

    这个系列目前计划写四篇,分别是配置,示例,WCF发布,实战.当然不排除加餐情况.  介绍: rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统.他遵循Mozilla Publi ...