zigbee快速使用指南

zigbee型号说明

此处省略写,zigbee协议栈使用:
cc2530-2.5.1a。CC2530是2.4Ghz,芯片其它说明,略。

官方说明

  1. zigbee芯片型号 ,使用TI公司的CC2530芯片。
  2. 协议栈 ,CC2530-2.5.1a,该版本支持了OTA。
  3. 协议栈构成,略。
  4. 本说明纯属自己学习过程笔记,中间如果存在错误,希望大家可以指正。本说明主要是从代码层面快速运用zigbee模块(CC2530)。

zigbee开发

zstack结构

1.协调 路由 终端
听起来就不复杂,
协调–组建网络,发起
路由–中间转发等等呢
终端–最终的设备(可能这么叫不专业)
2.组建网络
协调器是发起者,所以它有权利让别人加入到网络中来。

代码

1.协议栈起点
直接从下面代码出发,zstack采取的是片段轮询,这里先把什么Coordinator,EndDevice,Router放一边,先看整体,再到局部。前面的很多任务都是系统协议栈需要的。自己的任务是在

const pTaskEventHandlerFn tasksArr[] = {
//这里开始添加自己需要的任务,
  SerialApp_ProcessEvent
};
void osalInitTasks( void )
{
//每个任务都有一个ID,taskID自身++,
SerialApp_Init( taskID );
}
//上述过程相当把任务加入了zstack协议

上述过程已经完成了任务加入系统。整个系统代码大体如下:

/*********************************************************************
 * GLOBAL VARIABLES
 */

// 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
  SerialApp_ProcessEvent
};

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 )
{
  uint8 taskID = 0;

  tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
  osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));

  macTaskInit( taskID++ );
  nwk_init( taskID++ );
  Hal_Init( taskID++ );
#if defined( MT_TASK )
  MT_TaskInit( taskID++ );
#endif
  APS_Init( taskID++ );
#if defined ( ZIGBEE_FRAGMENTATION )
  APSF_Init( taskID++ );
#endif
  ZDApp_Init( taskID++ );
#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )
  ZDNwkMgr_Init( taskID++ );
#endif
  SerialApp_Init( taskID );
}

2.配置必要硬件
所谓配置必要硬件,就是在SerialApp_Init(unit8 task_id),完成初始化过程。

/*********************************************************************
 * @fn      SerialApp_Init
 *
 * @brief   This is called during OSAL tasks' initialization.
 *
 * @param   task_id - the Task ID assigned by OSAL.
 *
 * @return  none
 */
void SerialApp_Init( uint8 task_id )
{
//1、系统硬件初始化
  bsp_init();//什么串口,led,传感器,统统这里
  SerialApp_TaskID = task_id;
  SampleApp_NwkState = DEV_INIT;  
  afRegister( (endPointDesc_t *)&SerialApp_epDesc );
  RegisterForKeys( task_id );

#if defined ( LCD_SUPPORTED )
  HalLcdWriteString( "SerialApp", HAL_LCD_LINE_2 );
#endif
//2、设置好广播,还是点播
  /*点播地址*/
  SerialApp_Txp2pAddr.addrMode = (afAddrMode_t)Addr16Bit;
  SerialApp_Txp2pAddr.endPoint = SERIALAPP_ENDPOINT;
  SerialApp_Txp2pAddr.addr.shortAddr = AddrNotPresent;
  
  /*广播地址*/
  SerialApp_TxBroadcastAddr.addrMode = (afAddrMode_t)AddrBroadcast;
  SerialApp_TxBroadcastAddr.endPoint = SERIALAPP_ENDPOINT;
  SerialApp_TxBroadcastAddr.addr.shortAddr = 0xFFFF;
  
  ZDO_RegisterForZDOMsg( SerialApp_TaskID, End_Device_Bind_rsp );
  ZDO_RegisterForZDOMsg( SerialApp_TaskID, Match_Desc_rsp );


}

上述代码是,做了系统初始化工作,注册好必要的函数,当然在使用中,要搞清是在广播还是点播,地址要设置好,一些高级一点的运用,可能还要判断一下SYS_EVENT_MSG,主要是判断ZDO_STATE_CHANGE,来执行相应地址设置,(例如防止整个系统中coordinator挂了,系统中的路由改变成coordinator。这个例程有空可以在探讨。)
3.处理回调
没办法片段轮询系统,回调是处理这类事物的关键(回调本质上使用的是函数指针,即传递的参数是函数指针。)
前面设置好了事件回调函数,SerialApp_ProcessEvent。

/*********************************************************************
 * @fn      SerialApp_ProcessEvent
 *
 * @brief   Generic Application Task event processor.
 *
 * @param   task_id  - The OSAL assigned task ID.
 * @param   events   - Bit map of events to process.
 *
 * @return  Event flags of all unprocessed events.
 */
//这个函数是注册任务时,指定的哦!!!!!
UINT16 SerialApp_ProcessEvent( uint8 task_id, UINT16 events )
{
  (void)task_id;  // Intentionally unreferenced parameter
//1、按照惯例,先判断系统事件有无发生
  if ( events & SYS_EVENT_MSG )
  {
    afIncomingMSGPacket_t *MSGpkt;

    while ( (MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SerialApp_TaskID )) )
    {
      switch ( MSGpkt->hdr.event )
      {
      case ZDO_CB_MSG:
        break;          
      case KEY_CHANGE:       
        break;
      case AF_INCOMING_MSG_CMD://无线信号接收,数据包到来
        SerialApp_ProcessMSGCmd( MSGpkt );
        break;
      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.
            HalLedSet(HAL_LED_1, HAL_LED_MODE_ON);           
            if(SampleApp_NwkState != DEV_ZB_COORD)
            {
            }
            else
            {
            }
        }
        else
        {
          // Device is no longer in the network
        }
        break;     
      default:
        break;
      }

      osal_msg_deallocate( (uint8 *)MSGpkt );
    }

    return ( events ^ SYS_EVENT_MSG );
  }
//2、这里开始可以是用户自己的事件了,什么自定义的事件,这里随便定义了一个事件USER_SEND_PERIODIC,这个时间在周期发送事件,可以是什么传感器啊,周期发送出去,当然osal_start_timerEx(),系统初始化时,需要调用一下,才能触发,USER_SEND_PERIODIC这个是宏定义的,宏定义一下
//#define USER_SEND_PERIODIC 0x11
//不要跟其它事件,使用一样的值
  if(events & USER_SEND_PERIODIC){  
    sendAF(); osal_start_timerEx(SerialApp_TaskID,USER_SEND_PERIODIC,200);//200MS
    return (events ^ USER_SEND_PERIODIC);
  }

  return ( 0 );  // Discard unknown events.
}

上述代码主要就是处理系统回调,包括系统事件回调,用户自定义事件的回调。函数返回的是没有处理的事件。
所谓事件的设定可以是定时事件,也可以是自主设置
osal_start_timerEx( uint8 taskID, uint16 event_id, uint16 timeout_value ),该函数源码如下:

/*********************************************************************
 * @fn      osal_start_timerEx
 *
 * @brief
 *
 *   This function is called to start a timer to expire in n mSecs.
 *   When the timer expires, the calling task will get the specified event.
 *
 * @param   uint8 taskID - task id to set timer for
 * @param   uint16 event_id - event to be notified with
 * @param   UNINT16 timeout_value - in milliseconds.
 *
 * @return  SUCCESS, or NO_TIMER_AVAIL.
 */
uint8 osal_start_timerEx( uint8 taskID, uint16 event_id, uint16 timeout_value )
{
。。。。。。。。
}

**uint8 osal_set_event( uint8 task_id, uint16 event_flag )**自行设置事件发生,源码如下:

/*********************************************************************
 * @fn      osal_set_event
 *
 * @brief
 *
 *    This function is called to set the event flags for a task. The
 *    event passed in is OR'd into the task's event variable.
 *
 * @param   uint8 task_id - receiving tasks ID
 * @param   uint8 event_flag - what event to set
 *
 * @return  SUCCESS, INVALID_TASK
 */
uint8 osal_set_event( uint8 task_id, uint16 event_flag )
{
。。。。。。。
}

4.其它处理逻辑
其它处理逻辑,主要就是系统需要处理的信息,什么数据采集,传递等等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值