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

https://blog.csdn.net/jdh99/article/details/9203553

本文博客链接: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 )

此函数代码:

[cpp]  view plain  copy
  1. void SampleApp_Init( uint8 task_id )  
  2. {  
  3.   SampleApp_TaskID = task_id;  
  4.   SampleApp_NwkState = DEV_INIT;  
  5.   SampleApp_TransID = 0;  
  6.   
  7.   // Device hardware initialization can be added here or in main() (Zmain.c).  
  8.   // If the hardware is application specific - add it here.  
  9.   // If the hardware is other parts of the device add it in main().  
  10.   
  11.  #if defined ( BUILD_ALL_DEVICES )  
  12.   // The "Demo" target is setup to have BUILD_ALL_DEVICES and HOLD_AUTO_START  
  13.   // We are looking at a jumper (defined in SampleAppHw.c) to be jumpered  
  14.   // together - if they are - we will start up a coordinator. Otherwise,  
  15.   // the device will start as a router.  
  16.   if ( readCoordinatorJumper() )  
  17.     zgDeviceLogicalType = ZG_DEVICETYPE_COORDINATOR;  
  18.   else  
  19.     zgDeviceLogicalType = ZG_DEVICETYPE_ROUTER;  
  20. #endif // BUILD_ALL_DEVICES  
  21.   
  22. #if defined ( HOLD_AUTO_START )  
  23.   // HOLD_AUTO_START is a compile option that will surpress ZDApp  
  24.   //  from starting the device and wait for the application to  
  25.   //  start the device.  
  26.   ZDOInitDevice(0);  
  27. #endif  
  28.   
  29.   // Setup for the periodic message's destination address  
  30.   // Broadcast to everyone  
  31.   SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast;  
  32.   SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;  
  33.   SampleApp_Periodic_DstAddr.addr.shortAddr = 0xFFFF;  
  34.   
  35.   // Setup for the flash command's destination address - Group 1  
  36.   SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)afAddrGroup;  
  37.   SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT;  
  38.   SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP;  
  39.   
  40.   // Fill out the endpoint description.  
  41.   SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;  
  42.   SampleApp_epDesc.task_id = &SampleApp_TaskID;  
  43.   SampleApp_epDesc.simpleDesc  
  44.             = (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc;  
  45.   SampleApp_epDesc.latencyReq = noLatencyReqs;  
  46.   
  47.   // Register the endpoint description with the AF  
  48.   afRegister( &SampleApp_epDesc );  
  49.   
  50.   // Register for all key events - This app will handle all key events  
  51.   RegisterForKeys( SampleApp_TaskID );  
  52.   
  53.   // By default, all devices start out in Group 1  
  54.   SampleApp_Group.ID = 0x0001;  
  55.   osal_memcpy( SampleApp_Group.name, "Group 1", 7  );  
  56.   aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group );  
  57.   
  58. #if defined ( LCD_SUPPORTED )  
  59.   HalLcdWriteString( "SampleApp", HAL_LCD_LINE_1 );  
  60. #endif  
  61. }  

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

[cpp]  view plain  copy
  1. // The order in this table must be identical to the task initialization calls below in osalInitTask.  
  2. const pTaskEventHandlerFn tasksArr[] = {  
  3.   macEventLoop,  
  4.   nwk_event_loop,  
  5.   Hal_ProcessEvent,  
  6. #if defined( MT_TASK )  
  7.   MT_ProcessEvent,  
  8. #endif  
  9.   APS_event_loop,  
  10. #if defined ( ZIGBEE_FRAGMENTATION )  
  11.   APSF_ProcessEvent,  
  12. #endif  
  13.   ZDApp_event_loop,  
  14. #if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )  
  15.   ZDNwkMgr_event_loop,  
  16. #endif  
  17.   SampleApp_ProcessEvent  
  18. };  

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

源代码:

[cpp]  view plain  copy
  1. uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )  
  2. {  
  3.   afIncomingMSGPacket_t *MSGpkt;  
  4.   (void)task_id;  // Intentionally unreferenced parameter  
  5.   
  6.   if ( events & SYS_EVENT_MSG )  
  7.   {  
  8.     MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );  
  9.     while ( MSGpkt )  
  10.     {  
  11.       switch ( MSGpkt->hdr.event )  
  12.       {  
  13.         // Received when a key is pressed  
  14.         case KEY_CHANGE:  
  15.           SampleApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );  
  16.           break;  
  17.   
  18.         // Received when a messages is received (OTA) for this endpoint  
  19.         case AF_INCOMING_MSG_CMD:  
  20.           SampleApp_MessageMSGCB( MSGpkt );  
  21.           break;  
  22.   
  23.         // Received whenever the device changes state in the network  
  24.         case ZDO_STATE_CHANGE:  
  25.           SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);  
  26.           if ( (SampleApp_NwkState == DEV_ZB_COORD)  
  27.               || (SampleApp_NwkState == DEV_ROUTER)  
  28.               || (SampleApp_NwkState == DEV_END_DEVICE) )  
  29.           {  
  30.             // Start sending the periodic message in a regular interval.  
  31.             osal_start_timerEx( SampleApp_TaskID,  
  32.                               SAMPLEAPP_SEND_PERIODIC_MSG_EVT,  
  33.                               SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );  
  34.           }  
  35.           else  
  36.           {  
  37.             // Device is no longer in the network  
  38.           }  
  39.           break;  
  40.   
  41.         default:  
  42.           break;  
  43.       }  
  44.   
  45.       // Release the memory  
  46.       osal_msg_deallocate( (uint8 *)MSGpkt );  
  47.   
  48.       // Next - if one is available  
  49.       MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );  
  50.     }  
  51.   
  52.     // return unprocessed events  
  53.     return (events ^ SYS_EVENT_MSG);  
  54.   }  
  55.   
  56.   // Send a message out - This event is generated by a timer  
  57.   //  (setup in SampleApp_Init()).  
  58.   if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )  
  59.   {  
  60.     // Send the periodic message  
  61.     SampleApp_SendPeriodicMessage();  
  62.   
  63.     // Setup to send message again in normal period (+ a little jitter)  
  64.     osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,  
  65.         (SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) );  
  66.   
  67.     // return unprocessed events  
  68.     return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT);  
  69.   }  
  70.   
  71.   // Discard unknown events  
  72.   return 0;  
  73. }  


解析:
问: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()的处理,此函数中产生应用任务数据

[cpp]  view plain  copy
  1. osal_msg_send( *(epDesc->epDesc->task_id), (byte *)msgPtr ); //发往应用任务  

4.信息发送过程

步骤:

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

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

[cpp]  view plain  copy
  1. osal_start_timerEx( SampleApp_TaskID,  
  2.                               SAMPLEAPP_SEND_PERIODIC_MSG_EVT,  
  3.                               SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );  

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

[cpp]  view plain  copy
  1. if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT )  
  2.   {  
  3.     // Send the periodic message  
  4.     SampleApp_SendPeriodicMessage();  
  5.   
  6.     // Setup to send message again in normal period (+ a little jitter)  
  7.     osal_start_timerEx( SampleApp_TaskID, SAMPLEAPP_SEND_PERIODIC_MSG_EVT,  
  8.         (SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) );  
  9.   
  10.     // return unprocessed events  
  11.     return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT);  
  12.   }  

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

[cpp]  view plain  copy
  1. void SampleApp_SendPeriodicMessage( void )  
  2. {  
  3.   if ( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,  
  4.                        SAMPLEAPP_PERIODIC_CLUSTERID,  
  5.                        1,  
  6.                        (uint8*)&SampleAppPeriodicCounter,  
  7.                        &SampleApp_TransID,  
  8.                        AF_DISCV_ROUTE,  
  9.                        AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )  
  10.   {  
  11.   }  
  12.   else  
  13.   {  
  14.     // Error occurred in request to send.  
  15.   }  
  16. }  

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


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

[cpp]  view plain  copy
  1. void SampleApp_HandleKeys( uint8 shift, uint8 keys )  
  2. {  
  3.   (void)shift;  // Intentionally unreferenced parameter  
  4.     
  5.   if ( keys & HAL_KEY_SW_1 )  
  6.   {  
  7.     /* This key sends the Flash Command is sent to Group 1. 
  8.      * This device will not receive the Flash Command from this 
  9.      * device (even if it belongs to group 1). 
  10.      */  
  11.     SampleApp_SendFlashMessage( SAMPLEAPP_FLASH_DURATION );  
  12.   }  
  13.   
  14.   if ( keys & HAL_KEY_SW_2 )  
  15.   {  
  16.     /* The Flashr Command is sent to Group 1. 
  17.      * This key toggles this device in and out of group 1. 
  18.      * If this device doesn't belong to group 1, this application 
  19.      * will not receive the Flash command sent to group 1. 
  20.      */  
  21.     aps_Group_t *grp;  
  22.     grp = aps_FindGroup( SAMPLEAPP_ENDPOINT, SAMPLEAPP_FLASH_GROUP );  
  23.     if ( grp )  
  24.     {  
  25.       // Remove from the group  
  26.       aps_RemoveGroup( SAMPLEAPP_ENDPOINT, SAMPLEAPP_FLASH_GROUP );  
  27.     }  
  28.     else  
  29.     {  
  30.       // Add to the flash group  
  31.       aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group );  
  32.     }  
  33.   }  
  34. }  

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值