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的经典之处在于功能的运行,——》函数指针,这部分在其它笔记中记录。
FreeModbus Slave 改进的eMbPoll()【worldsing 笔记】的更多相关文章
- FreeModbus Slave For AVR源代码 精简版2 【worldsing 笔记】
FreeModbus 源码:点击下载 线圈BUG解决(后来发现不一定是BUG) 1.eMBException eMBFuncWriteCoil( UCHAR * pucFrame, USHORT * ...
- FreeModbus Slave RTU 精简版源代码【worldsing 笔记】
RTU精简版本 测试环境:IAR for avr 5.40 + M128 目前只优化了ModBusPort.c和ModBusRTU.c ModBusPort.c 566 bytes of CO ...
- emWin(ucGui)数值显示例程 -【worldsing笔记】
本例程下载:2.emWin5.26(ucGui)VS2008数字显示.zip 在emWin显示文本字符还是容易,我们也可以使用字符串和标准 C 库的函数来显示数值.然而,有时候这会是件困难的事.通 ...
- WS103C8例程——串口2【worldsing笔记】
在超MINI核心板 stm32F103C8最小系统板上调试Usart2功能:用Jlink 6Pin接口连接WStm32f103c8的Uart2,PC机向mcu发送数据,mcu收到数据后数据加1,回传给 ...
- Keil Mdk5.0 破解包 和谐包【worldsing笔记】
有关Keil MDK 5.0的介绍和下载 http://www.cnblogs.com/worldsing/p/3355911.html 下载地址 点击下载:http://pan.baidu.com/ ...
- Modbus Poll master-slave测试 Dtech USB转485(worldsing 笔记)
1,简介 网站地址:http://www.modbustools.com/ 该网站提供了几个软件工具,可以运行于windows 2000/XP/Vista/7环境下,用来测试和仿真Modebus设备. ...
- QTbaWidget控件几个例程 【worldsing笔记】
Qt Creator自带的 QTabWidget控件几个例程 在Qt Windos版本安装后,在Example目录可以找到与QTabWidget相关的工程Demo,如果按默认安装的话他们分别是: ...
- emWin5.24 VS2008模拟LCD12864 stm32 RTX移植 【worldsing笔记】
emWin for 12864 并口移植 源代码下载:RTX_emWin5.24_Keil_VS2008-20141122.zip 硬件环境: CPU: stm32f103ve LCD:st7 ...
- VS2008 工程中部分文件不参与编译 从生成中排除【Worldsing笔记】
Visual Studio 2008 .VS2008.VC2008工程源文件配置.编译配置 有时编写代码时,往往存在这样的需求(或是希望有这样的功能):一个工程经过不共同的配置实现不同的版本或是功 ...
随机推荐
- 选择Android还是选择JavaEE?
很多同学咨询过同样的一个问题,该问题也是最备受争议的问题,那就是到底是选择Android还是选择JavaEE.下面发表一些本人的看法. Android属于一个特有的Java技术应用,专注于 ...
- SGU 130
SGU130,用k条弦将一个圆分成k+1份的方法数. #include <iostream> #include <vector> #include <string> ...
- Android 通过 Intent 传递类对象
Android中Intent传递类对象提供了两种方式一种是 通过实现Serializable接口传递对象,一种是通过实现Parcelable接口传递对象. 要求被传递的对象必须实现上述2种接口中的一种 ...
- 怎样开发Chrome浏览器的插件
http://jingyan.baidu.com/article/b907e627fb90fd46e7891c3c.html Chrome 浏览器作为基于Webkit的新一代浏览器.Chrome自从正 ...
- caffe简易上手指南(一)—— 运行cifar例子
简介 caffe是一个友好.易于上手的开源深度学习平台,主要用于图像的相关处理,可以支持CNN等多种深度学习网络. 基于caffe,开发者可以方便快速地开发简单的学习网络,用于分类.定位等任务,也可以 ...
- JNDI和在tomcat中配置DBCP连接池 元数据的使用 DBUtils框架的使用 多表操作
1 JNDI和在tomcat中配置DBCP连接池 JNDI(Java Naming and Directory Interface),Java命名和目录接口,它对应于J2SE中的javax.namin ...
- VPN DNS leak 问题的解决
前一段时间遇到一个问题.customer说发现连接VPN后在PPP端发现security leak,整个转了好大一个圈子才把问题解决了.之所以费这么大周折,倒不是因为很难解决,只是费了很大劲儿才定位了 ...
- Miles per gallon to kilometers per liter
Miles per gallon to kilometers per liter 1 Imperial Gallon = 4.54609188 litres 1 Mile = 1.609344 kil ...
- 代理服务器squid
http://www.baidu.com/s?wd=squid%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8&f=12&rsp=0& ...
- tar 命令打包,除了某个目录剩下的都打包
tar czvf beifen.tar.gz ./webdata --exclude webdata/uploadfiles