tag 标签: ,状态机,串口

相关博文
  • 热度 3
    2013-12-23 17:46
    3332 次阅读|
    0 个评论
    UART函数:MT_UART.c void MT_UartProcessZToolData ( uint8 port, uint8 event ) 该函数是串口MT协议解析函数,解析接收到的串口数据,并确定是程序启动函数,还是简单的串口数据,然后发送数据到正确的地方(MT或APP)。Ti的协议栈中的MT的指令结构比较简单(一般还会在校验后面加帧尾,有的还会在数据里与帧头相同的数据后面加转义字符),如下图:帧头、数据、校验和。 (怎么传不了图片啊,只能这样了) | SOP |  MT CMD   |  FCS  | |    1    |      3-256     |     1     |  ,但是MT CMD里面有包含了不少没什么用的数据,内容就比较复杂了。不过他的整个处理还是非常好的。 开始先检测缓冲区内是否有数据,然后从DMA中将数据读出,虽然是一个一个数据读取的,可能有人觉得比较麻烦,但是仔细往下看就不会有这种感觉了。这样做的目的只是在接下来使用状态机的方式把数据解析出来,这样方便简单单,又能检测数据的正确性。下面对整个结构有详细的注解,大家交流交流啊!   原函数:(函数来源于:Z-Stack Lighting 1.0.1) /***************************************************************************************************  * @fn      MT_UartProcessZToolData  *  * @brief   | SOP | Data Length  |   CMD   |   Data   |  FCS  |  *         |  1  |     1      |    2     |  0-Len   |   1   |  *  *          Parses the data and determine either is SPI or just simply serial data  *          then send the data to correct place (MT or APP)  *            * @param   port     - UART port  *          event    - Event that causes the callback  *  *  * @return  None  ***************************************************************************************************/ void MT_UartProcessZToolData ( uint8 port, uint8 event ) {   uint8  ch;   uint8  bytesInRxBuffer;   (void)event;  // Intentionally unreferenced parameter   while (Hal_UART_RxBufLen(port))  //循环接收数据   {     HalUARTRead (port, ch, 1);         switch (state)   //串口接收状态机     {       case SOP_STATE:   //SOF位         if (ch == MT_UART_SOF)           state = LEN_STATE;  //确认后跳转状态         break;           case LEN_STATE:   //数据长度位         LEN_Token = ch;             tempDataLen = 0;             /* Allocate memory for the data *///建立一个存储空间         pMsg = (mtOSALSerialData_t *)osal_msg_allocate( sizeof ( mtOSALSerialData_t ) +                                                         MT_RPC_FRAME_HDR_SZ + LEN_Token );             if (pMsg)         {           /* Fill up what we can */           pMsg-hdr.event = CMD_SERIAL_MSG;           pMsg-msg = (uint8*)(pMsg+1);           pMsg-msg = LEN_Token;           state = CMD_STATE1;       //正确后跳转至CMD0         }         else         {           state = SOP_STATE;           return;         }         break;           case CMD_STATE1:    // CMD_STATE1         pMsg-msg = ch;         state = CMD_STATE2;       //跳转至CMD_STATE2         break;           case CMD_STATE2:    // CMD_STATE2         pMsg-msg = ch;         /* If there is no data, skip to FCS state */         if (LEN_Token)         {           state = DATA_STATE;//跳转至数据接收状态         }         else         {           state = FCS_STATE;  //没有数据跳转只校验和         }         break;           case DATA_STATE:  //接收数据             /* Fill in the buffer the first byte of the data */         pMsg-msg = ch;             /* Check number of bytes left in the Rx buffer */         bytesInRxBuffer = Hal_UART_RxBufLen(port);             /* If the remain of the data is there, read them all, otherwise, just read enough */         if (bytesInRxBuffer = LEN_Token - tempDataLen)         {           HalUARTRead (port, pMsg-msg , bytesInRxBuffer);           tempDataLen += bytesInRxBuffer;         }         else         {           HalUARTRead (port, pMsg-msg , LEN_Token - tempDataLen);           tempDataLen += (LEN_Token - tempDataLen);         }             /* If number of bytes read is equal to data length, time to move on to FCS */         if ( tempDataLen == LEN_Token )  //数据位接收完成,跳转校验             state = FCS_STATE;   //数据接收完成跳转至数据校验             break;           case FCS_STATE:   //校验和--按位异或             FSC_Token = ch;             /* Make sure it's correct */   //如果信息接受正确         if ((MT_UartCalcFCS ((uint8*)pMsg-msg , MT_RPC_FRAME_HDR_SZ + LEN_Token) == FSC_Token))         {           osal_msg_send( App_TaskID, (byte *)pMsg );         }         else         {           /* deallocate the msg */           osal_msg_deallocate ( (uint8 *)pMsg );         }             /* Reset the state, send or discard the buffers at this point */         state = SOP_STATE;  //重新回到初始状态,检测帧头             break;           default:        break;     } #if TEST  //自己加的,接收到的数据在发送回串口助手     //For test UART     HalUARTWrite(HAL_UART_PORT_0,(uint8*)pMsg-msg ,MT_RPC_FRAME_HDR_SZ + LEN_Token); #endif   //end TEST   } } 注: 1.状态机:是通信里经常会有到的一种协议解析方式。 2.这个只是UART接收时的数据处理相当于底层的解析,还有更多指令解析在  zllInitiator_event_loop ( uint8 task_id, uint16 events )和zllSampleRemote_event_loop ( uint8 task_id, uint16 events ) 这两个函数中还有解析,改天继续写!