博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
zigbee学习:示例程序SampleApp中通讯流程
阅读量:5366 次
发布时间:2019-06-15

本文共 8148 字,大约阅读时间需要 27 分钟。

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

 

本文博客链接:,作者:jdh,转载请注明.

参考链接:

 

环境:

主机: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 );    }  }}

转载于:https://www.cnblogs.com/dyllove98/p/3165828.html

你可能感兴趣的文章
Docker 安装MySQL5.7(三)
查看>>
CSS: caption-side 属性
查看>>
CSS3中box-sizing的理解
查看>>
Web.Config文件配置之配置Session变量的生命周期
查看>>
mysql导入source注意点
查看>>
linux下编译安装nginx
查看>>
DLL 导出函数
查看>>
windows超过最大连接数解决命令
查看>>
12个大调都是什么
查看>>
angular、jquery、vue 的区别与联系
查看>>
Intellij idea创建javaWeb以及Servlet简单实现
查看>>
代理网站
查看>>
Open multiple excel files in WebBrowser, only the last one gets activated
查看>>
FFmpeg进行视频帧提取&音频重采样-Process.waitFor()引发的阻塞超时
查看>>
最近邻与K近邻算法思想
查看>>
【VS开发】ATL辅助COM组件开发
查看>>
FlatBuffers In Android
查看>>
《演说之禅》I & II 读书笔记
查看>>
thinkphp3.2接入支付宝支付接口(PC端)
查看>>
response和request
查看>>