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

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

               

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

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

参考链接:

 

环境:

主机:WIN7

开发环境:IAR8.10.3

MCU:

示例程序: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 = 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 );    }  }}
           

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!

你可能感兴趣的文章
jQuery实现html网页顶部自适应导航栏(media)------Sestid
查看>>
鼠标悬停显示下划线(带小特效)------Sestid
查看>>
jQuery 实现input搜索框自动匹配------Sestid
查看>>
Js 实现回车键触发登录,并弹出需要输入信息------Sestid
查看>>
Js字符串和数组方法及使用------Sestid
查看>>
JavaScript常用算法(面试)------Sestid
查看>>
Js或者jQuery实现点击图片出现蒙层并将图片放大在蒙层上------Sestid
查看>>
Js,jQuery事件、效果大全------Sestid
查看>>
CSS块元素、内联元素、内联块元素详解------Sestid
查看>>
Js实现跟随鼠标移动的小球------Sestid
查看>>
HTML图像,链接,列表,表格等详细介绍------Sestid
查看>>
Js实现的俄罗斯方块小游戏------Sestid
查看>>
Js实现贪吃蛇小游戏------Sestid
查看>>
jQuery常用方法(持续更新)
查看>>
原生js实现自定义倒计时效果------Sestid
查看>>
原生js实现生成随机验证码=------Sestid
查看>>
js实现购物时选带属性的商品------Sestid
查看>>
点击出现对应界面(第二个界面可以选择显示内容)------Sestid
查看>>
Js实现炫酷仿抖罗盘时钟------Sestid
查看>>
vivo官网鼠标触碰图片拉长------Sestid
查看>>