精华内容
下载资源
问答
  • Z-Stack Developer's Guide.pdf中文版,高清PDF,带索引目录,ZigBee协议栈开发指南
  • zigbee协议栈

    2018-04-25 14:47:08
    ZigBee协议适应无线传感器的低花费、低能量、高容错性等的要求。Zigbee的基础是IEEE 802.15.4。但IEEE仅处理低级MAC层和物理层协议,因此Zigbee联盟扩展了IEEE,对其网络层协议和API进行了标准化。Zigbee是一种新兴...
  • 2.5.1a版本和3.0.2版本的Zigbee协议栈,以供学习和做相关开发的人员下载
  • 本毕业设计设计开发了一种基于CC2530 的嵌入式无线传感器网络ZigBee协议栈的多种传感器数据无线采集与控制。可应用于计算、存储等资源受限的嵌入式系统,在不同应用条件下适应多种物理层技术。由这种协议栈构造出的...
  • zigbee 协议栈 无线点灯 使用的是2.5.1的协议栈,实现了无线点灯的功能。代码内有注释。
  • TI ZigBee 最新协议栈,基于CC2530,完整支持ZigBee2007,ZigBeePro,学习ZigBee,物联网参考资源。
  • MPU6050的zigbee协议栈

    2018-06-23 16:56:17
    3. 实现了通过Z-stack协议栈,将传感器数据从终端发送到协调器(该发送方法所有传感器通用,只要你能获取你所需的传感器的数据,就可以使用我的代码进行数据的发送)。 4. 该工程可以直接使用IAR软件打开并实现仿真...
  • Zigbee 协议栈

    千次阅读 2020-05-26 13:58:39
    Zigbee 协议栈平台协议栈对我们的作用怎么使用协议栈协议栈的安装、编译与下载Components (部件)Documents (文件)Projects (项目例子)Tools (工具) 平台 协议 TI ZStack-CC2530-2.5.1a 协议栈对我们的作用 ...

    平台

    协议 TI ZStack-CC2530-2.5.1a

    协议栈对我们的作用

    协议栈是协议的实现,可以理解为代码,函数库, 供上层应用调用,协议较底下的层与应用是相互独立的。商业化的协议栈就是给你写好了底层的代码, 符合协议标准,提供给你一个功能模块给你调用你需要关心的就是你的应用逻辑,数据从哪里到哪里,怎么存储,处理;还有系统里的设备之间的通信顺序什么的,当你的应用需要数据通信时, 调用组网函数给你组建你想要的网络;当你想从一个设备发数据到另一个设备时, 调用无线数据发送函数;当然,接收端就调用接收函数;当你的设备没事干的时候,你就调用睡眠函数;要干活的时候就调用唤醒函数。所以当你做具体应用时,不需要关心协议栈是怎么写的,里面的每条代码是什么意思。除非你要做协议研究。每个厂商的协议栈有区别,也就是函数名称和参数可能有区别,这个要看具体的例子、说明文档。

    怎么使用协议栈

    举个例子,用户实现-个简单的无线数据通信时的一 般步骤:
    1、组网:调用协议栈的组网函数、加入网络函数,实现网络的建立与节点的加入。
    2、发送:发送节点调用协议栈的无线数据发送函数,实现无线数据发送。
    3、接收:接收节点调用协议栈的无线数据接收函数,实现无线数据接收。
    是不是看上去很简单啊,其实协议栈很多都封装好了,下面我们大概看看无线发送函数:

    afStatus_ t AF_ DataRequest(    afAddrType_ t *dstAddr,
    								endPointDesc_ t *srcEP,
    								uint16 cID,
    								uint16 len,
    								uint8 *buf,
    								uint8 *transID,
    								uint8 options,
    								uint8
    								radius )
    

    用户调用该函数即可实现数据的无线数据的发送,此函数中有8个参数,用户需要将每个参数的含义理解以后,才能熟练使用该函数进行无线数据通信的目的。现在只讲其中最重要的两个参数,其它参数不需要死记硬背,以后用多了自然就记住了。

    uint16 len,//发送数据的长度;
    uint8 *buf,//指向存放发送数据的缓冲区的指针。
    

    至于调用该函数后,如何初始化硬件进行数据发送等工作,用户不需要关心, ZigBee协议栈己经将所需要的工作做好了,我们只需要调用相应的API函数即可,而不必关心具体实现细节。看起来是不是很简单呢,是不是有动手试试的冲动。先别急还要先安装ZigBee协议栈才能进行开发调试呢,下面就动手安装ZigBee协议栈吧。

    协议栈的安装、编译与下载

    去TI官网下载 ZStack-CC2530-2.5.1a.exe 进行安装,路径你可以选择默认,同样你也可以选择你想要安装的位置。也许有人就困惑了,装完之后不是应该有个桌面图标的么?其实所谓的安装协议栈只是把一些文件解压到你安装的目录下。
    在这里插入图片描述

    Components (部件)

    顾名思义这个是放我们的库的文件夹,里面放了一些我们用到的ZDO,driver , hal , zcl等库的代码

    Documents (文件)

    这个不用说大家都知道是放TI的开发文档的,里面很多都是讲述协议栈的API的有空时可以看看

    Projects (项目例子)

    这个文件夹放的是TI协议栈的例子程序,一个个例子程序都是以一个个project的形式给我们的,学好这些例子程序里面的一两个,基本你能做事情了。

    Tools (工具)

    这个文件夹是放T|的例子程序的一些上位机之类的程序,作为工具使用。

    用IAR打开 \ZStack-2.5.1a\Projects\zstack\Samples\SampleApp\CC2530DB\SampleApp.eww
    在这里插入图片描述

    App 应用层目录

    这是用户创建各种不同工程的区域,在这个目录中包含了应用层的内容和这个项目的主要内容。

    HAL :硬件层目录

    包含有与硬件相
    关的配置和驱动及操作函数。

    MAC:MAC层目录

    包含了MAC层的参数配置文件及其MAC的LIB库的函数接口文件。

    MT

    实现通过串口可控制各层并与各层进行直接交互

    NWK :网络层目录

    包含网络层配置参数文件网络层库的函数接口文件及

    APS层库的函数接口。

    OSAL :协议栈的操作系统。

    Profile : Application framework

    应用框架层目录包含AF层处理函数文件。应用框架层是应用程序和APS层的无线数据接口。

    Security:安全层目录

    包含安全层处理函数.比如加密函数等

    Services :地址处理函数目录

    包括地址模式的定义及地址处理函数。

    Tools :工程配置目录

    包括空间划分及Z-Stack相关配置信息。

    ZDO : ZDO目录

    ZMac: MAC层目录

    包括MAC层参数配置及MAC层LB库函数回调处理函数.

    ZMain:主函数目录

    包括入口函数及硬件配置文件。

    Output :输出文件目录

    由IAR IDE自动生成。

    协议栈应用开发相关函数

    OSAL(Operating System Abstraction Layer)

    中文解释操作系统抽象层。它可以看做是一种机制,一种任务分配资源的机制,从而形成 了一个简单多任务的操作系统。

    int main( void )

    在ZMain.c

    /*********************************************************************
     * @fn      main
     * @brief   First function called after startup.
     * @return  don't care
     */
    int main( void )
    {
      // Turn off interrupts //关闭所有中断
      osal_int_disable( INTS_ALL );
    
      // Initialization for board related stuff such as LEDs //初始化系统时钟
      HAL_BOARD_INIT();
    
      // Make sure supply voltage is high enough to run //检查芯片电压是否正常
      zmain_vdd_check();
    
      // Initialize board I/O //初始化IO , LED、Timer 等
      InitBoard( OB_COLD );
    
      // Initialze HAL drivers //初始化芯片各硬件模块
      HalDriverInit();
    
      // Initialize NV System//初始化Flash存储器
      osal_nv_init( NULL );
    
    
    
    
    
      // Initialize the MAC //初始化MAC层
      ZMacInit();
    
      // Determine the extended address //确定IEEE 64位地址
      zmain_ext_addr();
    
    #if defined ZCL_KEY_ESTABLISH
      // Initialize the Certicom certificate information.
      zmain_cert_init();
    #endif
    
      // Initialize basic NV items//初始化非易失变量
      zgInit();
    
    #ifndef NONWK
      // Since the AF isn't a task, call it's initialization routine
      afInit();
    #endif
    
    
    
    
    
      // Initialize the operating system//初始化操作系统
      osal_init_system();
    
      // Allow interrupts//使能全部中断
      osal_int_enable( INTS_ALL );
    
      // Final board initialization//最终板载初始化
      InitBoard( OB_READY );
    
      // Display information about this device//显示设备信息
      zmain_dev_info();
    
      /* Display the device info on the LCD */
    #ifdef LCD_SUPPORTED
      zmain_lcd_init(); //初始化LCD
    #endif
    
    #ifdef WDT_IN_PM1
      /* If WDT is used, this is a good place to enable it. */
      WatchDogEnable( WDTIMX );
    #endif
    
      osal_start_system(); // No Return from here//执行操作系统
    
    
      return 0;  // Shouldn't get here.
    } // main()
    

    osal_init_system()

    右键 go to definition of…

    /*********************************************************************
     * @fn      osal_init_system
     *
     * @brief
     *
     *   This function initializes the "task" system by creating the
     *   tasks defined in the task table (OSAL_Tasks.h).
     *
     * @param   void
     *
     * @return  SUCCESS
     */
    uint8 osal_init_system( void )
    {
      // Initialize the Memory Allocation System
      osal_mem_init();
    
      // Initialize the message queue
      osal_qHead = NULL;
    
      // Initialize the timers
      osalTimerInit();
    
      // Initialize the Power Management System
      osal_pwrmgr_init();
    
      // Initialize the system tasks.
      osalInitTasks();
    
      // Setup efficient search for the first free block of heap.
      osal_mem_kick();
    
      return ( SUCCESS );
    }
    

    osalInitTasks()

    // 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_ProcessEventa
    };
    
    const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] );
    uint16 *tasksEvents;
    
    /*********************************************************************
     * FUNCTIONS
     *********************************************************************/
    
    /*********************************************************************
     * @fn      osalInitTasks
     *
     * @brief   This function invokes the initialization function for each task.
     *
     * @param   void
     *
     * @return  none
     */
    void osalInitTasks( void )  //任务初始化函数在OSAL. SampleApp.c文件中
    
    {
      uint8 taskID = 0;
    
      // 分配内存,返回指向缓冲区的指针
      tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
      // 设置所分配的内存空间单元值为0
      osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));
    
      // 任务优先级由高向低依次排列,高优先级对应taskID 的值反而小
      macTaskInit( taskID++ );  //macTaskInit(0) ,用户不需考虑
      nwk_init( taskID++ );     //nwk_init(1),用户不需考虑
      Hal_Init( taskID++ );     //Hal_Init(2) ,用户需考虑
    #if defined( MT_TASK )
      MT_TaskInit( taskID++ );
    #endif
      APS_Init( taskID++ );      //APS_Init(3) ,用户不需考虑
    #if defined ( ZIGBEE_FRAGMENTATION )
      APSF_Init( taskID++ );
    #endif
      ZDApp_Init( taskID++ );    //ZDApp_Init(4) ,用户需考虑
    #if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
      ZDNwkMgr_Init( taskID++ );
    #endif
    
    ///************************************关键函数
      //用户创建的任务
      SampleApp_Init( taskID );  // SampleApp_Init _Init(5) ,用户需考虑
    ///************************************
    
    
    }
    

    SampleApp_ Init()是我们应用协议栈例程的必要函数,用户通常在这里初始化自己的
    东西。

    osal_start_system()

    /*********************************************************************
     * @fn      osal_start_system
     *
     * @brief
     *
     *   This function is the main loop function of the task system (if
     *   ZBIT and UBIT are not defined). This Function doesn't return.
     *
     * @param   void
     *
     * @return  none
     */
    void osal_start_system( void )
    {
    #if !defined ( ZBIT ) && !defined ( UBIT )
      for(;;)  // Forever Loop
    #endif
      {
        osal_run_system();
      }
    }
    

    osal_run_system();

    /*********************************************************************
     * @fn      osal_run_system
     *
     * @brief
     *
     *   This function will make one pass through the OSAL taskEvents table
     *   and call the task_event_processor() function for the first task that
     *   is found with at least one event pending. If there are no pending
     *   events (all tasks), this function puts the processor into Sleep.
     *
     * @param   void
     *
     * @return  none
     */
    void osal_run_system( void )
    {
      uint8 idx = 0;
    
      osalTimeUpdate(); //扫描哪个事件被触发了,然后置相应的标志位
      Hal_ProcessPoll(); //轮询TIMER与UART
    
    /*A do statement executes a statement one or more times, while its test-context expression has a **nonzero** value:
    
        do
            statement
            while (test);
    */
    
      //得到待处理的最高优先级任务索引1号idx
      do {
        if (tasksEvents[idx])  // Task is highest priority that is ready.
        {
          break;
        }
      } while (++idx < tasksCnt);
    
      if (idx < tasksCnt)
      {
        uint16 events;
        halIntState_t intState;
    
        HAL_ENTER_CRITICAL_SECTION(intState);// 进入临界区,保护
        events = tasksEvents[idx];//提取需要处理的任务中的事件
        tasksEvents[idx] = 0;  // Clear the Events for this task.tasksEvents[idx] = 0; //清除本次任务的事件
        HAL_EXIT_CRITICAL_SECTION(intState);
    
        activeTaskID = idx;
        events = (tasksArr[idx])( idx, events );//通过指针调用任务处理函数,关键
        activeTaskID = TASK_NO_TASK;
    
        HAL_ENTER_CRITICAL_SECTION(intState);
        tasksEvents[idx] |= events;  // Add back unprocessed events to the current task.//保存未处理的事件
    
        HAL_EXIT_CRITICAL_SECTION(intState);//退出临界区
    
      }
    #if defined( POWER_SAVING )
      else  // Complete pass through all task events with no activity?
      {
        osal_pwrmgr_powerconserve();  // Put the processor/system into sleep
      }
    #endif
    
      /* Yield in case cooperative scheduling is being used. */
    #if defined (configUSE_PREEMPTION) && (configUSE_PREEMPTION == 0)
      {
        osal_task_yield();
      }
    #endif
    }
    

    SampleApp_ Init()

    用户应用任务初始化函数

    /*********************************************************************
     * @fn      SampleApp_Init
     *
     * @brief   Initialization function for the Generic App Task.
     *          This is called during initialization and should contain
     *          any application specific initialization (ie. hardware
     *          initialization/setup, table initialization, power up
     *          notificaiton ... ).
     *
     * @param   task_id - the ID assigned by OSAL.  This ID should be
     *                    used to send messages and set timers.
     *
     * @return  none
     */
    void SampleApp_Init( uint8 task_id )
    { 
      SampleApp_TaskID = task_id;   //osal分配的任务ID随着用户添加任务的增多而改变
      SampleApp_NwkState = DEV_INIT;//设备状态设定为ZDO层中定义的初始化状态
    	/*设备状态设定为ZDO层中定义的初始化状态
    	初始化应用设备的网络类型, 设备类型的改变都要产生一个事件一_ZDO_ STATE_ CHANGE ,
    	从字面理解为ZDO状态发生了改变。所以在设备初始化的时候一定要把它初始化为什么状
    	态都没有。那么它就要去检测整个环境,看是否能重新建立或者加入存在的网络。但是有一
    	种情况例外,就是当NV_ RESTORE被设置的候( NV_ RESTORE是把信息保存在非易失存
    	储器中),那么当设备断电或者某种意外重启时,由于网络状态存储在非易失存储器中,那
    	么此时就只需要恢复其网络状态,而不需要重新建立或者加入网络了.这里需要设置
    	NV RESTORE宏定义。*/
    
      SampleApp_TransID = 0;        //消息发送ID(多消息时有顺序之分)
      
      // 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
    
    //该段的意思是,如果设置了HOLD_AUTO_START宏定义,将会在启动芯片的时候会暂停启动
    //流程,只有外部触发以后才会启动芯片。其实就是需要一个按钮触发它的启动流程。  
    #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;//组号0x0001
    
      // Fill out the endpoint description. 定义本设备用来通信的APS层端点描述符
      SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT; //指定端点号
      SampleApp_epDesc.task_id = &SampleApp_TaskID;   //SampleApp 描述符的任务ID
      SampleApp_epDesc.simpleDesc
                = (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc;//SampleApp简单描述符
      SampleApp_epDesc.latencyReq = noLatencyReqs;    //延时策略
    /*向AF层登记描述符,登记endpoint description 到AF,要对该应用进行初始化并在AF
    //进行登记,告诉应用层有这么一个EP已经开通可以使用,那么下层要是有关于该应用的信
    //息或者应用要对下层做哪些操作,就自动得到下层的配合*/
    
      // Register the endpoint description with the AF
      afRegister( &SampleApp_epDesc );    //向AF层登记描述符
    
      // 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 );//把该组登记添加到APS中
    
    #if defined ( LCD_SUPPORTED )
      HalLcdWriteString( "SampleApp", HAL_LCD_LINE_1 ); //如果支持LCD,显示提示信息
    #endif
    }
    

    SampleApp_ ProcessEvent()

    用户应用任务的事件处理函数

    /*********************************************************************
     * @fn      SampleApp_ProcessEvent
     *
     * @brief   Generic Application Task event processor.  This function
     *          is called to process all events for the task.  Events
     *          include timers, messages and any other user defined events.
     *
     * @param   task_id  - The OSAL assigned task ID.
     * @param   events - events to process.  This is a bit map and can
     *                   contain more than one event.
     *
     * @return  none
     */
    //用户应用任务的事件处理函数
    uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
    {
      afIncomingMSGPacket_t *MSGpkt;
      (void)task_id;  // Intentionally unreferenced parameter
    
      if ( events & SYS_EVENT_MSG ) //接收系统消息再进行判断
      {
        //接收属于本应用任务SampleApp的消息,以SampleApp_TaskID标记
        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://接收数据事件,调用函数AF_DataRequest()接收数据
              SampleApp_MessageMSGCB( MSGpkt );//调用回调函数对收到的数据进行处理
              break;
    
            // Received whenever the device changes state in the network
            case ZDO_STATE_CHANGE:
              //只要网络状态发生改变,就通过ZDO_STATE_CHANGE事件通知所有的任务。
              //同时完成对协调器,路由器,终端的设置
              SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
              //if ( (SampleApp_NwkState == DEV_ZB_COORD)//实验中协调器只接收数据所以取消发送事件
              if ( (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 指针指向下一个放在缓冲区的待处理的事件,
          //返回while ( MSGpkt )重新处理事件,直到缓冲区没有等待处理事件为止
          MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
        }
    
        // return unprocessed events 返回未处理的事件
        return (events ^ SYS_EVENT_MSG);
      }
    
    /*********************************************************************
     * @fn      SampleApp_ProcessEvent
     *
     * @brief   Generic Application Task event processor.  This function
     *          is called to process all events for the task.  Events
     *          include timers, messages and any other user defined events.
     *
     * @param   task_id  - The OSAL assigned task ID.
     * @param   events - events to process.  This is a bit map and can
     *                   contain more than one event.
     *
     * @return  none
     */
    //用户应用任务的事件处理函数
    uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
    {
      afIncomingMSGPacket_t *MSGpkt;
      (void)task_id;  // Intentionally unreferenced parameter
    
      if ( events & SYS_EVENT_MSG ) //接收系统消息再进行判断
      {
        //接收属于本应用任务SampleApp的消息,以SampleApp_TaskID标记
        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://接收数据事件,调用函数AF_DataRequest()接收数据
              SampleApp_MessageMSGCB( MSGpkt );//调用回调函数对收到的数据进行处理
              break;
    
            // Received whenever the device changes state in the network
            case ZDO_STATE_CHANGE:
              //只要网络状态发生改变,就通过ZDO_STATE_CHANGE事件通知所有的任务。
              //同时完成对协调器,路由器,终端的设置
              SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);
              //if ( (SampleApp_NwkState == DEV_ZB_COORD)//实验中协调器只接收数据所以取消发送事件
              if ( (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 指针指向下一个放在缓冲区的待处理的事件,
          //返回while ( MSGpkt )重新处理事件,直到缓冲区没有等待处理事件为止
          MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );
        }
    
        // return unprocessed events 返回未处理的事件
        return (events ^ SYS_EVENT_MSG);
      }
    

    void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )

    /*********************************************************************
     * LOCAL FUNCTIONS
     */
    
    /*********************************************************************
     * @fn      SampleApp_MessageMSGCB
     *
     * @brief   Data message processor callback.  This function processes
     *          any incoming data - probably from other devices.  So, based
     *          on cluster ID, perform the intended action.
     *
     * @param   none
     *
     * @return  none
     */
    //接收数据,参数为接收到的数据
    void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
    {
      uint16 flashTime;
      byte buf[3]; 
    
      switch ( pkt->clusterId ) //判断簇ID
      {
        case SAMPLEAPP_PERIODIC_CLUSTERID: //收到广播数据
          osal_memset(buf, 0 , 3);
          osal_memcpy(buf, pkt->cmd.Data, 2); //复制数据到缓冲区中
          
          if(buf[0]=='D' && buf[1]=='1')      //判断收到的数据是否为"D1"         
          {
              HalLedBlink(HAL_LED_1, 0, 50, 500);//如果是则Led1间隔500ms闪烁
    #if defined(ZDO_COORDINATOR) //协调器收到"D1"后,返回"D1"给终端,让终端Led1也闪烁
              SampleApp_SendPeriodicMessage();
    #endif
          }
          else
          {
              HalLedSet(HAL_LED_1, HAL_LED_MODE_ON);                   
          }
          break;
    
        case SAMPLEAPP_FLASH_CLUSTERID: //收到组播数据
          flashTime = BUILD_UINT16(pkt->cmd.Data[1], pkt->cmd.Data[2] );
          HalLedBlink( HAL_LED_4, 4, 50, (flashTime / 4) );
          break;
      }
    }
    

    void SampleApp_SendPeriodicMessage( void )

    分析发送周期信息

    void SampleApp_SendPeriodicMessage( void )
    {
      byte SendData[3]="D1";
    
      // 调用AF_DataRequest将数据无线广播出去
      if( AF_DataRequest( &SampleApp_Periodic_DstAddr,//发送目的地址+端点地址和传送模式
                           &SampleApp_epDesc,//源(答复或确认)终端的描述(比如操作系统中任务ID等)源EP
                           SAMPLEAPP_PERIODIC_CLUSTERID, //被Profile指定的有效的集群号
                           2,       // 发送数据长度
                           SendData,// 发送数据缓冲区
                           &SampleApp_TransID,     // 任务ID号
                           AF_DISCV_ROUTE,      // 有效位掩码的发送选项
                           AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )  //传送跳数,通常设置为AF_DEFAULT_RADIUS
      {
      }
      else
      {
        HalLedSet(HAL_LED_1, HAL_LED_MODE_ON);
        // Error occurred in request to send.
      }
    }
    

    void SampleApp_SendFlashMessage( uint16 flashTime )

    /*********************************************************************
     * @fn      SampleApp_SendFlashMessage
     *
     * @brief   Send the flash message to group 1.
     *
     * @param   flashTime - in milliseconds
     *
     * @return  none
     */
    void SampleApp_SendFlashMessage( uint16 flashTime ) //此实验没有用到,后面再分析
    {
      uint8 buffer[3];
      buffer[0] = (uint8)(SampleAppFlashCounter++);
      buffer[1] = LO_UINT16( flashTime );
      buffer[2] = HI_UINT16( flashTime );
    
      if ( AF_DataRequest( &SampleApp_Flash_DstAddr, &SampleApp_epDesc,
                           SAMPLEAPP_FLASH_CLUSTERID,
                           3,
                           buffer,
                           &SampleApp_TransID,
                           AF_DISCV_ROUTE,
                           AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
      {
      }
      else
      {
        // Error occurred in request to send.
      }
    }
    
    

    AF_DataRequest()

    /*********************************************************************
     * @fn      AF_DataRequest
     *
     * @brief   Common functionality for invoking APSDE_DataReq() for both
     *          SendMulti and MSG-Send.
     *
     * input parameters
     *
     * @param  *dstAddr - Full ZB destination address: Nwk Addr + End Point.
     * @param  *srcEP - Origination (i.e. respond to or ack to) End Point Descr.
     * @param   cID - A valid cluster ID as specified by the Profile.
     * @param   len - Number of bytes of data pointed to by next param.
     * @param  *buf - A pointer to the data bytes to send.
     * @param  *transID - A pointer to a byte which can be modified and which will
     *                    be used as the transaction sequence number of the msg.
     * @param   options - Valid bit mask of Tx options.
     * @param   radius - Normally set to AF_DEFAULT_RADIUS.
     *
     * output parameters
     *
     * @param  *transID - Incremented by one if the return value is success.
     *
     * @return  afStatus_t - See previous definition of afStatus_... types.
     */
    uint8 AF_DataRequestDiscoverRoute = TRUE;
    afStatus_t AF_DataRequest( afAddrType_t *dstAddr, endPointDesc_t *srcEP,
                               uint16 cID, uint16 len, uint8 *buf, uint8 *transID,
                               uint8 options, uint8 radius )
    

    东西很多,慢慢来吧

    展开全文
  • Zigbee 协议栈 2.4.0

    2018-10-16 10:30:44
    zigbee协议栈源码.版本2.4.0.解压后生成 exe文件,直接安装即可使用. 是从官网直接下载的协议栈源码,练习zigbee必不可少的工具.分析源码对后续开发非常有用
  • zigbee协议栈生成hex文件后无法下载,下载提示失败,如何解决,请看文档
  • ZIGBEE协议栈的串口实现,接收发送,有说明
  • ZigBee 堆栈是在IEEE 802.15.4 标准基础上建立的,定义了协议的MAC 和PHY 层。 ZigBee 设备应该包括IEEE802.15.4(该标准定义了RF 射频以及与相邻设备之间的通信)的 PHY 和MAC 层,以及ZigBee 堆栈层:网络层(NWK)、...
  • zigbee协议栈源码

    2018-04-26 20:43:35
    zigbee协议栈源码。目标平台: iar51_cc2430。ZigBee是基于IEEE802.15.4标准的低功耗局域网协议。根据国际标准规定,ZigBee技术是一种短距离、低功耗的无线通信技术。
  • 基于ZigBee协议栈的无线传感器网络性能分析,彭超,刘玉英,无线传感器网络由一个协调器、数个路由器和多个终端节点组成。本文采用主动测量与被动测量的方法来实现对无线传感器网络性能的分
  • 1. 什么是Zigbee协议栈 ? 什么是 ZigBee 协议栈呢?它和 ZigBee 协议有什么关系呢?协议是一系列的通信标准,通信双方 需要共同按照这一标准进行正常的数据发射和接收。协议 栈是协议的具体实现形式,通俗 点来理解...

    1. 什么是Zigbee协议栈 ?

    什么是 ZigBee 协议栈呢?它和 ZigBee 协议有什么关系呢?协议是一系列的通信标准,通信双方 需要共同按照这一标准进行正常的数据发射和接收。协议 栈是协议的具体实现形式,通俗
    点来理解就 是协议栈是协议和用户之间的一个接口,开发人员通过使用协议栈来使用这个协议的,进而实现无线 数据收发。

    ZigBee 的协议分为两部分,IEEE 802.15.4定义了 PHY(物理层)和 MAC(介质访问层)技术规范;ZigBee 联盟定义了 NW K(网络
    层)、APS(应 用程序支持子层)、APL(应 用层)技术规范。ZigBee 协议栈就是将各个层定义的协议都集合在一直, 以函数的形式实现,并给用户提供 API(应用层),用户可以直接调用。
     

    2. 如何使用 ZigBee 协议栈?
    协议栈是协议的实现,可以理解为代码,函数库,供上层应 用调用,协议较底下的层与应用是相互独 立的。商业化的协议栈就是给你写好了底层的代码,符合协议标准,提供给你一个功能
    模块 给你调用。你需要关心的就是你的应用逻辑,数 据从哪里到哪里,怎么存储,处理;还有系 统里的设 备之间的通信顺序什么的,当你的应用 需要数据通信时,调用组网函数给你组建你
    想要的网络;当你 想从一个设备发数据到另一个设备时,调用无线数据发送函数;当然,接收端就调用接收函数;当你 的设备没事干的时候 ,你就调用睡眠函数;要干活的时候就调用唤醒函数。

    所以当你做具体应用时, 不需要关心 协议栈是怎么写的,里面的每条代码是什么 意思。除非你要做协议研究。每个厂商的协议 栈有区别,也就是函数名称和参数可能有区别,这个要看具体的例子、说明文档。

    3.ZigBee 协议栈的安装、编译与下载

    首先去TI的官网http://www.ti.com下载我们要用的zstack协议栈的安装文件,就是一个.exe文件。 下载完成之后,解压得到.exe文件,进行安装,路径你可以选择默认,同样你也可以选择你想要安装的位置。

    其实所谓的安装协议栈 只是把一些文件解压到你安装的目录下。

    Components,顾名思义这个是放我们的库的文件夹,里面放了一些我们用到的 ZDO,driver,hal, zcl 等库的代码
    Documents,是放 TI 的开发文档的,里面很多都是讲述协议栈的 API 的
    Projects,这个文件夹放的是 TI 协议栈的例子程序,一个个例子程序都是以一个个 project 的 形式给我们的,学好这些例子程序里面的一两个,基本你能做事情了。
    Tools,这个文件夹是放 TI 的例子程序的一些上位机之类的程序,作为工具使用。

    Components文件夹:

    hal是硬件层面上的一些driver等等。

    mac,zmac是mac层的协议接口。

     mt中你要用到的API几乎都可以在这里找到例子。

    osal这个就是TI的Zstack协议栈的操作系统,是事件驱动的。

    stack是一些zdo和zcl的东西。

     

    展开全文
  • Microchip zigbee 协议栈

    2018-02-06 10:57:58
    Microchip zigbee 协议栈 v1.0-3.8 包括协调节点,终端节点和路由器节点
  • Zigbee协议栈工作流程和无线收发控制LED,能测试Zigbee传输距离
  • 各位同学,学习Zigbee无线通信曾无数次放弃,看不懂英文的API文档,本人用翻译软件简单将协议栈的所有文档翻译成PDF 在翻译过程中,没有太多精力去纠结那些(司机)和(驱动)的错误。还有直译过程中,将某些代码...
  • ZIGBEE官方协议栈,亲测可用。 1 ZigBee 3.0覆盖了最广泛的设备类型,包括家庭自动化、照明、能源管理、智能家电、安全装置,传感器和医疗保健监控产品。它同时支持易于使用的DIY设备以及专业安装系统。基于IEEE 802...
  • 1、Zigbee协议栈简介 协议是一系列的通信标准,通信双方需要按照这一标准进行正常的数据发射和接收。协议栈是协议的具体实现形式,通俗讲协议栈就是协议和用户之间的一个接口,开发人员通过使用协议栈来使用这个...

    1、Zigbee协议栈简介

      协议是一系列的通信标准,通信双方需要按照这一标准进行正常的数据发射和接收。协议栈是协议的具体实现形式,通俗讲协议栈就是协议和用户之间的一个接口,开发人员通过使用协议栈来使用这个协议,进而实现无线数据收发。

      如图1所示:Zigbee协议分为两部分,IEEE 802.15.4定义了PHY(物理层)和MAC(介质访问层)技术规范;Zigbee联盟定义了NWK(网络层)、APS(应用程序支持层)、APL(应用层)技术规范。Zigbee协议栈就是将各个层定义的协议都集合在一起,以函数的形式实现,并给用户提供API(应用层),用户可以直接调用。

                图1 ZigBee无线网络协议层的架构图

     2、如何理解Zigbee协议栈

      协议栈是协议的实现,可以理解为代码,库函数,供上层应用调用,协议较底下的层与应用是相互独立的。商业化的协议栈只提供你接口(其实和互联网行业的API模式很像)。就像你调用地图API时不需要关心底层地图是怎么根据位置或坐标绘制的,你也不用关心协议栈底层的实现,除非你想做协议研究。每个厂家的协议栈是有区别的,比如TI的BLE协议栈和nordic的BLE协议栈就有很大的不同(多说一点,TI的BLE协议栈更像是安卓的BLE结构,所以会安卓蓝牙的人可能能看懂TI的代码)。

     3、如何使用Zigbee协议栈

      以简单的无线数据通信为例,其一般步骤为:

    ① 组网:调用协议栈组网函数、加入网络函数,实现网络的建立和节点的加入

    ② 发送:发送节点调用协议栈的发送函数,实现数据无线发送

    ③ 接收:接收节点调用协议栈的无线接收函数,实现无线数据接收

      由于协议栈都把这些函数都封装好了,因此我们用起来比较方便。下面是协议栈无线发送函数:

      如果想更好的应用协议栈就需要对协议栈提供的这些函数及其参数的具体作用和意义进行细致的了解,这个在接下来中会详细介绍。

     4、安装Zigbee协议栈

      从我百度共享的所有本系列资料中下载004解压并安装:

                   图2 ZigBee协议栈下载路径

     安装好之后在win7开始按钮下会有如下文件结构:

                      图3 ZigBee协议安装完成后的文件结构

      其中:

     5、基于协议栈的无线收发控制LED工程讲解(一)

      从网盘下载ZStack-2.3.1a压缩文件:

                                 图4 工程源码所在云盘目录

        用IAR打开.. \ZStack-2.5.1a\Projects\zstack\Samples\SampleApp\CC2530DB目录下的工程文件,注意不要把001Stack-2.5.1a放在比较深的文件夹内,否则IAR打开工程时可能一直卡打不开,也最好不要有中文!打开后工程及结构如下:(有点眼花缭乱,不要紧,后面会结合源码一步步分析)

                      图5 工程整体架构

     6、基于协议栈的无线收发控制LED工程讲解(二)

      在IAR中选择XXXXEB,第一遍要rebuild all,下载好协调器之后,再切换到EndDeviceEB编译下载到另一个板子做终端设备

              图6 编译工程

     

    两个节点程序下载好之后上电会看到:组网成功后D1闪烁。

                    图7 实验现象

     

    7、基于协议栈的无线收发控制LED工程讲解(三)

    main code:

    复制代码
     1 int main( void )
     2 {
     3     osal_int_disable( INTS_ALL );// Turn off interrupts         关中断
     4     HAL_BOARD_INIT();// Initialization for board related stuff such as LEDs
     5     zmain_vdd_check();// Make sure supply voltage is high enough to run   检查芯片是否上电正常
     6     InitBoard( OB_COLD );// Initialize board I/O  初始化I/O,LED,Timer等
     7     HalDriverInit();// Initialze HAL drivers 初始化硬件抽象层驱动模块
     8     osal_nv_init( NULL );// Initialize NV System 初始化flash存储器
     9     znpTestRF();// Initialize and check the ZNP RF Test Mode NV items. 
    10     ZMacInit();// Initialize the MAC  初始化MAC层
    11     zmain_ext_addr();// Determine the extended address  确定IEEE64位地址
    12 
    13 #if defined ZCL_KEY_ESTABLISH
    14     zmain_cert_init();// Initialize the Certicom certificate information.
    15 #endif
    16 
    17     zgInit();// Initialize basic NV items  初始化非易失变量
    18 
    19 #ifndef NONWK
    20     afInit();// Since the AF isn't a task, call it's initialization routine
    21 #endif
    22 
    23     osal_init_system();// Initialize the operating system     初始化OS(重点介绍1)
    24     osal_int_enable( INTS_ALL );// Allow interrupts       使能中断
    25     InitBoard( OB_READY );// Final board initialization      最终板载初始化
    26     zmain_dev_info();// Display information about this device     显示设备信息(这里有LCD屏幕)
    27 
    28 #ifdef LCD_SUPPORTED/* Display the device info on the LCD 将信息显示在LCD上*/
    29     zmain_lcd_init();      
    30 #endif
    31 
    32 #ifdef WDT_IN_PM1
    33     WatchDogEnable( WDTIMX );/* If WDT is used, this is a good place to enable it. */
    34 #endif
    35 
    36     osal_start_znp(); // No Return from here    执行操作系统(重点介绍2)
    37 
    38     return 0;  // Shouldn't get here.
    39 } // main()
    复制代码

    代码有点难懂,核心是执行初始化工作,包括硬件抽象层、网络层、任务等。然后执行osal_start_znp() ,进入一个死循环,不断对任务进行遍历执行。这里我们需要重点了解两个函数:

     

     ① 操作系统初始化函数

    在操作系统初始化中需重点关注的是操作系统任务初始化osalInitTasks函数,操作系统初始化函数中主要来创建任务taskID任务ID,每增加一个任务ID++,同时ID越小表示该任务优先级越高!其中蓝框内的函数是要根据系统想完成的任务做修改的地方,其他都是官方提供的基本不用变的任务。

     ② 操作系统启动函数

     

    执行OS的函数就是个大循环,不断取出当前优先级最高的待处理事件进行处理,处理的核心思想在osal_run_task函数内:通过调用一个函数指针来远程调用一个事件处理函数

     

    8、小结

      至此,我们讲到任务如何建立、如何处理等,其中有一个环节没有讲——如何从events=(tasksArr[idx])(idx,event)关联到每个具体任务的事件处理函数的?这个其实我在CC2540/CC2541的前两篇中已有详细介绍:[接下来会针对具体通信梳理流程!]

    1、CC2541蓝牙4.0芯片中级教程——基于OSAL操作系统的运行流程了解+定时器和串口例程了解

    2、CC2541芯片中级教程-OSAL操作系统(进一步了解-OLED && 普通按键和5方向按键-中断!!!)这个系统驱动层和应用层不一样~

    3、CC2541芯片中级教程-OSAL操作系统(ADC光敏电阻和修改串口波特率)

    4、CC2541芯片中级教程-OSAL操作系统(简单AT指令实现+IIC软件和硬件实现驱动MPU6050)

    5、CC2541芯片中级教程-OSAL操作系统(PWM+看门狗)

    展开全文
  • Zigbee协议栈

    2018-04-26 21:04:11
    Zigbee协议栈,歪果仁弄的,有点久了:A Zigbee-subset/IEEE 802.15.4 Multi-platform Protocol Stack implementation of a Zigbee-subset/IEEE 802.15.4 wireless stack, named MSSTATE_LRWPAN. Version 0.1 of ...
  • 一.ZigBee 协议栈简介 什么是ZigBee 协议栈呢?它和ZigBee 协议有什么关系呢?协议是一系列的通信标准,通信双方需要共同按照这一标准进行正常的数据发射和接收。协议栈是协议的具体实现形式,通俗点来理解就是协议栈...

    一.ZigBee 协议栈简介

    有问题发送邮件至468078841@qq.com
    什么是ZigBee 协议栈呢?它和ZigBee 协议有什么关系呢?协议是一系列的通信标准,通信双方需要共同按照这一标准进行正常的数据发射和接收。协议栈是协议的具体实现形式,通俗点来理解就是协议栈是协议和用户之间的一个接口,开发人员通过使用协议栈来使用个协议的,进而实现无线数据收发。

    ZigBee 的协议分为两部分,IEEE 802.15.4 定义了PHY(物理层)和MAC(介质访问层)技术规范;ZigBee 联盟定义了NWK(网络层)、APS(应用程序支持子层)、APL(应用层)技术规范。ZigBee 协议栈就是将各个层定义的协议都集合在一直,以函数的形式实现,并给用户提供API(应用层),用户可以直接调用。

    							 					Z-Stack协议栈体系结构								
    

    在这里插入图片描述

    二.如何使用ZigBee 协议栈

    协议栈是协议的实现,可以理解为代码,函数库,供上层应用调用,协议较底下的层与应用是相互独立的。你需要关心的就是你的应用逻辑,数据从哪里到哪里,怎么存储,处理;还有系统里的设备之间的通信顺序什么的.至于初始化等等工作不需要我们考虑。我们只需要调用相关的API函数就可以了。

    三.了解zigbee协议栈的应用文件夹

    安装好zigbee协议栈,打开目录Texas Instruments

    在这里插入图片描述

    (一)Components:顾名思义这个是放我们的库的文件夹,里面放了一些我们用到的ZDO,driver,hal,zcl 等库的代码

    (二)Documents:这里放的是TI 的开发文档的,里面很多都是讲述协议栈的API

    (三)Projects:这个文件夹放的是TI 协议栈的例子程序。

    (四)Tools:这个文件夹是放TI 的例子程序的一些上位机之类的程序,作为工具使用。

    接下来介绍的东西均需要打开示例工程在这里我们打开\ZStack-CC25302.5.1a\Projects\zstack\Samples\SampleApp\CC2530DB进入zigbee的协议栈中
    在这里插入图片描述

    为了确保程序没问题我们在这里重新编译一下协议栈。

    这是我们协议栈的汇总目录
    在这里插入图片描述
    这里是我们zigbee的文件夹,里面写好的代码都分为很多的group
    (一)APP:应用层目录,这里用户可以创建不同的工程目录,这里包含项目工程主要内容

    (二)HAL:硬件层目录,包含有与硬件相关的配置和驱动及操作函数。

    (三)MAC: MAC 层目录,包含了MAC 层的参数配置文件及其MAC 的LIB 库的函数接口文件。

    (四)MT:实现通过串口可控各层,于各层进行直接交互。

    (五)NWK:网络层目录,含网络层配置参数文件及网络层库的函数接口文件,APS 层库的函数接口

    (六)OSAL:协议栈的操作系统。

    (七)Profile: AF层目录,包含AF 层处理函数文件。

    (八)Security:安全层目录,安全层处理函数,比如加密函数等。

    (九)Services:地址处理函数目录,包括着地址模式的定义及地址处理函数。

    (十)Tools:工程配置目录,包括空间划分及ZStack 相关配置信息。

    (十一)ZDO: ZDO目录。

    (十二)ZMac: MAC 层目录,包括MAC 层参数配置及MAC 层LIB 库函数回调处理函数。

    (十三)Output:输出文件目录,这个EW8051 IDE 自动生成的。

    在这里插入图片描述
    点击DemoEB可以进行设备类型工作空间选择,必须要选好,不然不可以使用。

    CoordinatorEB:为协调器的工作空间。

    ROuterEB:为路由器的工作空间。

    EndDeviceEB:为无线终端的设备选择。

    四.zigbee协议栈的工作流程

    在我们这个版本的来说在我们使用者的路径流程是:main()---> osal_init_system()---> osalInitTasks()---> SampleApp_Init()

    (一)打开ZMain.c 找到main 函数
    学过C语言的都知道,C语言函数是在一直执行main文件里面的内容,首先我们先查看main.c的内容

    
    int main( void )
    {
      // Turn off interrupts
      osal_int_disable( INTS_ALL ); //关闭协议栈所有中断
    
      // Initialization for board related stuff such as LEDs
      HAL_BOARD_INIT();             //初始化协议栈系统时钟
    
      // Make sure supply voltage is high enough to run
      zmain_vdd_check();            //检查芯片电压是否正常
    
      // Initialize board I/O
      InitBoard( OB_COLD );         //初始化I/O 
    
      // Initialze HAL drivers
      HalDriverInit();              //初始化芯片硬件
    
      // Initialize NV System
      osal_nv_init( NULL );         //初始化Flash 存储器
    
      // Initialize the MAC
      ZMacInit();                   //初始化MAC 层
    
      // Determine the extended address
      zmain_ext_addr();             //确定IEEE 64位设备地址
    
      // Initialize basic NV items
      zgInit();                     //初始化非易失变量
    
    #ifndef NONWK
      // Since the AF isn't a task, call it's initialization routine
      afInit();
    #endif
    
      // Initialize the operating system
      osal_init_system();           //初始化协议栈操作系统
    
      // Allow interrupts
      osal_int_enable( INTS_ALL );  //使能全部中断
    
      // Final board initialization
      InitBoard( OB_READY );        //最终板载初始化
    
      // Display information about this device
      zmain_dev_info();             //LCD显示设备信息
    
      /* Display the device info on the LCD */
    #ifdef LCD_SUPPORTED
      zmain_lcd_init();             //初始化LCD
    #endif
    
    #ifdef WDT_IN_PM1
      /* If WDT is used, this is a good place to enable it. */
      WatchDogEnable( WDTIMX );
    #endif
    
      osal_start_system(); // No Return from here 执行操作系统,这里进入将不会退出,一直执行osal_start_system
    
      return 0;  // Shouldn't get here.
    } // main()
    

    我们接着看一下osal_start_system在这里我们可以点击选中然后goto到函数里面查看。
    在这里插入图片描述

    void osal_start_system( void )
    {
    #if !defined ( ZBIT ) && !defined ( UBIT )
      for(;;)  // Forever Loop //这是个死循环
    #endif
      {
        osal_run_system();  //协议栈一直执行这个函数
      }
    }
    

    接着继续goto osal_run_system这个是任务系统轮询的主要函数。他会查找发生的事件然后调用相应的事件执行函数, 如果没有事件登记要发生那就将进入睡眠模式。在协议栈中,所有将要处理的内容定义为事件,这个函数就是查找事件的函数,每个事件都有自己的事件号,根据事件号大小判断优先级,一个一个执行,例如按键按键,就触发按键事件,这个现在知道就可以,在后面我们会介绍。
    在这里我们知道了协议栈一直执行事件扫面函数,那我们如何根据需求开发呢,我们要做的就是设置一个自己要监测的事件,然后写交互逻辑。 // 一个任务可以有多个事件

    void osal_run_system( void )
    {
      uint8 idx = 0;
    
      osalTimeUpdate();//更新事件
      Hal_ProcessPoll();
    
      do {
        if (tasksEvents[idx])  // Task is highest priority that is ready.
        {
          break;
        }
      } while (++idx < tasksCnt);
    
      if (idx < tasksCnt)
      {
        uint16 events;
        halIntState_t intState;
    
        HAL_ENTER_CRITICAL_SECTION(intState);
        events = tasksEvents[idx];
        tasksEvents[idx] = 0;  // Clear the Events for this task.
        HAL_EXIT_CRITICAL_SECTION(intState);
    
        activeTaskID = idx;
        events = (tasksArr[idx])( idx, events );
        activeTaskID = TASK_NO_TASK;
    
        HAL_ENTER_CRITICAL_SECTION(intState);
        tasksEvents[idx] |= events;  // Add back unprocessed events to the current task.
        HAL_EXIT_CRITICAL_SECTION(intState);
      }
    #if defined( POWER_SAVING )
      else  // Complete pass through all task events with no activity?
      {
        osal_pwrmgr_powerconserve();  // Put the processor/system into sleep
      }
    #endif
    
      /* Yield in case cooperative scheduling is being used. */
    #if defined (configUSE_PREEMPTION) && (configUSE_PREEMPTION == 0)
      {
        osal_task_yield();
      }
    #endif
    }
    
    

    我们接下来进行事件的初始设置。在前面main函数中 osalInitTasks(); 为初始化系统任务,我们需要将自己的需求加入其中就可以达到目的。 goto一下进入函数 //osalInitTasks这个是设置任务的函数,然后任务里面也定义了很多事件

    void osalInitTasks( void )
    {
      uint8 taskID = 0;
    
      // 分配内存,返回指向缓冲区的指针
      tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
      // 设置所分配的内存空间单元值为0
      osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));
    
      // 任务优先级由高向低依次排列,高优先级对应taskID 的值反而小
      macTaskInit( taskID++ );  // taskID 0
      nwk_init( taskID++ );     // taskID 1
      Hal_Init( taskID++ );     //taskID 2
    #if defined( MT_TASK )
      MT_TaskInit( taskID++ );
    #endif
      APS_Init( taskID++ );      //taskID 3
    #if defined ( ZIGBEE_FRAGMENTATION )
      APSF_Init( taskID++ );
    #endif
      ZDApp_Init( taskID++ );    //taskID 4
    #if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
      ZDNwkMgr_Init( taskID++ );  
    #endif
     //SampleApp_Init为用户创建任务,我们需要在这里进行任务的添加 现在进入函数我们查看一下
      SampleApp_Init( taskID );  // taskID 5 
    }
    
    

    在这里我们看一下用户应用任务的事件处理函数进入SampleApp_ProcessEvent函数在这里我们可以看到在协议栈初始的时候定义的事件,和处理函数,在后面我们再详细介绍如何使用。

    uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
    {
      afIncomingMSGPacket_t *MSGpkt;
      (void)task_id;  // Intentionally unreferenced parameter
    
      if ( events & SYS_EVENT_MSG )//如果是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://如果是接受到RF消息进入这里
              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
        //  返回while ( MSGpkt )重新处理事件,直到缓冲区没有等待处理事件为止
          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 ) //如果是 SAMPLEAPP_SEND_PERIODIC_MSG_EVT 事件进入这里 这里是网络状态改变之后标志位值1的
      {
        // 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;
    }
    
    

    了解以上的流程我们就可以了解到协议栈的整体运行机制了。并且大概的概念。

    下面我们介绍本节涉及zigbee协议栈的函数;

    函数名osal_start_timerEx

    函数声明uint8 osal_start_timerEx( uint8 taskID, uint16 event_id, uint16 timeout_value )

    这是一个定时器的函数,将在timeout_value毫秒之后将任务号为taskID的任务,事件号为event_id的事件标志位置为1.这个时候就可以通过evens&进行判断

    有问题请发邮件至468078841@qq.com
    zigbee协议栈串口收发 From zigbee菜鸟笔记(十 二)点击进入

    展开全文
  • zigbee协议栈中文版

    2018-12-20 10:41:44
    开发ZigBee中文文档,详细说明ZigBee协议栈的,避免阅读英文资料
  • STM32 Zigbee 协议栈

    2014-02-10 11:19:10
    可用来zigbee 协议栈的开发和物联络网的入门学习
  • zigbee协议栈OSAL分析

    2021-01-06 03:03:05
    本文从源程序出发,分享本人学习zigbee协议栈的一些理解,介绍zigbee协议栈OSAL任务调度及用户自定义任务的调度处理过程。为了便于抓住本质,理清思路,本文剔除一些无关部分。 程序的入口是ZMain.c文件下的main(),...
  • ZigBee协议栈工作原理

    2021-09-26 14:12:58
      打开协议栈文件夹Texas Instruments\Projects\zstack,里面包含了TI公司的例程和工具。再打开Samples文件夹:   Samples文件夹里面有三个例子,即GenericApp、SampleApp、SimpleApp。在这里我们选择SampleApp...
  • ZigBee协议栈

    千次阅读 2019-05-10 14:52:43
    协议栈:是协议的具体实现形式,可以说是协议和用户之间的一个接口,开发人员通过使用协议栈来使用这个协议,进而实现无线数据收发。 ZigBee 的协议分为两部分, IEEE 802.15.4 定义了 PHY(物理层)和 MAC(介质...
  • ZIgBee协议栈

    2019-05-03 20:00:25
    ZigBee协议栈就是将各个层定义的协议都集合在一起,以函数的形式实现,并给用户提供一些API,工用户调用。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,549
精华内容 1,819
关键字:

zigbee协议栈