关于在CC2430中基于ZIGBEE2006的串口通信

     就跟我自己承诺的一样,我会发一篇关于zigbee串口通信的。
 虽然这个是我五月份就做的东西,但是现在看来,还是有那么一群人对这个纠缠不清。但是,这个其实很简单。
 事实上zigbee协议栈2006是有自己集成好了串口函数的, 就在MT层的SPIMgr.c文件里面。这里是一部分的源码:
 
/***************************************************************************************************
 *                                          LOCAL FUNCTIONS
 ***************************************************************************************************/

/***************************************************************************************************
 * @fn      SPIMgr_Init
 *
 * @brief
 *
 * @param   None
 *
 * @return  None
***************************************************************************************************/
void SPIMgr_Init ()
{
  halUARTCfg_t uartConfig;

  /* Initialize APP ID */
  App_TaskID = 0;

  /* UART Configuration */
  uartConfig.configured           = TRUE;
  uartConfig.baudRate             = SPI_MGR_DEFAULT_BAUDRATE;
  uartConfig.flowControl          = SPI_MGR_DEFAULT_OVERFLOW;
  uartConfig.flowControlThreshold = SPI_MGR_DEFAULT_THRESHOLD;
  uartConfig.rx.maxBufSize        = SPI_MGR_DEFAULT_MAX_RX_BUFF;
  uartConfig.tx.maxBufSize        = SPI_MGR_DEFAULT_MAX_TX_BUFF;
  uartConfig.idleTimeout          = SPI_MGR_DEFAULT_IDLE_TIMEOUT;
  uartConfig.intEnable            = TRUE;
#if defined (ZTOOL_P1) || defined (ZTOOL_P2)
  uartConfig.callBackFunc         = SPIMgr_ProcessZToolData;
#elif defined (ZAPP_P1) || defined (ZAPP_P2)
  uartConfig.callBackFunc         = SPIMgr_ProcessZAppData;
#else
  uartConfig.callBackFunc         = NULL;
#endif

  /* Start UART */
#if defined (SPI_MGR_DEFAULT_PORT)

  HalUARTOpen (SPI_MGR_DEFAULT_PORT, &uartConfig);
#else
  /* Silence IAR compiler warning */
  (void)uartConfig;
#endif

  /* Initialize for ZApp */
#if defined (ZAPP_P1) || defined (ZAPP_P2)
  /* Default max bytes that ZAPP can take */
  SPIMgr_MaxZAppBufLen  = 1;
  SPIMgr_ZAppRxStatus   = SPI_MGR_ZAPP_RX_READY;
#endif


}

/***************************************************************************************************
 * @fn      MT_SerialRegisterTaskID
 *
 * @brief
 *
 *   This function registers the taskID of the application so it knows
 *   where to send the messages whent they come in.
 *
 * @param   void
 *
 * @return  void
 ***************************************************************************************************/
void SPIMgr_RegisterTaskID( byte taskID )
{
  App_TaskID = taskID;
}

/***************************************************************************************************
 * @fn      SPIMgr_CalcFCS
 *
 * @brief
 *
 *   Calculate the FCS of a message buffer by XOR'ing each byte.
 *   Remember to NOT include SOP and FCS fields, so start at the CMD
 *   field.
 *
 * @param   byte *msg_ptr - message pointer
 * @param   byte len - length (in bytes) of message
 *
 * @return  result byte
 ***************************************************************************************************/
byte SPIMgr_CalcFCS( uint8 *msg_ptr, uint8 len )
{
  byte x;
  byte xorResult;

  xorResult = 0;

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

  return ( xorResult );
}


#if defined (ZTOOL_P1) || defined (ZTOOL_P2)
/***************************************************************************************************
 * @fn      SPIMgr_ProcessZToolRxData
 *
 * @brief   | SOP | CMD  |   Data Length   | FSC  |
 *          |  1  |  2   |       1         |  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   pBuffer  - pointer to the buffer that contains the data
 *          length   - length of the buffer
 *
 *
 * @return  None
 ***************************************************************************************************/
void SPIMgr_ProcessZToolData ( uint8 port, uint8 event )
{
  uint8  ch;

  /* Verify events */
  if (event == HAL_UART_TX_FULL)
  {
    // Do something when TX if full
    return;
  }

  if (event & (HAL_UART_RX_FULL | HAL_UART_RX_ABOUT_FULL | HAL_UART_RX_TIMEOUT))
  {
    while (Hal_UART_RxBufLen(SPI_MGR_DEFAULT_PORT))
    {
      HalUARTRead (SPI_MGR_DEFAULT_PORT, &ch, 1);

      switch (state)
      {
        case SOP_STATE:
          if (ch == SOP_VALUE)
            state = CMD_STATE1;
          break;

        case CMD_STATE1:
          CMD_Token[0] = ch;
          state = CMD_STATE2;
          break;

        case CMD_STATE2:
          CMD_Token[1] = ch;
          state = LEN_STATE;
          break;

        case LEN_STATE:
          LEN_Token = ch;
          if (ch == 0)
            state = FCS_STATE;
          else
            state = DATA_STATE;

          tempDataLen = 0;

          /* Allocate memory for the data */
          SPI_Msg = (mtOSALSerialData_t *)osal_msg_allocate( sizeof ( mtOSALSerialData_t ) + 2+1+LEN_Token );

          if (SPI_Msg)
          {
            /* Fill up what we can */
            SPI_Msg->hdr.event = CMD_SERIAL_MSG;
            SPI_Msg->msg = (uint8*)(SPI_Msg+1);
            SPI_Msg->msg[0] = CMD_Token[0];
            SPI_Msg->msg[1] = CMD_Token[1];
            SPI_Msg->msg[2] = LEN_Token;
          }
          else
          {
            state = SOP_STATE;
            return;
          }

          break;

        case DATA_STATE:
            SPI_Msg->msg[3 + tempDataLen++] = ch;
            if ( tempDataLen == LEN_Token )
              state = FCS_STATE;
          break;

        case FCS_STATE:

          FSC_Token = ch;

          /* Make sure it's correct */
          if ((SPIMgr_CalcFCS ((uint8*)&SPI_Msg->msg[0], 2 + 1 + LEN_Token) == FSC_Token))
          {
            osal_msg_send( MT_TaskID, (byte *)SPI_Msg );
          }
          else
          {
            /* deallocate the msg */
            osal_msg_deallocate ( (uint8 *)SPI_Msg);
          }

          /* Reset the state, send or discard the buffers at this point */
          state = SOP_STATE;

          break;

        default:
         break;
      }


    }
  }
}
#endif //ZTOOL

#if defined (ZAPP_P1) || defined (ZAPP_P2)
/***************************************************************************************************
 * @fn      SPIMgr_ProcessZAppRxData
 *
 * @brief   | SOP | CMD  |   Data Length   | FSC  |
 *          |  1  |  2   |       1         |  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   pBuffer  - pointer to the buffer that contains the data
 *          length   - length of the buffer
 *
 *
 * @return  None
 ***************************************************************************************************/
void SPIMgr_ProcessZAppData ( uint8 port, uint8 event )
{

  osal_event_hdr_t  *msg_ptr;
  uint16 length = 0;
  uint16 rxBufLen  = Hal_UART_RxBufLen(SPI_MGR_DEFAULT_PORT);

  /*
     If maxZAppBufferLength is 0 or larger than current length
     the entire length of the current buffer is returned.
  */
  if ((SPIMgr_MaxZAppBufLen != 0) && (SPIMgr_MaxZAppBufLen <= rxBufLen))
  {
    length = SPIMgr_MaxZAppBufLen;
  }
  else
  {
    length = rxBufLen;
  }

  /* Verify events */
  if (event == HAL_UART_TX_FULL)
  {
    // Do something when TX if full
    return;
  }

  if (event & ( HAL_UART_RX_FULL | HAL_UART_RX_ABOUT_FULL | HAL_UART_RX_TIMEOUT))
  {
    if ( App_TaskID )
    {
      /*
         If Application is ready to receive and there is something
         in the Rx buffer then send it up
      */
      if ((SPIMgr_ZAppRxStatus == SPI_MGR_ZAPP_RX_READY ) && (length != 0))
      {
        /* Disable App flow control until it processes the current data */
         SPIMgr_AppFlowControl ( SPI_MGR_ZAPP_RX_NOT_READY );

        /* 2 more bytes are added, 1 for CMD type, other for length */
        msg_ptr = (osal_event_hdr_t *)osal_msg_allocate( length + sizeof(osal_event_hdr_t) );
        if ( msg_ptr )
        {
          msg_ptr->event = SPI_INCOMING_ZAPP_DATA;
          msg_ptr->status = length;

          /* Read the data of Rx buffer */
          HalUARTRead( SPI_MGR_DEFAULT_PORT, (uint8 *)(msg_ptr + 1), length );

          /* Send the raw data to application...or where ever */
          osal_msg_send( App_TaskID, (uint8 *)msg_ptr );
        }
      }
    }
  }
}

/***************************************************************************************************
 * @fn      SPIMgr_ZAppBufferLengthRegister
 *
 * @brief
 *
 * @param   maxLen - Max Length that the application wants at a time
 *
 * @return  None
 *
 ***************************************************************************************************/
void SPIMgr_ZAppBufferLengthRegister ( uint16 maxLen )
{
  /* If the maxLen is larger than the RX buff, something is not right */
  if (maxLen <= SPI_MGR_DEFAULT_MAX_RX_BUFF)
    SPIMgr_MaxZAppBufLen = maxLen;
  else
    SPIMgr_MaxZAppBufLen = 1; /* default is 1 byte */
}

/***************************************************************************************************
 * @fn      SPIMgr_AppFlowControl
 *
 * @brief
 *
 * @param   status - ready to send or not
 *
 * @return  None
 *
 ***************************************************************************************************/
void SPIMgr_AppFlowControl ( bool status )
{

  /* Make sure only update if needed */
  if (status != SPIMgr_ZAppRxStatus )
  {
    SPIMgr_ZAppRxStatus = status;
  }

  /* App is ready to read again, ProcessZAppData have to be triggered too */
  if (status == SPI_MGR_ZAPP_RX_READY)
  {
    SPIMgr_ProcessZAppData ( SPI_MGR_DEFAULT_PORT, HAL_UART_RX_TIMEOUT );
  }

}

#endif //ZAPP

 这些意思很明显,特别注意下有色彩背景的代码。这个其实就是C语言的宏定义。在zigbee协议栈,这个是用得很多的。当然,本人自己也很喜欢用这个方法定义,因为简单,而且直观,更重要的是很方便, 你可以随便定义你要的部分进行编译。
 呵呵,有点跑题了。接下来就解释下把,:
 /* UART Configuration */
  uartConfig.configured           = TRUE;
  uartConfig.baudRate             = SPI_MGR_DEFAULT_BAUDRATE;
  uartConfig.flowControl          = SPI_MGR_DEFAULT_OVERFLOW;
  uartConfig.flowControlThreshold = SPI_MGR_DEFAULT_THRESHOLD;
  uartConfig.rx.maxBufSize        = SPI_MGR_DEFAULT_MAX_RX_BUFF;
  uartConfig.tx.maxBufSize        = SPI_MGR_DEFAULT_MAX_TX_BUFF;
  uartConfig.idleTimeout          = SPI_MGR_DEFAULT_IDLE_TIMEOUT;
  uartConfig.intEnable            = TRUE;
#if defined (ZTOOL_P1) || defined (ZTOOL_P2)
  uartConfig.callBackFunc         = SPIMgr_ProcessZToolData;
#elif defined (ZAPP_P1) || defined (ZAPP_P2)
  uartConfig.callBackFunc         = SPIMgr_ProcessZAppData;
#else
  uartConfig.callBackFunc         = NULL;
#endif

这个就是串口的初始化部分,注意了, 上面 uartConfig.callBackFunc是一个函数指针,后面的就是这个串口的调用函数。协议栈默认编了两个固化的,这两个是用于与zibgee的上位机通信的, 有特定的协议,是由TI自己定的。
就是一位内TI定义了这个协议,使得如果我们自己编写的话就使用了。


这样。有一种办法,就是跟着它的协议,一下是我得到的TI的串口通信协议:

'***********************************************************************************************
'*                                   协议数据单元的相关说明                                    *
'***********************************************************************************************
'
'    ARMSKY-ZLocation无线定位开发系统使用TI公司的ZigBee协议栈Z-Stack v1.4.2。为了方便用户与使用
'Z-Stack v1.4.2的目标硬件进行数据交换,Z-Stack v1.4.2中定义了串口通信数据格式。
'
'    串口属性设置如下:
'
'        波 特 率:38400bps
'        数 据 位:8个
'        停 止 位:1个
'        奇偶校验:无
'
'    Z-Stack v1.4.2中串口通信数据格式如下:
'
'        ****************************************************
'        *   SOP   *   CMD   *   LEN   *   Data   *   FCS   *
'        ****************************************************
'
'        数据包由多个字段构成,每个字段由1个或多个字节构成。多字节字段的高位字节首先被发送。
'
'        SOP(包起始):该字段长度为1字节,值为0x02,表示数据包开始。
'        CMD(命令ID):该字段长度为2字节,表示数据包的作用。
'        LEN(长度)  :该字段长度为1字节,表示Data字段的长度。
'        Data(数据) :该字段包含要被传输的实际数据,该字段的长度由LEN字段指定。
'        FCS(帧校验序列):该字段长度为1字节,确保数据包的完整性。FCS字段值的计算方法是:
'                           从CMD字段开始到Data字段结束,逐个字节进行XOR运算,结果即为FCS字段值。
'                           接收方收到数据包后,从Data字段开始到FCS字段结束,逐个字节进行XOR运算,
'                           结果为0表示接收正确,否则表示错误。
'
'        Z-Stack v1.4.2中定义了很多串口通信数据包,此处只描述定位应用中所需使用的串口通信数据包。
'        其他串口通信数据包格式定义请参看Serial Port Interface_F8W-2003-0001_.pdf。
'
'
'    下面给出4个本定位应用中需要用到的串口通信命令数据包的格式定义:
'
'        SYS_PING:发送该命令给目标设备以检查设备的状态及能力。格式定义如下:
'
'                  *****************************
'                  *  CMD=0x0007  *  LEN=0x00  *
'                  *****************************
'
'        SYS_PING_RESPONSE:该命令是对SYS_PING命令的响应。格式定义如下:
'
'                  **********************************************
'                  *  CMD=0x1007  *  LEN=0x02  *  Capabilities  *
'                  **********************************************
'
'                  Capabilities:该字段长度为2字节。该字段值表示目标设备可以处理的接口。位掩码如下:
'
'                                MT_CAP_MAC 0x0001
'                                MT_CAP_NWK 0x0002
'                                MT_CAP_AF 0x0004
'                                MT_CAP_ZDO 0x0008
'                                MT_CAP_USER_TEST 0x0010
'                                MT_CAP_SEQ 0x0020
'                                MT_CAP_BOOTLOAD 0 x 8000
'
'        SYS_GET_DEVICE_INFO:发送该命令给目标设备以获得设备的信息。格式定义如下:
'
'                  *****************************
'                  *  CMD=0x0014  *  LEN=0x00  *
'                  *****************************
'
'        SYS_GET_DEVICE_INFO_RESPONSE:该命令是对SYS_GET_DEVICE_INFO命令的响应。格式定义如下:
'
'                  *******************************************************************************************************************************
'                  * CMD=0x1014 * LEN=0x03 * Status * IEEEAddress * ShortAddress * DeviceType * DeviceState * NumAssocDevices * AssocDevicesList *
'                  *******************************************************************************************************************************
'
'                  LEN=0x03  Serial Port Interface_F8W-2003-0001_.pdf中第16页中有定义,但存在疑问,不过不影响本应用。
'                  Status:该字段长度为1字节。0表示成功,1表示失败。如果IEEEAddress或/和ShortAddress不在有效范围内,则该字段值为1。
'                  IEEEAddress:该字段长度为8字节。
'                  ShortAddress:该字段长度为2字节。
'                  DeviceType:该字段长度为1字节,用来表示设备类型。位0到位2用来指示设备运行为协调器、路由器还是终端设备。
'                  DeviceState:该字段长度为1字节,用来表示设备状态。可能的设备状态请参看Serial Port Interface_F8W-2003-0001_.pdf中第16页中的定义。
'                  NumAssocDevices:该字段长度为1字节,表示关联到该目标设备的设备数量。
'                  AssocDevicesList:该字段长度可变,它是一个每个数据元素为16bit的数组。表示关联到该目标设备的设备的网络地址。


'***********************************************************************************************
'*                                Z-Stack定位规范中规定的报文格式                              *
'***********************************************************************************************
'
'    在Z-Stack定位规范中规定了如下9个报文:
'
'                                        XY-RSSI请求报文(簇ID:0x0011)
'                                        XY-RSSI响应报文(簇ID:0x0012)
'                                        盲节点查找请求报文(簇ID:0x0013)
'                                        盲节点查找响应报文(簇ID:0x0014)
'                                        参考节点配置报文(簇ID:0x0015)
'                                        盲节点配置报文(簇ID:0x0016)
'                                        参考节点配置请求报文(簇ID:0x0017)
'                                        盲节点配置请求报文(簇ID:0x0018)
'                                        RSSIBlast报文(簇ID:0x0019)
'
'
'    XY-RSSI请求报文(簇ID:0x0011)
'
'            发送该请求报文来触发一个XY-RSSI响应报文。在发送一系列RSSI Blast报文后该请求报文应被
'        立即发送以取回在“1跳”射频范围内的参考节点的坐标和与它们每一个的平均RSSI射频链接强度。
'        注意:如果该报文被发送大于“1跳”半径,那么RSSI射频链接强度将不可用,只有XY坐标可用。
'        该报文除了一个簇ID没有其他内容。
'
'    XY-RSSI响应报文(簇ID:0x0012)
'
'            该报文被发送以响应XY-RSSI请求报文。RSSI平均值包含了XY-RSSI请求报文本身的RSSI值,然后
'        RSSI平均值被归零以便为另一个一系列RSSI Blast报文做准备。因此,如果RSSI Blast报文从未被发
'        送,那么RSSI平均值就是XY-RSSI请求报文的RSSI值。
'
'        字节索引                      描    述                            值
'       ==================================================================================
'          0和1      参考节点的X位置。                               bit[15:2] 整米
'                                                                    bit[1:0]  0.25米
'                                                                    如果该字段为0xFFFF,
'                                                                    表明参考节点没有被配置。
'
'          2和3      参考节点的Y位置。                               bit[15:2] 整米
'                                                                    bit[1:0]  0.25米
'                                                                    如果该字段为0xFFFF,
'                                                                    表明参考节点没有被配置。
'
'           4        任何一系列RSSI Blast广播报文并且包含XY-RSSI     0~255
'                    请求报文本身RSSI值的RSSI平均值。
'
'    盲节点查找请求报文(簇ID:0x0013)
'
'            发送该报文给一个盲节点以迫使其执行一个位置查找。当位置查找完成后,该报文的响应报文被
'        盲节点发回。位置查找所需要的时间取决于网络的总流量。该报文除了一个簇ID没有其他内容。
'
'    盲节点查找响应报文(簇ID:0x0014)
'
'            该报文被盲节点发送以响应盲节点查找请求报文。
'
'        字节索引                      描    述                            值
'       ==================================================================================
'          0         状态。                                          0 — 成功
'                                                                    1 — 没有足够的参考节点响应。
'
'         1和2       盲节点的(被CC2431内部定位引擎计算出)的X位置。   bit[15:2] 整米
'                                                                    bit[1:0]  0.25米
'
'
'         3和4       盲节点的(被CC2431内部定位引擎计算出)的Y位置。   bit[15:2] 整米
'                                                                    bit[1:0]  0.25米
'
'          5         被用来参与计算位置的参考节点数量。              0~8
'
'         6和7       最近的(基于RSSI)参考节点的短地址。              0x0000~0xFFFA,0xFFFF无效。
'
'         8和9       最近的参考节点的X位置。                         bit[15:2] 整米
'                                                                    bit[1:0]  0.25米
'
'
'         10和11     最近的参考节点的Y位置。                         bit[15:2] 整米
'                                                                    bit[1:0]  0.25米
'
'          12        最近的参考节点的RSSI。
'
'
'    参考节点配置报文(簇ID:0x0015)
'
'            发送该报文给一个参考节点来设置它的配置项目。该报文也从参考节点被发送以响应参考节点
'        配置报文。
'
'        字节索引                      描    述                            值
'       ==================================================================================
'         0和1       参考节点的X位置。                               bit[15:2] 整米
'                                                                    bit[1:0]  0.25米
'
'         2和3       参考节点的Y位置。                               bit[15:2] 整米
'
'                                                                    bit[1:0]  0.25米
'    盲节点配置报文(簇ID:0x0016)
'
'            发送该报文给一个盲节点来设置它的配置项目。该报文也从盲节点被发送以响应盲节点配置报文。
'
'        字节索引                      描    述                            值
'       ==================================================================================
'           0        盲节点的A参数。A被定义为在离发射机1米的参考距
'                    离上接收到的平均功率的绝对值(以dBm为单位)。
'
'           1        盲节点的N参数。N是路径损耗指数,用来描述来自
'                    发射机的信号功率随着距离的增大而衰减的速率。
'
'           2        运行模式。                                      0 — 被查询模式
'                                                                    1 — 自动模式。
'
'          3和4      采集时间。在发送XY-RSSI请求报文后要等待参考     以100毫秒为单位增加。
'                    节点响应的毫秒数。
'
'          5和6      循环时间。低字节首先发送。在开始一个计算周期    以100毫秒为单位增加。
'                    之前要等待的毫秒数。只用于自动模式。
'
'          7和8      报告短地址。低字节首先发送。在自动模式下,该    0x0000~0xFFFF
'                    地址为盲节点响应报文的目的地址;在查询模式下,
'                    响应被返回给请求者的地址。
'
'           9        报告端点。在自动模式下,盲节点响应报文的目的
'                    端点。
'
'           10       被用来参与位置计算的参考节点的最小数量。        1~16
'
'
'    参考节点配置请求报文(簇ID:0x0017)
'
'            发送该报文给一个参考节点以请求它的配置。该请求报文的响应报文是参考节点配置报文。
'        该报文除了一个簇ID没有其他内容。
'
'
'    盲节点配置请求报文(簇ID:0x0018)
'
'            发送该报文给一个盲节点以请求它的配置。该请求报文的响应报文是盲节点配置报文。
'        该报文除了一个簇ID没有其他内容。
'
'    RSSI Blast报文(簇ID:0x0019)
'
'            以“1跳”半径广播该报文,在相对短的时间多次发送该报文来触发射频范围内的参考节点计算
'        它们收到的RSSI Blast广播报文的平均RSSI值。该报文除了一个簇ID没有其他内容。
'
'
'    用户PC端软件应用可以通过Z-Stack中规定的系统应用报文(SYS_APP_MSG)来与Location Dongle进行通信。
'
'    PC可以通过使用系统应用报文(SYS_APP_MSG)来发送OTA(over the air)报文,输出报文格式为:
'
'        字节索引                      描    述                            值
'       ==================================================================================
'          0和1      目的地址 — 低字节在前。输出报文的目的地址。     0x0000~0xFFFF
'           2        输出报文的目的端点。                             0x00~0xFF
'          3和4      簇ID — 低字节在前。输出报文的簇ID。             0x0000~0xFFFF
'           5        输出报文(下一字段)长度。                         0x00~0xFF
'          6~n      输出报文(Z-Stack定位规范中规定的那9个报文)
'
'
'
'    PC可以通过使用系统应用报文(SYS_APP_MSG)来输入OTA(over the air)报文,输入报文格式为:
'
'        字节索引                      描    述                            值
'       ==================================================================================
'           0        应用端点。                                    对于本应用,应为203
'          1和2      源地址 — 低字节在前。输入报文的源地址。         0x0000~0xFFFF
'           3        输入报文的源端点。                                 0x00~0xFF
'          4和5      簇ID — 低字节在前。输入报文的簇ID。             0x0000~0xFFFF
'           6        输入报文的长度。                                   0x00~0xFF
'          7~n      输入报文(Z-Stack定位规范中规定的那9个报文)
'
'
'
'    系统应用报文SYS_APP_MSG被用来给应用发送原始数据。该请求报文可以或不能获得一个响应报文。
'该请求报文可能获得多个异步响应报文。
'
'    系统应用报文SYS_APP_MSG的格式如下:
'
'        *****************************************************************************
'        *   CMD = 0x0018   *   LEN = 0x01 +Data字段长度   *   Endpoint   *   Data   *
'        *****************************************************************************
'
'        Endpoint:该字段长度为1字节。该字段指定数据将被发送给的应用端点。不要使用该字段
'                  来发送ZDO报文(端点0)。
'        Data:该字段长度可变。该字段包含来自应用端点的原始数据包。
'
'
'    SYS_APP_MSG_RESPONSE报文是系统应用报文SYS_APP_MSG的响应报文,格式如下:
'
'        ***************************************************************
'        *   CMD = 0x1018   *   LEN = 可变   *   Endpoint   *   Data   *
'        ***************************************************************
'
'        Endpoint:该字段长度为1字节。该字段指明数据是来自哪个应用端点。
'        Data:该字段长度可变。该字段包含来自应用端点的原始数据包。
'

 如果想用它默认的通讯协议,就只能这样。当然,市面上的zigbee开发套件基本都是用的这个协议。
 但是,还有另外一种方法,就是禁掉这些函数,自己编写函数。
 这就是我弄出来的东西。
 首先你想禁掉这些很简单,注意到#if 这个后面的内容没, 这个是宏定义判断语句, 只要后面的值有定义(有时候还必须为1)的时候,就生效,所以最直接的方法救治把宏定义禁掉(不要很傻的说把整个注释掉,这个是最白痴的做法,协议栈的文件是所有工程通用的,最好保证完整性。这也就是为什么这个协议栈用那么多宏定义的原因,人家是很聪明的。)
 但是涉及到怎么禁,这个我估计会难倒很多人。因为很多人注重代码,却从来忽视了一个东西,那就是编译器。
 zigbee的这些宏定义你在代码里面是找不到的,为了修改方便,它们都被设置成有编译器设定。
 其它拐弯磨脚的我就不说了,直接方法把。
 在IAR下打开一个工程, 从左边workspace里面工程名字点右键->option进入工程设定,这里点左边的C/C++ Complier,然后直接左边上面点Preprossor。
 这个界面就是用编译器的宏定义页面, 里面有文件的默认库地址,还有宏定义,在下面那个。可以看到很多宏定义,其中会有一项ZTOOL_P1(或者是ZTOOL_P2,ZAPP_P1,ZAPP_P2)这个是定义串口调用函数的宏定义, 如果你不想用这些函数, 这几个你就必须注释掉。怎么注释?删除?可以,这个是最简单的,但是如果以后你还要用到呢?所以最好的方法就是给它前面随便价格数字或者小写字母就是了,因为宏定义习惯上都是用大写字母(只是习惯,小写也没事),可以很大成都避免跟其它定义冲突的。

 好了, 注释掉后,就得自己编写调用函数,这是必须的,要不你一样用不了。
 首先是自己编写一个初始化函数:
    halUARTCfg_t uartConfig; //定义串口初始化结构

    /* UART Configuration */
  uartConfig.configured           = TRUE; 
  uartConfig.baudRate             = HAL_UART_BR_115200;//波特率115200
  uartConfig.flowControl          = FALSE;
  uartConfig.flowControlThreshold = 48;
  uartConfig.rx.maxBufSize        = 128;
  uartConfig.tx.maxBufSize        = 128;
  uartConfig.idleTimeout          = 6;
  uartConfig.intEnable            = TRUE;
  uartConfig.callBackFunc         = rxCB; //自己编写的接收处理函数
  HalUARTOpen(HAL_UART_PORT_0,&uartConfig); //启动串口
HalUARTWrite( HAL_UART_PORT_0,"The CC2430 is initial finished!/n",sizeof("The CC2430 is initial finished!/n"));//只是为了测试下是否串口初始化完成了.
  接下来就是自己编写才串口接收处理函数了:
static void rxCB( uint8 port, uint8 event )
{
  uint8 *buf, len;

  /* While awaiting retries/response, only buffer 1 next buffer: otaBuf2.
   * If allow the DMA Rx to continue to run, allocating Rx buffers, the heap
   * will become so depleted that an incoming OTA response cannot be received.
   * When the Rx data available is not read, the DMA Rx Machine automatically
   * sets flow control off - it is automatically re-enabled upon Rx data read.
   * When the back-logged otaBuf2 is sent OTA, an Rx data read is scheduled.
   */
  if ( otaBuf2 )
  {
    return;
  }

  if ( !(buf = osal_mem_alloc( SERIAL_APP_RX_CNT )) )
  {
    return;
  }

  /* HAL UART Manager will turn flow control back on if it can after read.
   * Reserve 1 byte for the 'sequence number'.
   */
  len = HalUARTRead( port, buf+1, SERIAL_APP_RX_CNT-1 );

  if ( !len )  // Length is not expected to ever be zero.
  {
    osal_mem_free( buf );
    return;
  }

  /* If the local global otaBuf is in use, then either the response handshake
   * is being awaited or retries are being attempted. When the wait/retries
   * process has been exhausted, the next OTA msg will be attempted from
   * otaBuf2, if it is not NULL.
   */
  if ( otaBuf )
  {
    otaBuf2 = buf;
    otaLen2 = len;
  }
  else
  {
    otaBuf = buf;
    otaLen = len;
    /* Don't call SerialApp_SendData() from here in the callback function.
     * Set the event so SerialApp_SendData() runs during this task's time slot.
     */

    osal_set_event( LocDongle_TaskID, 0x0004 ); //通知任务串口有数据
  }
}
这个我坦白,不是我自己编写的处理程序,是从栈里面抽出来的的, 但是有什么所谓?主要是自己能用,而且摆脱了串口栈束缚。

接下就是自己用任务处理串口数据了, 上面这个只是先把串口数据保存起来而已。有点类似于队列的原理。

到了这也就没我的事了呵。很简单的东西。不好的请见谅。

猜你喜欢

转载自blog.csdn.net/xuzhenglim/article/details/5912370
今日推荐