Chinaunix首页 | 论坛 | 博客
  • 博客访问: 43219
  • 博文数量: 59
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 10
  • 用 户 组: 普通用户
  • 注册时间: 2015-05-31 10:42
文章分类
文章存档

2015年(59)

我的朋友

分类: 嵌入式

2015-05-31 10:50:33

    下面看一下终端结点的不同之处,下面这个图是终端结点的的编译选项,这里我们可以看到没有了编译选项SOFT_START。这里我们重点看一下不同之处。
#if defined( ZDO_COORDINATOR ) && !defined( SOFT_START )
// Set the default to coodinator
  devStartModes_t devStartMode = MODE_HARD;
#else
  devStartModes_t devStartMode = MODE_JOIN;     // Assume joining
  //devStartModes_t devStartMode = MODE_RESUME; // if already "directly joined"
  // to parent. Set to make the device do an Orphan scan.
#endif
// Device Logical Type
uint8 zgDeviceLogicalType = DEVICE_LOGICAL_TYPE;
#if defined ( SOFT_START )
  #define DEVICE_LOGICAL_TYPE ZG_DEVICETYPE_SOFT
#elif defined( ZDO_COORDINATOR )
  #define DEVICE_LOGICAL_TYPE ZG_DEVICETYPE_COORDINATOR
#elif defined (RTR_NWK)
  #define DEVICE_LOGICAL_TYPE ZG_DEVICETYPE_ROUTER
#else
  #define DEVICE_LOGICAL_TYPE ZG_DEVICETYPE_ENDDEVICE
#endif
最后得出
zgDeviceLogicalType = DEVICE_LOGICAL_TYPE =ZG_DEVICETYPE_ENDDEVICE
     这里主要的不同还是在应用程序中的按键部分,下面是按键的程序,这个是在SimpleSwitch.c中
void zb_HandleKeys( uint8 shift, uint8 keys )
{
  uint8 startOptions;
  uint8 logicalType;
 
  // Shift is used to make each button/switch dual purpose.
  if ( shift )
  {
    if ( keys & HAL_KEY_SW_1 )
    {
    }
    if ( keys & HAL_KEY_SW_2 )
    {
    }
    if ( keys & HAL_KEY_SW_3 )
    {
    }
    if ( keys & HAL_KEY_SW_4 )
    {
    }
  }
  else
  {
    if ( keys & HAL_KEY_SW_1 )
    {
      if ( myAppState == APP_INIT )
      {
        // In the init state, keys are used to indicate the logical mode.
        // The Switch device is always an end-device 在这里当按下S1按键时设置为终端设备
        logicalType = ZG_DEVICETYPE_ENDDEVICE;
        zb_WriteConfiguration(ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType);
       
        // Do more configuration if necessary and then restart device with auto-start bit set
 
        zb_ReadConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
        startOptions = ZCD_STARTOPT_AUTO_START;
        zb_WriteConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
        zb_SystemReset();
 
      }
      else
      {
        // Initiate a binding with null destination
        zb_BindDevice(TRUE, TOGGLE_LIGHT_CMD_ID, NULL);
      }
    }
    if ( keys & HAL_KEY_SW_2 )
    {
      if ( myAppState == APP_INIT )
      {
        // In the init state, keys are used to indicate the logical mode.
        // The Switch device is always an end-device按键SW2和SW1的作用是一样的,都是设置为终端设备,这里也和协调器和路由器稍微有点不同
        logicalType = ZG_DEVICETYPE_ENDDEVICE;
        zb_WriteConfiguration(ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType);
 
 
        zb_ReadConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
        startOptions = ZCD_STARTOPT_AUTO_START;
        zb_WriteConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );
        zb_SystemReset();
      }
      else
      {
        // Send the command to toggle light
        zb_SendDataRequest( 0xFFFE, TOGGLE_LIGHT_CMD_ID, 0,
                        (uint8 *)NULL, myAppSeqNumber, 0, 0 );
      }
    }
    if ( keys & HAL_KEY_SW_3 )
    {
      // Remove all existing bindings
      zb_BindDevice(FALSE, TOGGLE_LIGHT_CMD_ID, NULL);
    }
    if ( keys & HAL_KEY_SW_4 )
    {
    }
  }
}
     从上面可以看出KEY1 KEY2都是作为终端设备的。而在函数中也并没有改变上面的变量的类型。下面的这个函数,在函数uint8 ZDOInitDevice( uint16 startDelay )调用的,上面在分析协调器的时,也有看到,这个函数在这里就直接返回,并没有起到什么作用。
void ZDAppDetermineDeviceType( void )
{
  if ( zgDeviceLogicalType == ZG_DEVICETYPE_ENDDEVICE )
    return;
 
#if defined ( SOFT_START )
  if ( zgDeviceLogicalType == ZG_DEVICETYPE_COORDINATOR )
  {
    devStartMode = MODE_HARD;     // Start as a coordinator
    ZDO_Config_Node_Descriptor.LogicalType = NODETYPE_COORDINATOR;
  }
  else
  {
    if ( zgDeviceLogicalType == ZG_DEVICETYPE_ROUTER )
    {
      softStartAllowCoord = FALSE;  // Don't allow coord to start
      continueJoining = TRUE;
    }
    devStartMode = MODE_JOIN;     // Assume joining
  }
#endif // SOFT_START
}

UINT16 ZDApp_event_loop( byte task_id, UINT16 events )
{
if ( events & ZDO_NETWORK_INIT )
  {
    // Initialize apps and start the network
    devState = DEV_INIT;
    ZDO_StartDevice( (uint8)ZDO_Config_Node_Descriptor.LogicalType, devStartMode,
                     DEFAULT_BEACON_ORDER, DEFAULT_SUPERFRAME_ORDER );
 
    // Return unprocessed events
    return (events ^ ZDO_NETWORK_INIT);
  }
}
ZDO_StartDevice()函数中可以根据不同的选项来进行操作。
void ZDO_StartDevice( byte logicalType, devStartModes_t startMode, byte beaconOrder, byte superframeOrder )
{
  ZStatus_t ret;
 
  ret = ZUnsupportedMode;
 
#if defined(ZDO_COORDINATOR)
  if ( logicalType == NODETYPE_COORDINATOR )
  {
    if ( startMode == MODE_HARD )
    {
      devState = DEV_COORD_STARTING; //调用网络的格式化函数形成网络
      ret = NLME_NetworkFormationRequest( zgConfigPANID, zgDefaultChannelList,
                                          zgDefaultStartingScanDuration, beaconOrder,
                                          superframeOrder, false );
    }
    else if ( startMode == MODE_RESUME )
    {
      // Just start the coordinator
      devState = DEV_COORD_STARTING;
      ret = NLME_StartRouterRequest( beaconOrder, beaconOrder, false );
    }
    else
    {
#if defined( LCD_SUPPORTED )
      HalLcdWriteScreen( "StartDevice ERR", "MODE unknown" );
#endif
    }
  }
#endif  // !ZDO_COORDINATOR
 
#if !defined ( ZDO_COORDINATOR ) || defined( SOFT_START )
  if ( logicalType == NODETYPE_ROUTER || logicalType == NODETYPE_DEVICE )
  {
    if ( (startMode == MODE_JOIN) || (startMode == MODE_REJOIN) )
    {
      devState = DEV_NWK_DISC;
 
  #if defined( MANAGED_SCAN )
      ZDOManagedScan_Next();
      ret = NLME_NetworkDiscoveryRequest( managedScanChannelMask, BEACON_ORDER_15_MSEC );
  #else
      ret = NLME_NetworkDiscoveryRequest( zgDefaultChannelList, zgDefaultStartingScanDuration );
  #endif
    }
    else if ( startMode == MODE_RESUME )
    {
      if ( logicalType == NODETYPE_ROUTER )
      {
        ZMacScanCnf_t scanCnf;
        devState = DEV_NWK_ORPHAN;
 
        /* if router and nvram is available, fake successful orphan scan */
        scanCnf.hdr.Status = ZSUCCESS;
        scanCnf.ScanType = ZMAC_ORPHAN_SCAN;
        scanCnf.UnscannedChannels = 0;
        scanCnf.ResultListSize = 0;
        nwk_ScanJoiningOrphan(&scanCnf);
 
        ret = ZSuccess;
      }
      else
      {
        devState = DEV_NWK_ORPHAN;
        ret = NLME_OrphanJoinRequest( zgDefaultChannelList,
                                      zgDefaultStartingScanDuration );
      }
    }
    else
    {
#if defined( LCD_SUPPORTED )
      HalLcdWriteScreen( "StartDevice ERR", "MODE unknown" );
#endif
    }
  }
#endif  //!ZDO COORDINATOR || SOFT_START
 
  if ( ret != ZSuccess )
    osal_start_timerEx(ZDAppTaskID, ZDO_NETWORK_INIT, NWK_RETRY_DELAY );
}
     在终端的结点时,就会执行蓝色的代码。至此,在程序中设备类型就确定了。这样整个工程中的三个设备就可以确定,并按照设定的方式来加入网络,或者形成网络了。

补充:
还有一个问题有点迷糊,现在解决一下,就是zgDeviceLogicalType全局变量是怎么改变的,因为这个全局变量会在函数void ZDAppDetermineDeviceType( void )用到,在工程中搜索zgDeviceLogicalType变量,并没有发现那里给其赋于了新值,只在ZGlobals.c文件中有下面的赋值,可是我们在应用程序中对NV条目也就是ZCD_NV_LOGICAL_TYPE中,写入了新的值。在按键处理程序中,
uint8 zgDeviceLogicalType = DEVICE_LOGICAL_TYPE;
 
zb_ReadConfiguration( ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType );
        if ( logicalType != ZG_DEVICETYPE_ENDDEVICE )
        {
          logicalType = ZG_DEVICETYPE_COORDINATOR;
          zb_WriteConfiguration(ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType);
        }
那条目ZCD_NV_LOGICAL_TYP中的值是怎么最后赋给了zgDeviceLogicalType变量呢?这个按键程序完后会执行系统的重启命令。
可以看到在
typedef struct zgItem
{
  uint16 id;
  uint16 len;
  void *buf;
} zgItem_t;
static CONST zgItem_t zgItemTable[] =
{
#if defined ( NV_INIT )
  {
    ZCD_NV_LOGICAL_TYPE, sizeof(zgDeviceLogicalType), &zgDeviceLogicalType//在这里进行了彼此之间的联系
  },
  {
    ZCD_NV_POLL_RATE, sizeof(zgPollRate), &zgPollRate
  },
.......
}
在下面的函数初始化的进行判断
uint8 zgInit( void )
{
  uint8  i = 0;
  uint8  setDefault = FALSE;
 
  // Do we want to default the Config state values 这里可以看到zgReadStartupOptions()读取ZCD_NV_STARTUP_OPTION条目的选项,在前面的应用中我们可以看到,ZCD_NV_STARTUP_OPTION条目中已经写入了ZCD_STARTOPT_AUTO_START值也就是0x04 & 0x01if判断不成功。setDefualt=FALSE
  if ( zgReadStartupOptions() & ZCD_STARTOPT_DEFAULT_CONFIG_STATE )
  {
    setDefault = TRUE;
  }
 
...................
  while ( zgItemTable[i].id != 0x00 )
  {
    // Initialize the item
    zgItemInit( zgItemTable[i].id, zgItemTable[i].len, zgItemTable[i].buf, setDefault  );
 
    // Move on to the next item
    i++;
  }
 
  // Clear the Config State default
  if ( setDefault )
  {
    zgWriteStartupOptions( ZG_STARTUP_CLEAR, ZCD_STARTOPT_DEFAULT_CONFIG_STATE );
  }
 
  return ( ZSUCCESS );
}
 
#define ZCD_STARTOPT_DEFAULT_CONFIG_STATE  0x01
#define ZCD_STARTOPT_DEFAULT_NETWORK_STATE 0x02
#define ZCD_STARTOPT_AUTO_START            0x04
    在zgItemInit()函数中,由于传递过来的值是setDefaultFALSE,也就是NV条目中已经写入了值所以,不会进行默认的初始化,而是读出条目中的值 ,这样就会把ZCD_NV_LOGICAL_TYP条目中的值,赋值给了zgDeviceLogicalType变量。这里也就是对这个变量的改变过程。
static uint8 zgItemInit( uint16 id, uint16 len, void *buf, uint8 setDefault )
{
 
  uint8 status;
 
  // If the item doesn't exist in NV memory, create and initialize
  // it with the value passed in. 如果条目已经存在的话,直接返回成功,不存在的的话直接创建和初始化
  status = osal_nv_item_init( id, len, buf );
  if ( status == ZSUCCESS )
  {
    if ( setDefault )
    {
      // Write the default value back to NV
      status =  osal_nv_write( id, 0, len, buf );
    }
    else
    {
   // The item exists in NV memory, read it from NV memory
    条目已经存在则读取
      status = osal_nv_read( id, 0, len, buf );
    }
  }
 
  return (status);
}
阅读(326) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~