Zigbee Stack CC2530 ZNP使用

概述

TI 的Z-Stack 提供兩種解決方案,一種基於TI 2530芯片爲核心的Zigbee解決方案,另一種爲ZNP(Zigbee and Processor),即CC2530+MCU的解決方案,這是TI提供的兩種不同的解決方案。

硬件配置

當前使用的ZNP方案爲MT7620N+CC2530的方式,MT7620N與CC2530採用UART接口通訊。

管腳            CC2530    
UART-RXD    P0_2    Pin17
UART-TXD    P0_3    Pin16
VCC         x       x
GND         x       x

ZNP工程設置(基於Z-Stack Home 1.2.2a.44539)

在Z-Stack協議棧中,TI已經已經實現了ZNP工程,工程目錄位於

Z-Stack Home 1.2.2a.44539\Projects\zstack\ZNP\cc253x

打開工程選擇CC2530-DEBUG進行相關的修改。
參考資料:

Z-Stack Home 1.2.2a.44539\Documents\API\Z-Stack ZNP Interface Specification.pdf 第2.3章節
裏面描述了CC2530ZNP的硬件接口

Step1.使能CC2530串口支持

通過ZNP Interface Specification 2.3.1.1 中的硬件接口描述可以看到,CFG1接口爲高電平時CC2530使能SPI接口,位低電平時CC2530使能UART接口。
CFG0控制CC2530是使用內置32k時鐘還是外置時鐘。
這個初始化配置位於void InitBoard( uint8 level )函數中。

void InitBoard( uint8 level )
{
  if ( level == OB_COLD )
  {
    // IAR does not zero-out this byte below the XSTACK.
    *(uint8 *)0x0 = 0;
    // Interrupts off
    osal_int_disable( INTS_ALL );
    // Check for Brown-Out reset
    ChkReset();

#if defined CC2531ZNP
    znpCfg1 = ZNP_CFG1_UART;
#elif defined CC2530_MK
    znpCfg1 = ZNP_CFG1_SPI;
    znpCfg0 = ZNP_CFG0_32K_OSC;
#else
    //znpCfg1 = P2_0;
    //znpCfg0 = P1_2;
    // Tri-state the 2 CFG inputs after being read (see hal_board_cfg_xxx.h for CFG0.)
    //P1INP |= BV(2);
    //P2INP |= BV(0);
    znpCfg1 = ZNP_CFG1_UART; //使能UART功能
    znpCfg0 = ZNP_CFG0_32K_XTAL;//使能外部32K時鐘
#endif
  }
  else  // !OB_COLD
  {
    /* Initialize Key stuff */
    HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE, OnBoard_KeyCallback);
  }
}

Step2 關閉Uart流控

默認的情況下ZNP串口通信是使能流控,但是ZAP上面並沒有使用流控,所以需要關閉ZNP中的流控功能。
流控主要是在串口初始化的時候配置。代碼位於
znp_app.c:
static void npInit(void)
{
  if (ZNP_CFG1_UART == znpCfg1)
  {
    halUARTCfg_t uartConfig;

    uartConfig.configured           = TRUE;
    uartConfig.baudRate             = ZNP_UART_BAUD;
#ifdef ZNP_ALT
    uartConfig.flowControl          = FALSE;
#else
    uartConfig.flowControl          = FALSE;//TRUE;//關閉流控
#endif
    uartConfig.flowControlThreshold = HAL_UART_FLOW_THRESHOLD;
    uartConfig.rx.maxBufSize        = HAL_UART_RX_BUF_SIZE;
    uartConfig.tx.maxBufSize        = HAL_UART_TX_BUF_SIZE;
    uartConfig.idleTimeout          = HAL_UART_IDLE_TIMEOUT;
    uartConfig.intEnable            = TRUE;
    uartConfig.callBackFunc         = npUartCback;
    HalUARTOpen(HAL_UART_PORT, &uartConfig);
    MT_UartRegisterTaskID(znpTaskId);
  }
  else
  {
    /* npSpiInit() is called by hal_spi.c: HalSpiInit().*/
  }

  npInitNV();
#if defined (MT_ZDO_FUNC)
  MT_ZdoInit();
#endif
  MT_SysResetInd();
#if defined ZCL_KEY_ESTABLISH
#if defined TC_LINKKEY_JOIN
  zcl_TaskID = znpTaskId;
#endif
#endif
#if LQI_ADJUST
  ZMacLqiAdjustMode(LQI_ADJ_MODE1);
#endif
#if defined CC2531ZNP
  (void)osal_pwrmgr_task_state(znpTaskId, PWRMGR_HOLD);
#endif
}

Step3 注意串口處理函數

串口通訊協議可以查看

Z-Stack Home 1.2.2a.44539\Documents\API\Z-Stack Monitor and Test API.pdf

在串口數據處理使用了void MT_UartProcessZToolData ( uint8 port, uint8 event )函數,該函數位於MT_UART.c文件下,有時在其他的工程中可能會修改該函數,來達到處理自己私有串口協議的目的。這樣會造成在使用ZNP時無法通訊的問題,只需要還原到最初的串口處理方式就可以解決問題。

MT_UART.c:

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:
        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[MT_RPC_POS_LEN] = LEN_Token;
          state = 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)
        {
          state = DATA_STATE;
        }
        else
        {
          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;

        /* 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[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;

        /* 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;
    }
  }
}

Step4 修改ZNP參數

在Z-Stack Monitor and Test API.pdf中有許多的功能,如果想添加這些功能可以在工程的Tools/znp.cfg中定義相關的功能宏。
Tools/znp.cfg:

#znp.cfg:

-DZNP_UART_BAUD=HAL_UART_BR_115200 //修改串口波特率

-DZIGBEEPRO
-DZIGBEE_FRAGMENTATION
-DINTER_PAN
-DOSAL_CLOCK
-DOSAL_SAPI=FALSE
-DSAPI_CB_FUNC=FALSE

Tools/f8wconfig.cfg:
在該配置中,可以修改信道等信息

編譯測試

在修改完成後,進行編譯並下載到CC2530中。
使用USB轉串口,與CC2530的Uart0連接。然後使用Z-TOOLS工具進行測試。
這裏寫圖片描述

測試結果:
這裏寫圖片描述

下一步就是移植zigbee linux gateway 到mt7620N上面。MT7620N上面運行的是openwrt系統。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章