Z-Statk协调器 路由器 终端的确定---Simple例程(一).doc_第1页
Z-Statk协调器 路由器 终端的确定---Simple例程(一).doc_第2页
Z-Statk协调器 路由器 终端的确定---Simple例程(一).doc_第3页
Z-Statk协调器 路由器 终端的确定---Simple例程(一).doc_第4页
Z-Statk协调器 路由器 终端的确定---Simple例程(一).doc_第5页
已阅读5页,还剩21页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Z-Statk协调器 路由器 终端的确定-Simple例程(一)2010-12-24 09:42:10分类:嵌入式 当我们选择了终端、路由器、或者协调器的时候,来看一下程序中是怎么判断的。也就是如何作为其中的各个角色进行启动,是加入网络,还是形成网络。因为我们在这三个设备上使用的一套代码。首先,我们可以看到下面的三张图,这个是以SampleApp例程为例子。从三幅图中我们可以看来,当选择不同的设备类型编译时,下面加载的配置文件是不一样的。 下面是f8wCoord.cfg文件中的配置信息。这个协调器中的编译选项比路由器结点的编译选项相比多了一个-DZDO_COORDINATOR选项。/* Common To All Applications */-DCPU32MHZ / CC2430s Run at 32MHz-DFORCE_MAC_NEAR / MAC code in NEAR-DROOT=_near_func / MAC/ZMAC code in NEAR-DMAC_CFG_APP_PENDING_QUEUE=TRUE/* Coordinator Settings */-DZDO_COORDINATOR / Coordinator Functions-DRTR_NWK / Router Functions/* Optional Settings */-DBLINK_LEDS / LED Blink Functions/* Compiler keywords */-DCONST=const _code-DGENERIC=_generic / Ptr declaration下面是终端结点的配置信息。f8wEndev.cfg/* Common To All Applications */-DCPU32MHZ / CC2430s Run at 32MHz-DFORCE_MAC_NEAR / MAC code in NEAR-DROOT=_near_func / MAC/ZMAC code in NEAR/* Optional Settings */-DMAC_OPT_FFD=0 / ZigBee RFD应该是决定了是终端结点-DBLINK_LEDS / LED Blink Functions/* Compiler keywords */-DCONST=const _code-DGENERIC=_generic / Ptr declaration下面是路由器结点的配置信息,f8wRouter.cfg,在这里没有协调器的编译选项/* Common To All Applications */-DCPU32MHZ / CC2430s Run at 32MHz-DFORCE_MAC_NEAR / MAC code in NEAR-DROOT=_near_func / MAC/ZMAC code in NEAR-DMAC_CFG_APP_PENDING_QUEUE=TRUE/* Router Settings */-DRTR_NWK / Router Functions/* Optional Settings */-DBLINK_LEDS / LED Blink Functions/* Compiler keywords */-DCONST=const _code-DGENERIC=_generic / Ptr declaration 从上面的三个配置文件的内容,我们来看一下这三个配置文件的区别。其实区别就在上面红色标注的部分。协调器比路由结点多了-DZDO_COORDINATOR / Coordinator Functions这句话,我们也可以看到就是在协调器结点中,也定义了路由器结点的选项,也就是-DRTR_NWK/ Router Functions, 其实这也说明了,在加载f8wCoord.cfg文件时,我们可以通过应用程序来决定配置成协调器,还是配置成路由器。还必须在配置了非自动启动模式HOLD_AUTO_START和软启动模式SOFT_START两个选项后,我们可以在SimpleControllerEB这个工程中和SimpleSwitchEB这个文件中,看到下面的编译选项,有什么不同点,也就是在作为协调器时,我们的编译选项多了一个非自动启动模式HOLD_AUTO_START模式。在这个选择设备的类型这个下拉框中,我们没有发现和SampleApp例程一样有三个选项,也就是协调器,路由器,终端,这里就两个选项一个是SimpleControllerEB,另一个是SimpleSwitchEB,我们知道SimpleSwitchEB是终端结点,SimpleControllerEB可作为协调器结点,那我们的路由结点在那里呢?从上面的分析可以看到一定是加载了 f8wCoord.cfg文件的,才可能成为路由器,其实协调器和路由器是通过程序中的按键来决定的,也就是用户的应用程序,其实这个工程和其它工程还有不同的地方就是协调器和路由器共用一个应用程序的文件,也就是SimpleController.c,而终端结点的应用在另一个文件SimpleSwitch.c。这个工程所有共用的代码是sapi.c文件,这也为我们应用程序的编写提供了另一种思路。开关设备SimpleSwitchEB无论按K1还是K2都是作为终端设备的,而灯设备SimpleControllerEB按键K1则作为协调器,按K2则作为路由器。那下面我们就看看应用程序中是怎么来实现这样一个功能的。下面首先是以协调器为例子。图1 协调器的编译选项的配置还是在ZDApp.c文件中,有下面的代码:#if defined( HOLD_AUTO_START ) devStates_t devState = DEV_HOLD;#else devStates_t devState = DEV_INIT;#endif#if defined( ZDO_COORDINATOR ) & !defined( SOFT_START )/定义了ZDO_COORDINATOR,没有定义SOFT_START执行下面的配置 / Set the default to coodinator devStartModes_t devStartMode = MODE_HARD;#else/其它情况 devStartModes_t devStartMode = MODE_JOIN;/ Assumejoining /devStartModes_t devStartMode = MODE_RESUME;/ if already directly joined/ to parent. Set to make the device do an Orphan scan.#endif 在协调器中定义了编译选项非自动启动模式HOLD_AUTO_START和软启动模式SOFT_START,这里可以得知各个选项的值:devStates_t devState = DEV_HOLD; devStartModes_t devStartMode = MODE_JOIN;在Zglobals.h文件中可以看到。#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/ Values for ZCD_NV_LOGICAL_TYPE (zgDeviceLogicalType)#define ZG_DEVICETYPE_COORDINATOR 0x00#define ZG_DEVICETYPE_ROUTER 0x01#define ZG_DEVICETYPE_ENDDEVICE 0x02#define ZG_DEVICETYPE_SOFT 0x03在AF.h文件中,/ Node Logical Types#define NODETYPE_COORDINATOR 0x00#define NODETYPE_ROUTER 0x01#define NODETYPE_DEVICE 0x02在ZDConfig.c文件中。NodeDescriptorFormat_t ZDO_Config_Node_Descriptor =#if defined( ZDO_COORDINATOR ) & !defined( SOFT_START ) NODETYPE_COORDINATOR,#elif defined (RTR_NWK) NODETYPE_ROUTER,#else NODETYPE_DEVICE, / Logical Type#endif 这些变量都会在下面的分析中展示其作用。我们可以看到这个协调器中各个变量的赋值是个什么情况,也就是加粗的部分。我们知道还要从ZDApp_Init()函数分析void ZDApp_Init( byte task_id ) uint8 capabilities; / Save the task ID ZDAppTaskID = task_id; / Initialize the ZDO global device short address storage ZDAppNwkAddr.addrMode = Addr16Bit; ZDAppNwkAddr.addr.shortAddr = INVALID_NODE_ADDR; (void)NLME_GetExtAddr(); / Load the saveExtAddr pointer.加载IEEE地址/ Check for manual Hold Auto Start/打开电源时,检测到有手工设置SW_1则会设置devState = DEV_HOLD,从而不进行网络初始化 ZDAppCheckForHoldKey(); / Initialize ZDO items and setup the device - type of device to create. ZDO_Init();/初始化ZDO条目,并设置设备的启动方式是协调器,还是别的/ Register the endpoint description with the AF / This task doesnt have a Simple description, but we still need / to register the endpoint. afRegister( (endPointDesc_t *)&ZDApp_epDesc );#if defined( ZDO_USERDESC_RESPONSE ) ZDApp_InitUserDesc();#endif / ZDO_USERDESC_RESPONSE / set broadcast address mask to support broadcast filtering NLME_GetRequest(nwkCapabilityInfo, 0, &capabilities); NLME_SetBroadcastFilter( capabilities ); / Start the device?是否启动设备?如果devState不是DEV_HOLD时,则启动设备,在上面的代码分析中,也可以看到,如果定义了HOLD_AUTO_START宏,则devState等于DEV_HOLD,不会启动设备。如果按下了SW_1键devState也等于DEV_HOLD,也不会启动网络。也就是说有两种方式可以设置非自动启动模式,一种是通过按键,一种通过宏定义 if ( devState != DEV_HOLD ) ZDOInitDevice( 0 );/在本例程中没有定义HOLD_AUTO_START所以这个会成功执行 else /如果定义了HOLD_AUTO_START,则等待延时或外部事件启动网络,并且LED4灯,也就是蓝色的灯闪烁 / Blink LED to indicate HOLD_START HalLedBlink ( HAL_LED_4, 0, 50, 500 ); ZDApp_RegisterCBs(); /* ZDO_Init() */我们首先看一下ZDO_Init( void )函数void ZDO_Init( void ) / Initialize ZD items #if defined ( REFLECTOR ) ZDO_EDBind = NULL; #endif / Setup the device - type of device to create. ZDODeviceSetup();static void ZDODeviceSetup( void )#if defined( ZDO_COORDINATOR ) NLME_CoordinatorInit();/这个函数执行#endif#if defined ( REFLECTOR)/源绑定操作 #if defined ( ZDO_COORDINATOR ) APS_ReflectorInit( APS_REFLECTOR_PUBLIC);/这个函数执行 #else APS_ReflectorInit( APS_REFLECTOR_PRIVATE ); #endif#endif#if !defined( ZDO_COORDINATOR ) | defined( SOFT_START ) NLME_DeviceJoiningInit();#endif 从上面的分析可知,由于编译了HOLD_AUTO_START选项后,devState = DEV_HOLD,所以不会进入ZDOInitDevice( 0 );函数,而是闪烁LED4,指示初始化设备。这时就应该到应用程序来处理的,决定来初始化为协调器,还是路由器了。void SAPI_Init( byte task_id )if ( HalKeyRead () = HAL_KEY_SW_5) / If SW5 is pressed and held while powerup, force auto-start and nv-restore off and reset/如果SW5按下,并且打开电源,强迫关闭自动启动,并且不从NV中读出参数,并重启startOptions = ZCD_STARTOPT_CLEAR_STATE | ZCD_STARTOPT_CLEAR_CONFIG;/把默认的启动选项写入到NV中 zb_WriteConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions ); zb_SystemReset();/并重新启动系统 #endif / HAL_KEY / Set an event to start the application osal_set_event(task_id, ZB_ENTRY_EVENT);我们看了一下startOptions选项表示的是什么意思。下面的代码在ZComDef.h文件中,#define ZCD_STARTOPT_DEFAULT_CONFIG_STATE 0x01#define ZCD_STARTOPT_DEFAULT_NETWORK_STATE 0x02#define ZCD_STARTOPT_AUTO_START 0x04#define ZCD_STARTOPT_CLEAR_CONFIG ZCD_STARTOPT_DEFAULT_CONFIG_STATE#define ZCD_STARTOPT_CLEAR_STATE ZCD_STARTOPT_DEFAULT_NETWORK_STATE通过宏定义可以看出,他们都是默认的选项。可以看到在程序的最后启动了ZB_ENTRY_EVENT事件,UINT16 SAPI_ProcessEvent( byte task_id, UINT16 events )if ( events & ZB_ENTRY_EVENT ) uint8 startOptions;/ Give indication to application of device startup这里这个函数是一空函数 zb_HandleOsalEvent( ZB_ENTRY_EVENT ); / LED off cancels HOLD_AUTO_START blink set in the stack HalLedSet (HAL_LED_4, HAL_LED_MODE_OFF);/在上面当按下SW5按键后写入了默认的启动选项,这里进行了读取 zb_ReadConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions ); if ( startOptions & ZCD_STARTOPT_AUTO_START ) zb_StartRequest(); else / blink leds and wait for external input to config and restart HalLedBlink(HAL_LED_2, 0, 50, 500); return (events ZB_ENTRY_EVENT ); 我们看一下ZCD_NV_STARTUP_OPTION的初始值是什么,在下面的函数中写入了ZCD_NV_STARTUP_OPTION的初始值,初始值为0.这个函数,在uint8 zgInit( void )中被调用。uint8 zgReadStartupOptions( void ) / Default to Use Config State and Use Network State uint8 startupOption = 0; / This should have been done in ZMain.c, but just in case.if ( osal_nv_item_init( ZCD_NV_STARTUP_OPTION, sizeof(startupOption), &startupOption ) = ZSUCCESS ) / Read saved startup control osal_nv_read( ZCD_NV_STARTUP_OPTION, 0, sizeof( startupOption ), &startupOption); return ( startupOption ); 由于#define ZCD_STARTOPT_AUTO_START 0x04所以下面的判断语句不成立,也就是没有执行zb_StartRequest();函数。if ( startOptions & ZCD_STARTOPT_AUTO_START ) 这时也就是网络没有形成,没有具体确定那个是协调器,还是作为路由器。下面就是通过应用程序的按键来确定。下面是灯设备,也就是SimpleController.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. / Key 1 starts device as a coordinator /当按下按键1时,读取配置信息,通过读取NV中的ZCD_NV_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); / Do more configuration if necessary and then restart device with auto-start bit set / write endpoint to simple desc.dont pass it in start req.then reset 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 zb_AllowBind( myAllowBindTimeout ); if ( keys & HAL_KEY_SW_2 ) if ( myAppState = APP_INIT ) / In the init state, keys are used to indicate the logical mode. / Key 2 starts device as a router zb_ReadConfiguration( ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType ); if ( logicalType != ZG_DEVICETYPE_ENDDEVICE ) logicalType = ZG_DEVICETYPE_ROUTER; 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 if ( keys & HAL_KEY_SW_3 ) if ( keys & HAL_KEY_SW_4 ) 在 ZGlobals.c文件中,我们可以找到ZCD_NV_LOGICAL_TYPE的初始值是什么?static CONST zgItem_t zgItemTable =#if defined ( NV_INIT ) ZCD_NV_LOGICAL_TYPE, sizeof(zgDeviceLogicalType), &zgDeviceLogicalType , ZCD_NV_POLL_RATE, sizeof(zgPollRate), &zgPollRate ,在这个文件中我们还可以看到下面的这句话,/ Device Logical Typeuint8 zgDeviceLogicalType = DEVICE_LOGICAL_TYPE;前面我们也有看到#if defined ( SOFT_START ) #define DEVICE_LOGICAL_TYPE ZG_DEVICETYPE_SOFT#define ZG_DEVICETYPE_SOFT 0x03 我们也可以看到在这个文件中的编译选项有NV_INIT,并且在uint8 zgInit( void )函数中,对这个结构体数组进行了初始化。也就是说最后NV中的ZCD_NV_LOGICAL_TYPE条目被初始化了ZG_DEVICETYPE_SOFT值,所以if ( logicalType != ZG_DEVICETYPE_ENDDEVICE )判断不成功,执行下面的两条语句。也就是设置设备的逻辑类型为协调器,并且写入到ZCD_NV_LOGICAL_TYPE的条目中。logicalType = ZG_DEVICETYPE_COORDINATOR;zb_WriteConfiguration(ZCD_NV_LOGICAL_TYPE, sizeof(uint8), &logicalType); 下面的语句就是语句就是写入了自动启动项,并且最后重新启动了系统。我们看一下重新启动后的流程在void SAPI_Init( byte task_id )函数中触发ZB_ENTRY_EVENT事件,进入UINT16 SAPI_ProcessEvent( byte task_id, UINT16 events )函数,对ZB_ENTRY_EVENT事件进行处理。if ( events & ZB_ENTRY_EVENT ) uint8 startOptions; / Give indication to application of device startup zb_HandleOsalEvent( ZB_ENTRY_EVENT ); / LED off cancels HOLD_AUTO_START blink set in the stack HalLedSet (HAL_LED_4, HAL_LED_MODE_OFF); zb_ReadConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions ); if ( startOptions & ZCD_STARTOPT_AUTO_START)/这时这个判断就是成立的 zb_StartRequest(); else / blink leds and wait for external input to config and restart HalLedBlink(HAL_LED_2, 0, 50, 500); return (events ZB_ENTRY_EVENT ); 判断成立的话,就会进入zb_StartRequest()函数。下面重点看一下zb_StartRequest()void zb_StartRequest() uint8 logicalType; / Start the device / start delay = min(NWK_START_DELAY, zgStartDelay) + rand() - only for fresh start, not restore if ( zgStartDelay ZG_DEVICETYPE_ENDDEVICE ) |#if defined( RTR_NWK ) #if defined( ZDO_COORDINATOR ) / Only RTR or Coord possible ( logicalType = ZG_DEVICETYPE_ENDDEVICE ) | #else / Only RTR possible ( logicalType != ZG_DEVICETYPE_ROUTER ) | #endif#else #if defined( ZDO_COORDINATOR ) / Error ( 1 ) |#else / only ED possible ( logicalType != ZG_DEVICETYPE_ENDDEVICE ) | #endif#endif ( 0 ) ) / error configuration SAPI_SendCback( SAPICB_START_CNF, ZInvalidParameter, 0 ); else ZDOInitDevice(zgStartDelay); return; 经过一系列的错误检测,可以得出上面的if分支不成立,会执行else分支也就是ZDOInitDevice(zgStartDelay);函数。这个函数,在上面的文章中也有分析到,这个函数中就分了NV_RESTORE编译选项的定义与否,由于这里没有定义这个选项,所以会直接执行ZDAppDetermineDeviceType();。uint8 ZDOInitDevice( uint16 startDelay ) uint8 networkStateNV = ZDO_INITDEV_NEW_NETWORK_STATE; uint16 extendedDelay = 0; 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 ) return ( ZDO_INITDEV_LEAVE_NOT_STARTED ); / Dont join - (one time).#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(); #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 device security ZDApp_SecInit( networkStateNV ); / Trigger the network start ZDApp_NetworkInit( extendedDelay ); return ( networkStateNV );在ZDAppDetermineDeviceType();函数中,对设备进行了判断。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; / Dont allow coord to start continueJoining = TRUE; devStartMode = MODE_JOIN; / Assume joining #endif / SOFT_START由于定义了SOFT_START编译选项,因为在按下S1按键后,把ZG_DEVICETYPE_COORDINATOR值写入了ZCD_NV_LOGICAL_TYPE条目中,在系统重新

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论