打印
[Zigbee]

Zigbee Stack CC2530 ZNP使用

[复制链接]
1143|31
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
aoyi|  楼主 | 2020-2-1 18:16 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
概述
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



使用特权

评论回复

相关帖子

沙发
aoyi|  楼主 | 2020-2-1 18:16 | 只看该作者
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);
  }
}


使用特权

评论回复
板凳
aoyi|  楼主 | 2020-2-1 18:17 | 只看该作者
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
}


使用特权

评论回复
地板
aoyi|  楼主 | 2020-2-1 18:18 | 只看该作者
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;
    }
  }
}


使用特权

评论回复
5
aoyi|  楼主 | 2020-2-1 18:18 | 只看该作者
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:
在该配置中,可以修改信道等信息

使用特权

评论回复
6
aoyi|  楼主 | 2020-2-1 18:19 | 只看该作者
编译测试

在修改完成后,进行编译并下载到CC2530中。
使用USB转串口,与CC2530的Uart0连接。然后使用Z-TOOLS工具进行测试。


使用特权

评论回复
7
aoyi|  楼主 | 2020-2-1 18:19 | 只看该作者

测试结果:

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


使用特权

评论回复
8
kkzz| | 2020-2-2 10:48 | 只看该作者
cc2530为什么有两个晶振

使用特权

评论回复
9
hudi008| | 2020-2-2 10:48 | 只看该作者
cc2530单片机如何定义一个标志变量

使用特权

评论回复
10
lzmm| | 2020-2-2 10:49 | 只看该作者
cc2530是属于什么单片机

使用特权

评论回复
11
minzisc| | 2020-2-2 10:49 | 只看该作者
cc2530是单片机吗

使用特权

评论回复
12
selongli| | 2020-2-2 10:49 | 只看该作者
cc2530与rs232通信时是使用了哪几个引脚?

使用特权

评论回复
13
fentianyou| | 2020-2-2 10:49 | 只看该作者
cc2530串口为什么不能被电脑识别

使用特权

评论回复
14
xiaoyaodz| | 2020-2-2 10:49 | 只看该作者
cc2430与cc2530的区别?

使用特权

评论回复
15
febgxu| | 2020-2-2 10:50 | 只看该作者
zigbeecc2530如何组网

使用特权

评论回复
16
sdlls| | 2020-2-2 10:50 | 只看该作者
Proteus 7.8 SP2上怎么cc2530

使用特权

评论回复
17
pixhw| | 2020-2-2 10:50 | 只看该作者
CC2530和EM357的不同之处?  

使用特权

评论回复
18
xiaoyaodz| | 2020-2-2 10:51 | 只看该作者
cc2530的供电模式有哪五种

使用特权

评论回复
19
kkzz| | 2020-2-2 10:51 | 只看该作者
cc2530和zigbee之间到底是怎么互相作用的?

使用特权

评论回复
20
fentianyou| | 2020-2-2 10:51 | 只看该作者
zigbee单片机cc2530按键怎么定义

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

100

主题

3306

帖子

3

粉丝