对于zigbee协调器而言,ZDO zigbee设备对象层向网络层发送一个组网请求,由于zigbee协议栈是个半开源,在网络层具体代码我们是看不到的,不过在网络层,网络组建完成以后会发送一个确认给ZDO层,即ZDO层使用
ZDO_NetworkFormationConfirmCB函数来接收发来的确认信息。下面看一下具体代码:
void ZDO_NetworkFormationConfirmCB( ZStatus_t Status ) nwkStatus = (byte)Status;
if ( Status == ZSUCCESS )//网络创建成功 {
HalLedSet ( HAL_LED_3, HAL_LED_MODE_ON );//点亮LED_3 HalLedSet (HAL_LED_4, HAL_LED_MODE_OFF);//关闭LED_4 #if defined ( ZBIT )
SIM_SetColor(0xd0ffd0); #endif
if ( devState == DEV_HOLD ) {
devState = DEV_COORD_STARTING; } }
#if defined(BLINK_LEDS) else
HalLedSet ( HAL_LED_3, HAL_LED_MODE_FLASH ); // Flash LED to show failure #endif
osal_set_event( ZDAppTaskID, ZDO_NETWORK_START );//设置网络启动事件 }
继续去ZDO层,看看是怎么处理网络启动事件的,在UINT16 ZDApp_event_loop( uint8 task_id, UINT16 events )中找到:
if ( events & ZDO_NETWORK_START ) {
ZDApp_NetworkStartEvt();//网络启动函数 return (events ^ ZDO_NETWORK_START); }
继续找到网络启动函数的代码如下:
void ZDApp_NetworkStartEvt( void ) {
if ( nwkStatus == ZSuccess )//if条件成立 {
if ( devState == DEV_COORD_STARTING )//这时设备状态确实是协调器启动状态 {
devState = DEV_ZB_COORD;//修改设备状态 }
osal_pwrmgr_device( PWRMGR_ALWAYS_ON );//进行电源管理,设置一直供电状态
osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT );//设置zigbee状态改变事件 } else {
// Try again with a higher energy threshold !!
if ( ( NLME_GetEnergyThreshold() + ENERGY_SCAN_INCREMENT ) < 0xff ) {
NLME_SetEnergyThreshold( (uint8)(NLME_GetEnergyThreshold() + ENERGY_SCAN_INCREMENT) );
osal_set_event( ZDAppTaskID, ZDO_NETWORK_INIT ); } else {
// Failed to start network. Enter a dormant state (until user intervenes)
devState = DEV_INIT;
osal_set_event( ZDAppTaskID, ZDO_STATE_CHANGE_EVT ); }
} }
接下来看ZDO层怎么对状态改变时间进行处理,找到UINT16
ZDApp_event_loop( uint8 task_id, UINT16 events )函数中 如下代码:
if ( events & ZDO_STATE_CHANGE_EVT ) {
ZDO_UpdateNwkStatus( devState );//更新网络状态函数
// At start up, do one MTO route discovery if the device is a concentrator
if ( zgConcentratorEnable == TRUE ) //if不成立,先不用管 {
// Start next event
osal_start_timerEx( NWK_TaskID, NWK_MTO_RTG_REQ_EVT, 100 ); }
// Return unprocessed events
return (events ^ ZDO_STATE_CHANGE_EVT); }
接着看一下更新网络状态函数的代码:
void ZDO_UpdateNwkStatus(devStates_t state) {
epList_t *pItem = epList;//epList_t结构体中第一个数据成员便是端口描述符,最后一个成员是void类型的指针,突然想到了链表操作。。。刚查看了一下,端口描述符的数据确实使用链表的操作来存入的。
while (pItem != NULL) {
if (pItem->epDesc->endPoint != ZDO_EP) {
zdoSendStateChangeMsg(state, *(pItem->epDesc->task_id));//该函数的作用是将网络状态改变state这一消息通知给在AF层注册过的所有端点,除了端口0。 }
pItem = pItem->nextDesc; }
#if defined MT_ZDO_CB_FUNC
zdoSendStateChangeMsg(state, MT_TaskID); #endif
ZDAppNwkAddr.addr.shortAddr = NLME_GetShortAddr(); //利用网络层的API函数得到网络地址
(void)NLME_GetExtAddr(); // 得到IEEE 64位长地址。 }
好,因为我们是在sapi层注册的端口描述符,那么信息肯定是发送到sapi层,那我们就去sapi层找一下处理这个消息的代码,在sapi.c中找到如下代码:
case ZDO_STATE_CHANGE:
// If the device has started up, notify the application if (pMsg->status == DEV_END_DEVICE || pMsg->status == DEV_ROUTER ||
pMsg->status == DEV_ZB_COORD )//成立 {
SAPI_StartConfirm( ZB_SUCCESS ); //sapi层利用这一函数对ZDO状态改变事件进行响应 }
else if (pMsg->status == DEV_HOLD || pMsg->status == DEV_INIT) {
SAPI_StartConfirm( ZB_INIT ); }
break;
好,进去看看SAPI_StartConfirm( ZB_SUCCESS )函数 void SAPI_StartConfirm( uint8 status ) {
#if defined ( MT_SAPI_CB_FUNC )
if ( SAPICB_CHECK( SPI_CB_SAPI_START_CNF ) ) {
zb_MTCallbackStartConfirm( status ); } else
#endif //MT_SAPI_CB_FUNC {
#if ( SAPI_CB_FUNC ) //条件成立,执行下面语句。 zb_StartConfirm( status ); #endif } }
再次进入到zb_StartConfirm(status)函数中 void zb_StartConfirm( uint8 status ) {
// If the device sucessfully started, change state to running if ( status == ZB_SUCCESS ) {
myAppState = APP_START; //在此函数中只做了一件事就是将应用状态改为启动状态。 } else {
osal_start_timerEx( sapi_TaskID, MY_START_EVT, myStartRetryDelay ); } }
到此为止,协调期建网操作已经全部完成了~ 中间出现很多参数,有时间的话可能会再去看一下这些参数的定义,我主要是先摸清zigbee协调器建网的主要过程,接下来我可能会研究一下终端节点是怎么加入网络以及怎么实现无线数据的收发。
关于ZStack-CC2530-2.3.0-1.4.0中simpleApp例子的 终端节点入网以及绑定操作(一)