微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 微波和射频技术 > 射频综合技术问答 > 第八讲:怎样实现入网操作

第八讲:怎样实现入网操作

时间:10-02 整理:3721RD 点击:
由于工作和搬家的原因,很长一段时间没有更新《Zstack协议栈初窥》系列文章了,在此向大家表达我深深的歉意。
这一期我将继续顺着Zstack协议栈初窥(六)的脉络,主要讲述Zigbee路由设备是如何完成入网操作的。
我们之前曾经提到过,所有zigbee的设备只有在完成入网过程后才能够接收来自网络中其它设备发送的无线信息,因此入网操作是Zstack协议栈中非要重要的一项功能。
Zigbee路由设备在首次上电后需要做的最重要的事情就是加入网络,我们下面就根据具体程序代码来一步步理清这个过程。同协调器一样,路由设备的具体执行流程也是:Main()->osal_init_system()->osalInitTasks()->ZDApp_Init()。
ZDApp_Init首先检测SW1是否被按下,如果SW1被按下,设备将处于DEV_HOLD状态,不会进入组网状态,这里我们要特别注意。如果SW1没有被按下,那么程序将调用ZDOInitDevice来开启设备。
uint8 ZDOInitDevice( uint16 startDelay )
{
  uint8 networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE;
  uint16 extendedDelay = 0;

  if ( devState == DEV_HOLD )
  {
    // Initialize the RAM items table, in case an NV item has been updated.
    zgInitItems( FALSE );
  }

  ZDConfig_InitDescriptors();
  //devtag.071807.todo - fix this temporary solution
  _NIB.CapabilityFlags = ZDO_Config_Node_Descriptor.CapabilityFlags;

#if defined ( NV_RESTORE )
  // Get Keypad directly to see if a reset nv is needed.
  // Hold down the SW_BYPASS_NV key (defined in OnBoard.h)
  // while booting to skip past NV Restore.
  if ( HalKeyRead() == SW_BYPASS_NV )
    networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE;
  else
  {
    // Determine if NV should be restored
    networkStateNV = ZDApp_ReadNetworkRestoreState();
  }

  if ( networkStateNV == ZDO_INITDEV_RESTORED_NETWORK_STATE )
  {
    networkStateNV = ZDApp_RestoreNetworkState();
  }
  else
  {
    // Wipe out the network state in NV
    NLME_InitNV();
    NLME_SetDefaultNV();
    // clear NWK key values
    ZDSecMgrClearNVKeyValues();
  }
#endif

  if ( networkStateNV == ZDO_INITDEV_NEW_NETWORK_STATE )
  {
    ZDAppDetermineDeviceType();

    // Only delay if joining network - not restoring network state
    extendedDelay = (uint16)((NWK_START_DELAY + startDelay)
              + (osal_rand() & EXTENDED_JOINING_RANDOM_MASK));
  }

  // Initialize the security for type of device
  ZDApp_SecInit( networkStateNV );

  if( ZDO_INIT_HOLD_NWK_START != startDelay )
  {
    devState = DEV_INIT;    // Remove the Hold state

    // Initialize leave control logic
    ZDApp_LeaveCtrlInit();

    // Check leave control reset settings
    ZDApp_LeaveCtrlStartup( &devState, &startDelay );

    // Leave may make the hold state come back
    if ( devState == DEV_HOLD )
    {
      // Set the NV startup option to force a "new" join.
      zgWriteStartupOptions( ZG_STARTUP_SET, ZCD_STARTOPT_DEFAULT_NETWORK_STATE );

      // Notify the applications
      osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );

      return ( ZDO_INITDEV_LEAVE_NOT_STARTED );   // Don't join - (one time).
    }

    // Trigger the network start
    ZDApp_NetworkInit( extendedDelay );
  }

  // set broadcast address mask to support broadcast filtering
  NLME_SetBroadcastFilter( ZDO_Config_Node_Descriptor.CapabilityFlags );

  return ( networkStateNV );
}
上面的这段代码我们在Zstack协议栈初窥(六)中也曾经贴出过,这里再次把它拿出来是要更细致地来分析它的作用。我们假设if ( HalKeyRead() == SW_BYPASS_NV )判断结果为false,那么networkStateNV的状态将取决于ZDApp_ReadNetworkRestoreState()的返回值。
uint8 ZDApp_ReadNetworkRestoreState( void )
{
  uint8 networkStateNV = ZDO_INITDEV_RESTORED_NETWORK_STATE;

  // Look for the New Network State option.
  if ( zgReadStartupOptions() & ZCD_STARTOPT_DEFAULT_NETWORK_STATE )
  {
    networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE;
  }

  return ( networkStateNV );
}
正常情况下,该返回值为ZDO_INITDEV_RESTORED_NETWORK_STATE。继续查看下面的代码,由于if ( networkStateNV == ZDO_INITDEV_RESTORED_NETWORK_STATE )为true,ZDApp_RestoreNetworkState()将被调用执行。
uint8 ZDApp_RestoreNetworkState( void )
{
  uint8 nvStat;
  // Initialize NWK NV items
  nvStat = NLME_InitNV();
  if ( nvStat != NV_OPER_FAILED )
  {
    if ( NLME_RestoreFromNV() )
    {
      // Are we a coordinator
      ZDAppNwkAddr.addr.shortAddr = NLME_GetShortAddr();
      if ( ZDAppNwkAddr.addr.shortAddr == 0 )
        ZDO_Config_Node_Descriptor.LogicalType = NODETYPE_COORDINATOR;
      devStartMode = MODE_RESUME;
      osal_cpyExtAddr( ZDO_UseExtendedPANID, _NIB.extendedPANID );
    }
    else
    {
      nvStat = NV_ITEM_UNINIT;
    }
    if ( ZG_SECURE_ENABLED )
    {
      nwkFrameCounterChanges = 0;
      if ( ZG_BUILD_COORDINATOR_TYPE && ZG_DEVICE_COORDINATOR_TYPE )
      {
        ZDApp_RestoreNwkKey();
      }
    }
    // The default for RxOnWhenIdle is true for Routers and false for end devices
    // [setup in the NLME_RestoreFromNV()].  Change it here if you want something
    // other than default.
  }

  if ( nvStat == ZSUCCESS )
    return ( ZDO_INITDEV_RESTORED_NETWORK_STATE );
  else
    return ( ZDO_INITDEV_NEW_NETWORK_STATE );
}
该函数负责从CC2530的NV存储器中读取设备之前保存的网络数据信息。由于我们的路由设备是全新的没有入网过的,因此NLME_RestoreFromNV()的返回值为flase,nvStat =将被赋值为NV_ITEM_UNINIT,ZDApp_RestoreNetworkState()函数的返回值为ZDO_INITDEV_NEW_NETWORK_STATE;如果设备之前曾经加入过网络,并且在预编译选项中我们启用了NV_RESTORE,那么NLME_RestoreFromNV()的返回值为true,程序将通过NLME_GetShortAddr()等函数获取保存在NV中的网络地址、PANID等信息,ZDApp_RestoreNetworkState()函数的返回值将为ZDO_INITDEV_RESTORED_NETWORK_STATE。   
未完待续。

本文为与非网月光码头原创,未经允许谢绝转载。
更多内容请见:【深度分析Zigbee】Zigbee技术知多少?资深大牛对对碰
----------------------------
主讲嘉宾简   介:网名:月光码头。毕业于中国科学院电子学研究所,主要从事zigbee物联网方向的应用研究,尤其擅长TI RF芯片、和Silicon Lab    MCU芯片的使用。现就职于上海理滋芯片设计公司,任研发部门经理,主要从事智能家居产品的设计开发,拥有5年多的zigbee软硬件开发经验。
------------------
推荐技术讲座:
  听东北人讲天线:每周一个实例,个个经典!(CST仿真实践全包括)
【ADS学习小组】课程汇总(火烽主讲)
【HFSS学习小组】课程汇总(木木主讲)

终于回归了,期待已久

感谢小编的精彩讲解,确实大有收获!

终于等到了续集,谢谢啦

从一看到八小编写的很好,因为我刚学习CC2530的ZigBee还是有点迷惑和不知如何用在自己的工作中,特请前辈指教。比如我使用一个协调器需要高速的读取同时快速移动(每秒5米)的多个终端节点(100个),每个终端节点只要把自身的ID传给协调器就可,我需要使用TI提供的那个协议栈来完成呢。项目中还规定终端节点使用电池供电并可靠使用6个月以上才可更换。

从一看到八小编写的很好,因为我刚学习CC2530的ZigBee还是有点迷惑和不知如何用在自己的工作中,特请前辈指教。比如我使用一个协调器需要高速的读取同时快速移动(每秒5米)的多个终端节点(100个),每个终端节点只要把自身的ID传给协调器就可,我需要使用TI提供的那个协议栈来完成呢。项目中还规定终端节点使用电池供电并可靠使用6个月以上才可更换。

我试过用Zigbee接RFID读写器,实现数据的无线传输,不错。

谢谢分享

111111111111111

谢谢分享!求更新快一点

更新啊 大神

求更新。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top