Chinaunix首页 | 论坛 | 博客
  • 博客访问: 43206
  • 博文数量: 59
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 10
  • 用 户 组: 普通用户
  • 注册时间: 2015-05-31 10:42
文章分类
文章存档

2015年(59)

我的朋友

分类: 嵌入式

2015-05-31 10:49:32

    在TI给的例子中,有两个大部分是用户必须编写,一个就是初始化函数,一个就是不同事件的处理函数,下面是SampleApp程序中的远程开头控制的初始化函数。
void SAPI_Init( byte task_id )
{

uint8 startOptions;

// 初始化任务ID,其中task_id由操作系统任务函数osalInitTasks( void ) 中的SAPI_Init( taskID );初始化

  sapi_TaskID = task_id;

  //初始化绑定标志位,默认不允许绑定

  sapi_bindInProgress = 0xffff;

 // 初始化端点描述符,分别是:端点任务ID号,端点号,简单描述符和延时请求,其中简单描述符有用户自己定义。

  sapi_epDesc.endPoint = zb_SimpleDesc.EndPoint;

  sapi_epDesc.task_id = &sapi_TaskID;

  sapi_epDesc.simpleDesc = (SimpleDescriptionFormat_t *)&zb_SimpleDesc;

  sapi_epDesc.latencyReq = noLatencyReqs;

  //向应用AF层注册端点描述符

  // Register the endpoint/interface description with the AF

 afRegister( &sapi_epDesc );

  //关闭描述符匹配响应请求 默认是关闭的 在zb_AllowBind()函数中打开
  // Turn off match descriptor response by default

  afSetMatch(sapi_epDesc.simpleDesc->EndPoint, FALSE);

  // Register callback evetns from the ZDApp
  //注册两个响应事件,也就是网络地址响应,描述符匹配响应

  ZDO_RegisterForZDOMsg( sapi_TaskID, NWK_addr_rsp );

  ZDO_RegisterForZDOMsg( sapi_TaskID, Match_Desc_rsp );

#if (defined HAL_KEY) && (HAL_KEY == TRUE)

  // Register for HAL events 注册按键事件

  RegisterForKeys( sapi_TaskID );

  if ( HalKeyRead () == HAL_KEY_SW_5)

  {

// If SW5 is pressed and held while powerup, force auto-start and nv-restore off and reset

//关闭自动启动设备

    startOptions = ZCD_STARTOPT_CLEAR_STATE | ZCD_STARTOPT_CLEAR_CONFIG;

    zb_WriteConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );

    zb_SystemReset();

  }
#endif // HAL_KEY
 
  // Set an event to start the application 设置进入事件 ,启动应用

  osal_set_event(task_id, ZB_ENTRY_EVENT);

}
下面是事件处理函数

UINT16 SAPI_ProcessEvent( byte task_id, UINT16 events )

{

  osal_event_hdr_t *pMsg;

  afIncomingMSGPacket_t *pMSGpkt;

  afDataConfirm_t *pDataConfirm;

  if ( events & SYS_EVENT_MSG ) //强制事件,也是系统定义好的事件,下面有很多子事件

  {

    pMsg = (osal_event_hdr_t *) osal_msg_receive( task_id );

    while ( pMsg )
    {
      switch ( pMsg->event )
      {
//消息注册并被接收后(OTA),将作为ZDO_CB_MSG (OSAL Msg)发送到应用/任务
        case ZDO_CB_MSG:

          SAPI_ProcessZDOMsgs( (zdoIncomingMsg_t *)pMsg );

          break;
        case AF_DATA_CONFIRM_CMD:

          // This message is received as a confirmation of a data packet sent. The status is of ZStatus_t type [defined in ZComDef.h]

          // The message fields are defined in AF.h

  //数据包发送确认信息,这些状态值定义在ZcomDef.h文件中,该信息定义在AF.h中

          pDataConfirm = (afDataConfirm_t *) pMsg;

 //发送消息确认        

      SAPI_SendDataConfirm( pDataConfirm->transID, pDataConfirm->hdr.status );

          break;
        case AF_INCOMING_MSG_CMD: //AF数据输入
          pMSGpkt = (afIncomingMSGPacket_t *) pMsg;
              //接收数据指示

          SAPI_ReceiveDataIndication( pMSGpkt->srcAddr.addr.shortAddr,pMSGpkt->clusterId,          pMSGpkt->cmd.DataLength, pMSGpkt->cmd.Data);

          break;
        case ZDO_STATE_CHANGE:  //ZDO状态改变

          // If the device has started up, notify the application 向应用通报设备启动

          if (pMsg->status == DEV_END_DEVICE ||

              pMsg->status == DEV_ROUTER ||
              pMsg->status == DEV_ZB_COORD )
          {
            SAPI_StartConfirm( ZB_SUCCESS );
          }

          else  if (pMsg->status == DEV_HOLD ||

                  pMsg->status == DEV_INIT)
          {
            SAPI_StartConfirm( ZB_INIT ); //启动确认
          }
          break;
        case ZDO_MATCH_DESC_RSP_SENT: //ZDO发送一个匹配描述符响应

          SAPI_AllowBindConfirm( ((ZDO_MatchDescRspSent_t *)pMsg)->nwkAddr );

          break;
        case KEY_CHANGE: //键盘事件

          zb_HandleKeys( ((keyChange_t *)pMsg)->state, ((keyChange_t *)pMsg)->keys );

          break;

        case SAPICB_DATA_CNF: //发送数据确认

          SAPI_SendDataConfirm(

                (uint8)((sapi_CbackEvent_t *)pMsg)->data,

                ((sapi_CbackEvent_t *)pMsg)->hdr.status );

          break;
 
        case SAPICB_BIND_CNF: //绑定确认

          SAPI_BindConfirm(

                ((sapi_CbackEvent_t *)pMsg)->data,

                ((sapi_CbackEvent_t *)pMsg)->hdr.status );

          break;
 
        case SAPICB_START_CNF:  //设备启动确认

          SAPI_StartConfirm( ((sapi_CbackEvent_t *)pMsg)->hdr.status );

          break;
 
        default:

          //用户信息处理

          // User messages should be handled by user or passed to the application

          if ( pMsg->event >= ZB_USER_MSG )

          {
               //用户可以编写自己的消息处理任务函数
          }
          break;
      }
 
      // Release the memory
      osal_msg_deallocate( (uint8 *) pMsg );
 
      // Next

      pMsg = (osal_event_hdr_t *) osal_msg_receive( task_id );

    }

    // Return unprocessed events 返回没有处理的事件

    return (events ^ SYS_EVENT_MSG);

  }

  if ( events & ZB_ALLOW_BIND_TIMER ) //允许绑定时间事件,也就是绑定时间到,没有绑定成功时执行

  {

    afSetMatch(sapi_epDesc.simpleDesc->EndPoint, FALSE);

    return (events ^ ZB_ALLOW_BIND_TIMER);

  }

  if ( events & ZB_BIND_TIMER ) //绑定时间

  {

    // Send bind confirm callback to application

    SAPI_BindConfirm( sapi_bindInProgress, ZB_TIMEOUT );

    sapi_bindInProgress = 0xffff;
    return (events ^ ZB_BIND_TIMER);

  }

  if ( events & ZB_ENTRY_EVENT )

  {

    uint8 startOptions;

    // Give indication to application of device startup 提示用户设备已经启动

    zb_HandleOsalEvent( ZB_ENTRY_EVENT );

    // LED off cancels HOLD_AUTO_START blink set in the stack 点高蓝色指示灯

    HalLedSet (HAL_LED_4, HAL_LED_MODE_OFF);
     //从ZigBee设备的非易失性存储器中读取配置信息

    zb_ReadConfiguration( ZCD_NV_STARTUP_OPTION, sizeof(uint8), &startOptions );

    if ( startOptions & ZCD_STARTOPT_AUTO_START )

    {
      zb_StartRequest();
    }
    else
    {

      // blink leds and wait for external input to config and restart 再次启动设备 加入网络

      HalLedBlink(HAL_LED_2, 0, 50, 500);
    }
 
    return (events ^ ZB_ENTRY_EVENT );

  }

  // This must be the last event to be processed

  if ( events & ( ZB_USER_EVENTS ) )

  {

    // User events are passed to the application 处理用户自己定义的事件

    zb_HandleOsalEvent( events );

    // Do not return here, return 0 later

  }

  // Discard unknown events 丢弃未知的事件

  return 0;

}
2. App任务事件处理函数
    在SAPI_Init()函数最后设置了进入事件(ZB-ENTRY_EVENT)用户自己定义的,这将触发任务的事件 处理函数SAPI_ProcessEvent(),该函数处理任务所有的事件,包含时间,消息和其他用户定义的事件。
              事件
           处理函数
 
 
 
 
系统消息事件
SYS_ENTRY_MSG
ZDO反馈
ZDO_CB_MSG
SAPI_ProcessZDOMsgs()
AF 数据确认
AF_DATA_CONFIRM_CMD
SAPI_SendDataConfirm()
AF 信息输入
AF_INCOMING_MSG_CMD
SAPI_ReceiveDataIndication()
ZDO 状态改变
ZDO_STATE_CHANGE
SAPI_StartConfirm()
ZDO 匹配描述符响应
ZDO_MATCH_DESC_RSP_SENT
SAPI_AllowBindConfirm()
按键
KEY_CHANGE
zb_HandleKeys()
发送数据确认
SAPICB_DATA_CNF
SAPI_SendDataConfirm()
绑定确认
SAPICB_BIND_CNF
SAPI_BindConfirm()
设备启动确认
SAPICB_START_CNF
SAPI_StartConfirm()
允许绑定时间事件
ZB_ALLOW_BIND_TIMER
afSetMatch()
绑定时间事件
ZB_BIND_TIMER
SAPI_BindConfirm()
进入事件
ZB_ENTRY_EVENT
zb_StartRequest()
3.  ZDO 初始化
void ZDApp_Init( byte task_id )
{

  uint8 capabilities;

  // Save the task ID 初始化任务ID,其中task_id由操作系统初始化任务函数osalInitTasks()决定

  ZDAppTaskID = task_id;

  // 初始化网络地址,地址模式为16位,网络地址为无效

  ZDAppNwkAddr.addrMode = Addr16Bit;

  ZDAppNwkAddr.addr.shortAddr = INVALID_NODE_ADDR;

  (void)NLME_GetExtAddr();  // 保存64位IEEE地址。

  // Check for manual "Hold Auto Start" 检测是否阻止自动启动

  ZDAppCheckForHoldKey();

  // Initialize ZDO items and setup the device - type of device to create.

 //根据设备类型初始化网络服务

  ZDO_Init();

  // Register the endpoint description with the AF

  // This task doesn't have a Simple description, but we still need

  // to register the endpoint. 注册端点0

  afRegister( (endPointDesc_t *)&ZDApp_epDesc );

 
#if defined( ZDO_USERDESC_RESPONSE )

  ZDApp_InitUserDesc();

#endif // ZDO_USERDESC_RESPONSE
 

  // set broadcast address mask to support broadcast filtering

  NLME_GetRequest(nwkCapabilityInfo, 0, &capabilities);

  NLME_SetBroadcastFilter( capabilities );

  // Start the device? 启动设备

  if ( devState != DEV_HOLD )

  {

    ZDOInitDevice( 0 );

  }

  else

  {

    // Blink LED to indicate HOLD_START

    HalLedBlink ( HAL_LED_4, 0, 50, 500 );

  }
 

  ZDApp_RegisterCBs(); //注册响应事件

} /* ZDO_Init() */
 
  任务事件处理函数ZDApp_event_loop()包含消息、网络初始化、网络启动、路由启动等事件。 

            事件
        处理函数
 
 
 
 
系统消息事件
SYS_ENTRY_MSG
AF 信息输入
AF_INCOMING_MSG_CMD
ZDP_IncomingData()
ZDO 反馈
AF_DATA_CONFIRM_CMD
ZDApp_ProcessMsgCBs()
AF 数据确认
AF_DATA_CONFIRM_CMD
网络发现确认
ZDO_NWK_DISC_CNF
NLME_JoinRequest()或
NLME_ReJoinRequest()
网络加入指示
ZDO_NWK_JOIN_IND
ZDApp_ProcessNetworkJoin()
网络加入请求
ZDO_NWK_JOIN_REQ
ZDApp_NetworkInit( )
网络初始化
ZDO_NETWORK_INIT
ZDO_StartDevice()
网络启动
ZDO_NETWORK_START
ZDApp_NetworkStartEvt()
路由启动
ZDO_ROUTER_START
osal_pwrmgr_device()
状态改变
ZDO_STATE_CHANGE_EVT
ZDO_UpdateNwkStatus()
网络NV 更新
ZDO_NWK_UPDATE_NV
ZDApp_SaveNetworkStateEvt()
设备重新启动
ZDO_DEVICE_RESET
SystemResetSoft()

  在f8wCoord.cfg文件中,我们可以看到,有下面的编译选项,协调器的设置,应该是表示

#define ZDO_COORDINATOR

/* Coordinator Settings */
-DZDO_COORDINATOR                  // Coordinator Functions
那么在ZGlobals.h 文件中可以看到下面的定义

// Values for ZCD_NV_LOGICAL_TYPE (zgDeviceLogicalType)

#define ZG_DEVICETYPE_COORDINATOR      0x00
#define ZG_DEVICETYPE_ROUTER           0x01
#define ZG_DEVICETYPE_ENDDEVICE        0x02
#define ZG_DEVICETYPE_SOFT             0x03
// Device Logical Type
#if defined ( SOFT_START )

  #define DEVICE_LOGICAL_TYPE ZG_DEVICETYPE_SOFT

#elif defined( ZDO_COORDINATOR )

  #define DEVICE_LOGICAL_TYPE ZG_DEVICETYPE_COORDINATOR

#elif defined (RTR_NWK)

  #define DEVICE_LOGICAL_TYPE ZG_DEVICETYPE_ROUTER

#else

  #define DEVICE_LOGICAL_TYPE ZG_DEVICETYPE_ENDDEVICE

#endif
    说明我们这里选择的是协调器,在下图中我们选择的不同的类型,下面的文件就会被不同的选择。控制节点的 IAR 工程配置选项中定义了阻止自定启动,即 HOLD_AUTO_START,因此在ZDApp.c 文件中定义了设备初始状态和启动模式:在uint8 ZDOInitDevice( uint16 startDelay )函数中
devState = DEV_HOLD

#if defined( ZDO_COORDINATOR ) && !defined( SOFT_START )

  // Set the default to coodinator

  devStartModes_t devStartMode = MODE_HARD;

 在控制节点的NV 中,默认状态下没有设置启动模式,即ZCD_NV_STARTUP_OPTION=0  
因此,初次使用控制节点时不会自定启动该节点。另外,对应控制节点的 SimpleController.c 定义了应用层的状态:
myAppState = APP_INIT
 

结束

阅读(501) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~