zigbee学习:示例程序SampleApp中通讯流程

zigbee学习:示例程序SampleApp中通讯流程


 

本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.


参考链接:

http://wjf88223.blog.163.com/blog/static/3516800120104711268760/

http://www.cnblogs.com/yqh2007/archive/2011/04/27/2030062.html

 

环境:

主机:WIN7

开发环境:IAR8.10.3

MCU:CC2530

示例程序:SampleApp

 

说明:

在此示例程序中,有两种通讯方式:

1.每个设备每隔5s,会发送广播信息

2.按下向上键,设备会向组1发送信息

如果按下向右键,可以加入或退出组1


代码分析:

1.在main()->osal_init_system()->osalInitTasks()中增加示例程序任务SampleApp_Init( taskID )

此函数代码:

 

void SampleApp_Init( uint8 task_id )

{

  SampleApp_TaskID = task_id;

  SampleApp_NwkState = DEV_INIT;

  SampleApp_TransID = 0;



  // Device hardware initialization can be added here or in main() (Zmain.c).

  // If the hardware is application specific - add it here.

  // If the hardware is other parts of the device add it in main().



 #if defined ( BUILD_ALL_DEVICES )

  // The "Demo" target is setup to have BUILD_ALL_DEVICES and HOLD_AUTO_START

  // We are looking at a jumper (defined in SampleAppHw.c) to be jumpered

  // together - if they are - we will start up a coordinator. Otherwise,

  // the device will start as a router.

  if ( readCoordinatorJumper() )

    zgDeviceLogicalType = ZG_DEVICETYPE_COORDINATOR;

  else

    zgDeviceLogicalType = ZG_DEVICETYPE_ROUTER;

#endif // BUILD_ALL_DEVICES



#if defined ( HOLD_AUTO_START )

  // HOLD_AUTO_START is a compile option that will surpress ZDApp

  //  from starting the device and wait for the application to

  //  start the device.

  ZDOInitDevice(0);

#endif



  // Setup for the periodic message's destination address

  // Broadcast to everyone

  SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast;

  SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;

  SampleApp_Periodic_DstAddr.addr.shortAddr = 0xFFFF;



  // Setup for the flash command's destination address - Group 1

  SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)afAddrGroup;

  SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;

  SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP;



  // Fill out the endpoint description.

  SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;

  SampleApp_epDesc.task_id = &SampleApp_TaskID;

  SampleApp_epDesc.simpleDesc

            = (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc;

  SampleApp_epDesc.latencyReq = noLatencyReqs;



  // Register the endpoint description with the AF

  afRegister( &SampleApp_epDesc );



  // Register for all key events - This app will handle all key events

  RegisterForKeys( SampleApp_TaskID );



  // By default, all devices start out in Group 1

  SampleApp_Group.ID = 0x0001;

  osal_memcpy( SampleApp_Group.name, "Group 1", 7  );

  aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group );



#if defined ( LCD_SUPPORTED )

  HalLcdWriteString( "SampleApp", HAL_LCD_LINE_1 );

#endif

}

 

 

2.任务数组tasksArr[]中增加示例程序任务:

 

// The order in this table must be identical to the task initialization calls below in osalInitTask.

const pTaskEventHandlerFn tasksArr[] = {

  macEventLoop,

  nwk_event_loop,

  Hal_ProcessEvent,

#if defined( MT_TASK )

  MT_ProcessEvent,

#endif

  APS_event_loop,

#if defined ( ZIGBEE_FRAGMENTATION )

  APSF_ProcessEvent,

#endif

  ZDApp_event_loop,

#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )

  ZDNwkMgr_event_loop,

#endif

  SampleApp_ProcessEvent

};

 

3.任务处理函数SampleApp_ProcessEvent()解析

源代码:

 

uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )

{

  afIncomingMSGPacket_t *MSGpkt;

  (void)task_id;  // Intentionally unreferenced parameter



  if ( events & SYS_EVENT_MSG )

  {

    MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );

    while ( MSGpkt )

    {

      switch ( MSGpkt->hdr.event )

      {

        // Received when a key is pressed

        case KEY_CHANGE:

          SampleApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );

          break;



        // Received when a messages is received (OTA) for this endpoint

        case AF_INCOMING_MSG_CMD:

          SampleApp_MessageMSGCB( MSGpkt );

          break;



        // Received whenever the device changes state in the network

        case ZDO_STATE_CHANGE:

          SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);

          if ( (SampleApp_NwkState == DEV_ZB_COORD)

              || (SampleApp_NwkState == DEV_ROUTER)

              || (SampleApp_NwkState == DEV_END_DEVICE) )

          {

            // Start sending the periodic message in a regular interval.

            osal_start_timerEx( SampleApp_TaskID,

                              SAMPLEAPP_SEND_PERIODIC_MSG_EVT,

                              SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );

          }

          else

          {

            // Device is no longer in the network

          }

          break;



        default:

          break;

      }



      // Release the memory

      osal_msg_deallocate( (uint8 *)MSGpkt );



      // Next - if one is available

      MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );

    }



    // return unprocessed events

    return (events ^ SYS_EVENT_MSG);

  }



  // Send a message out - This event is generated by a timer

  //  (setup in SampleApp_Init()).

  if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )

  {

    // Send the periodic message

    SampleApp_SendPeriodicMessage();



    // Setup to send message again in normal period (+ a little jitter)

    osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,

        (SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) );



    // return unprocessed events

    return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT);

  }



  // Discard unknown events

  return 0;

}

 


解析:
问:KEY_CHANGE事件如何在SampleApp_ProcessEvent()函数产生?

答:SampleApp_Init()函数注册了事件RegisterForKeys( SampleApp_TaskID );


问:AF_INCOMING_MSG_CMD事件如何在SampleApp_ProcessEvent()函数产生?

答:SampleApp_Init()函数注册了事件afRegister( &SampleApp_epDesc );

以下为系统处理来自AF层数据包的大致流程:

afIncomingData() ->afBuildMSGIncoming()->osal_msg_send() -> osal_set_event()
根据task_id调用事件处理函数SampleApp_ProcessEvent(),在此函数中判断具体事件类型再调用相应回调函数如SampleApp_MessageMSGCB()


问:ZDO_STATE_CHANGE事件如何在SampleApp_ProcessEvent()函数产生?

答:网络状态改变会引发函数ZDO_UpdateNwkStatus()的处理,此函数中产生应用任务数据

 

osal_msg_send( *(epDesc->epDesc->task_id), (byte *)msgPtr ); //发往应用任务


4.信息发送过程

 

步骤:

1).设备连接网络,网络状态改变,产生事件ZDO_STATE_CHANGE

在任务处理函数SampleApp_ProcessEvent()中产生一个定时器命令:

 

osal_start_timerEx( SampleApp_TaskID,

                              SAMPLEAPP_SEND_PERIODIC_MSG_EVT,

                              SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );


2).事件到后,发送信息,并且再度启动定时器

 

 

if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )

  {

    // Send the periodic message

    SampleApp_SendPeriodicMessage();



    // Setup to send message again in normal period (+ a little jitter)

    osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,

        (SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) );



    // return unprocessed events

    return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT);

  }


3).SampleApp_SendPeriodicMessage()函数源代码:

 

 

void SampleApp_SendPeriodicMessage( void )

{

  if ( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,

                       SAMPLEAPP_PERIODIC_CLUSTERID,

                       1,

                       (uint8*)&SampleAppPeriodicCounter,

                       &SampleApp_TransID,

                       AF_DISCV_ROUTE,

                       AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )

  {

  }

  else

  {

    // Error occurred in request to send.

  }

}


此函数调用 AF_DataRequest()函数向组1发送命令

 


5.退出和加入组1是通过RIGHT按键实现,按键处理源代码:

 

void SampleApp_HandleKeys( uint8 shift, uint8 keys )

{

  (void)shift;  // Intentionally unreferenced parameter

  

  if ( keys & HAL_KEY_SW_1 )

  {

    /* This key sends the Flash Command is sent to Group 1.

     * This device will not receive the Flash Command from this

     * device (even if it belongs to group 1).

     */

    SampleApp_SendFlashMessage( SAMPLEAPP_FLASH_DURATION );

  }



  if ( keys & HAL_KEY_SW_2 )

  {

    /* The Flashr Command is sent to Group 1.

     * This key toggles this device in and out of group 1.

     * If this device doesn't belong to group 1, this application

     * will not receive the Flash command sent to group 1.

     */

    aps_Group_t *grp;

    grp = aps_FindGroup( SAMPLEAPP_ENDPOINT, SAMPLEAPP_FLASH_GROUP );

    if ( grp )

    {

      // Remove from the group

      aps_RemoveGroup( SAMPLEAPP_ENDPOINT, SAMPLEAPP_FLASH_GROUP );

    }

    else

    {

      // Add to the flash group

      aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group );

    }

  }

}



你可能感兴趣的:(sample)