概述
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系統。