eMbPoll()的作用是FreeMod协议通信过程中不断查询事件对列有无完速数据桢,并进行地址和CRD验证,最后运行和回复主机。
为了减小代码尺寸对eMbPoll进行改进:
原版:
1:
2: eMBErrorCode
void )
4: {
static UCHAR *ucMBFrame;
static UCHAR ucRcvAddress;
static UCHAR ucFunctionCode;
static USHORT usLength;
static eMBException eException;
10:
int i;
12: eMBErrorCode eStatus = MB_ENOERR;
13: eMBEventType eEvent;
14:
/* Check if the protocol stack is ready. */
if( eMBState != STATE_ENABLED )
17: {
return MB_EILLSTATE;
19: }
20:
/* Check if there is a event available. If not return control to caller.
* Otherwise we will handle the event. */
TRUE )
24: {
switch ( eEvent )
26: {
case EV_READY:
break;
29:
case EV_FRAME_RECEIVED:
31: eStatus = peMBFrameReceiveCur( &ucRcvAddress, &ucMBFrame, &usLength );
if( eStatus == MB_ENOERR )
33: {
/* Check if the frame is for us. If not ignore the frame. */
if( ( ucRcvAddress == ucMBAddress ) || ( ucRcvAddress == MB_ADDRESS_BROADCAST ) )
36: {
void )xMBPortEventPost( EV_EXECUTE );
38: }
39: }
break;
41:
case EV_EXECUTE:
43: ucFunctionCode = ucMBFrame[MB_PDU_FUNC_OFF];
44: eException = MB_EX_ILLEGAL_FUNCTION;
for( i = 0; i < MB_FUNC_HANDLERS_MAX; i++ )
46: {
/* No more function handlers registered. Abort. */
if( xFuncHandlers[i].ucFunctionCode == 0 )
49: {
break;
51: }
if( xFuncHandlers[i].ucFunctionCode == ucFunctionCode )
53: {
54: eException = xFuncHandlers[i].pxHandler( ucMBFrame, &usLength );
break;
56: }
57: }
58:
/* If the request was not sent to the broadcast address we
* return a reply. */
if( ucRcvAddress != MB_ADDRESS_BROADCAST )
62: {
if( eException != MB_EX_NONE )
64: {
/* An exception occured. Build an error frame. */
66: usLength = 0;
67: ucMBFrame[usLength++] = ( UCHAR )( ucFunctionCode | MB_FUNC_ERROR );
68: ucMBFrame[usLength++] = eException;
69: }
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: }
break;
77:
case EV_FRAME_SENT:
break;
80: }
81: }
return MB_ENOERR;
83: }
改进后的eMbPoll():
1:
void ){
3:
static UCHAR *ucMBFrame;
static UCHAR ucFunctionCode;
static USHORT usLength;
static eMBException eException;
8: eMBEventType eEvent;
9: UCHAR i;
10: USHORT usCRC16;
//桢事件判断
if(eEvent == EV_FRAME_RECEIVED){
//最小桢判断
return;
//CRC判断
return;
//地址
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;
//执行功能码
if( xFuncHandlers[i].ucFunctionCode == 0 ){
return;
25: }
if( xFuncHandlers[i].ucFunctionCode == ucFunctionCode ){
27: eException = xFuncHandlers[i].pxHandler( ucMBFrame, &usLength );
break;
29: }
30: }
//回复主机
//错误码
33: usLength = 0;
34: ucMBFrame[usLength++] = ( UCHAR )( ucFunctionCode | MB_FUNC_ERROR );
35: ucMBFrame[usLength++] = eException;
36: }
//发送
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;
TRUE );
//发送结束
//回复结束
//地址判断
//桢事件判断
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的经典之处在于功能的运行,——》函数指针,这部分在其它笔记中记录。