我是靠谱客的博主 靓丽蜡烛,最近开发中收集的这篇文章主要介绍CC2530之串口接收回调函数MT_UartProcessZToolData(),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

需要测试代码的可以留下邮箱,或者关注微信公众号 小白技术栈 后台回复【cc2530串口回调函数】获取。

CC2530使用MT层实现串口读操作,在MT_UART.c文件定义回调函数:

#if defined (ZTOOL_P1) || defined (ZTOOL_P2)
  uartConfig.callBackFunc         = MT_UartProcessZToolData;

在串口接收回调函数MT_UartProcessZToolData()中,Zstack采用状态机接收的方式对串口接收数据进行处理,看似比较复杂,但其实这样接收数据还能校验数据的准确性,而且还有osal_msg_send( App_TaskID, (byte *)pMsg )发送机制,处理数据比较方便。

其接收数据格式为 0xFE + 数据长度(仅是data的长度)+ 命令字段 + data[] + 校验和

代码注释如下:

/***************************************************************************************************
 * @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:    //初始状态state = 0,判断帧头是否为SOP_STATE(0xFE)
        if (ch == MT_UART_SOF)
          state = LEN_STATE;    //若帧头正确,状态机状态改为LEN_STATE
        break;

      case LEN_STATE:    //接收第二字节时,进入LEN_STATE
        LEN_Token = ch;    //将第二字节(传输数据data[]的长度)赋值给LEN_Token

        tempDataLen = 0;    //初始化临时数据计数器tempDataLen为零

        /* Allocate memory for the data */
        pMsg = (mtOSALSerialData_t *)osal_msg_allocate( sizeof ( mtOSALSerialData_t ) +
                                                        MT_RPC_FRAME_HDR_SZ + LEN_Token );    //分配存放消息的空间,由3字节(1字节数据长度位+2字节CMD字段)+ data[]长度

        if (pMsg)    //若有消息接收
        {
          /* Fill up what we can */
          pMsg->hdr.event = CMD_SERIAL_MSG;    //事件ID,供应用层查询使用
          pMsg->msg = (uint8*)(pMsg+1);    //加1的目的是为了分配存放数据末尾的1字节校验和
          pMsg->msg[MT_RPC_POS_LEN] = LEN_Token;    //将数据长度存放到msg[0]
          state = CMD_STATE1;    //修改状态机状态为CMD_STATE1
        }
        else    //无消息则回到状态机起始状态
        {
          state = SOP_STATE;
          return;
        }
        break;

      case CMD_STATE1:    
        pMsg->msg[MT_RPC_POS_CMD0] = ch;    //第三字节为命令字段一
        state = CMD_STATE2;
        break;

      case CMD_STATE2:
        pMsg->msg[MT_RPC_POS_CMD1] = ch;    //第四字节为命令字段二
        /* If there is no data, skip to FCS state */
        if (LEN_Token)    //如果有数据接收,则状态机改为DATA_STATE
        {
          state = DATA_STATE;
        }
        else    //如果无数据接收,则状态机改为FCS_STATE校验模式
        {
          state = FCS_STATE;
        }
        break;

      case DATA_STATE:

        /* Fill in the buffer the first byte of the data */
        pMsg->msg[MT_RPC_FRAME_HDR_SZ + tempDataLen++] = ch;    //开始存放data[]

        /* 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)    //如果缓冲区剩余字节数不大于分配                        的空间,则将剩余字节全部存放到msg
        {
          HalUARTRead (port, &pMsg->msg[MT_RPC_FRAME_HDR_SZ + tempDataLen], bytesInRxBuffer);
          tempDataLen += bytesInRxBuffer;
        }
        else    //根据剩余空间大小存放数据
        {
          HalUARTRead (port, &pMsg->msg[MT_RPC_FRAME_HDR_SZ + tempDataLen], 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;    //将最后一个字节(校验和)赋值给FSC_Token
        

        /* Make sure it's correct */
        if ((MT_UartCalcFCS ((uint8*)&pMsg->msg[0], 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;
    }
  }
}

然后在SampleApp.c文件uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )函数状态机中添加如下:

mtOSALSerialData_t *UartMsg;
.
.
.

case CMD_SERIAL_MSG:
                    UartMsg = (mtOSALSerialData_t *)MSGpkt;
                    
                    memcpy(uartRecvBuf, UartMsg->msg, UartMsg->msg[0] + 3);
                    SampleApp_Send_P2P_Message();
                    memset(uartRecvBuf, 0, UartMsg->msg[0] + 3); 

将串口接收到的消息发送到协调器,通过协调器打印出来。

cc2530串口接收数据由stm32发送测试,其测试代码为:

uint8_t MT_UartCalcFCS( uint8_t *msg_ptr, uint8_t len )
{
  uint8_t x;
  uint8_t xorResult;

  xorResult = 0;

  for ( x = 0; x < len; x++, msg_ptr++ )
    xorResult = xorResult ^ *msg_ptr;

  return ( xorResult );
}

/*********************************************************************
 * @fn      led_entry
 *
 * @brief   Led run.
 *
 * @param   parameter - none
 *
 * @return  none
 */
void led_entry(void *parameter)
{
    uint8_t led_state = LED_ON;
		uint8_t test_buf[13] = {0xFE, 0x08, 0x03, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x00};
		test_buf[11] = 0xff;
		
    while(1)
    {
        LED(led_state);
        led_state = ~led_state;
				test_buf[12] = MT_UartCalcFCS((uint8_t*)&test_buf[1], 11);
        HAL_UART_Transmit(&huart1, test_buf, 13, 0xFF);
				test_buf[4]++;
        rt_thread_mdelay(1000);
    }
}

 

最后

以上就是靓丽蜡烛为你收集整理的CC2530之串口接收回调函数MT_UartProcessZToolData()的全部内容,希望文章能够帮你解决CC2530之串口接收回调函数MT_UartProcessZToolData()所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(48)

评论列表共有 0 条评论

立即
投稿
返回
顶部