如何在协议栈中构建自己的 Zigbee 网络指示灯

这篇文章主要讲解,如何构建自己的网络指示灯,实现设备在网时亮灯,脱网时灭灯这个效果。
解决这个问题主要分两个步骤:
1)建立指示灯的底层驱动代码。
2)替换掉官方的网络指示灯应用代码。

一、建立指示灯底层驱动代码
这个太简单了,不多解释,只贴代码。
LED.c 文件
/********************************************************************
*
* 文件名:LED.c
*
* 文件描述:指示灯驱动文件
*
* 创建人:Jesse_黄嘉伟;QQ:3524999324
*
* 版本号:
*
* 修改记录:
*
********************************************************************/
#include <iocc2530.h>
#include "LED.h"


/*********************************************************************
 * MACROS
 */

/*********************************************************************
 * CONSTANTS
 */

/*********************************************************************
 * TYPEDEFS
 */

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

/*********************************************************************
 * GLOBAL FUNCTIONS
 */

/*********************************************************************
 * LOCAL VARIABLES
 */

/*********************************************************************
 * LOCAL FUNCTIONS
 */

/*********************************************************************
 * EXTERN VARIABLES
 */

/*********************************************************************
 * EXTERN FUNCTIONS
 */




/************************************************************************
* 函数名:void Init_IndicatorLight(void)
* 功能:初始化指示灯
* 参数:none
* 返回值:none
* 调用函数:none
* 引用全局变量:none
* 函数全局变量:none
* 作者:黄嘉伟
* 时间:2017/2/18
* 最后修改时间:
* 说明:
*************************************************************************/
void Init_IndicatorLight(void)
{
  // 网络指示灯 P0_7;入网时亮,未入网时灭;低电平亮,高电平灭
  P0SEL &= ~(1<<7);     // 通用IO口
  P0DIR |= (1<<7);      // IO口方向输出
  CLOSE_NWKLIGHT();     // 指示灯灭
}

/************************************************************************
* 函数名:void Control_IndicatorLight(uint8_t light, uint8_t state)
* 功能:控制指示灯亮灭
* 参数:
  light:指示灯
  state:指示灯状态
* 返回值:none
* 调用函数:none
* 引用全局变量:none
* 函数全局变量:none
* 作者:黄嘉伟
* 时间:2017/2/18
* 最后修改时间:
* 说明:
*************************************************************************/
void Control_IndicatorLight(uint8 light, uint8 state)
{
  switch(light)
  {
    case LIGHT_NEK:
      {
        if(state==LIGHT_ON)
        {
          OPEN_NWKLIGHT();
        }
        if(state==LIGHT_OFF)
        {
          CLOSE_NWKLIGHT();
        }
      }
      break;
      
    default:
      break;
  }
}
LED.h 文件
/********************************************************************
*
* 文件名:LED.c
*
* 文件描述:指示灯驱动文件
*
* 创建人:Jesse_黄嘉伟;QQ:3524999324
*
* 版本号:
*
* 修改记录:
*
********************************************************************/
#ifndef __LED_H
#define __LED_H

#include "ZComDef.h"
/*********************************************************************
 * MACROS
 */
// 指示灯 IO 口
#define NEKLIGHT       P0_7
// 指示灯类型
#define LIGHT_NEK 0x01
// 指示灯状态
#define LIGHT_ON  0x01
#define LIGHT_OFF 0x00

#define OPEN_NWKLIGHT()  (NEKLIGHT=0)
#define CLOSE_NWKLIGHT() (NEKLIGHT=1)
/*********************************************************************
 * CONSTANTS
 */

/*********************************************************************
 * TYPEDEFS
 */

/*********************************************************************
 * VARIABLES
 */

/*********************************************************************
 * FUNCTIONS
 */
void Init_IndicatorLight(void);
void Control_IndicatorLight(uint8 light, uint8 state);

#endif

二、替换掉官方的网络指示灯应用代码
在 Zigbee 官方的协议栈中也有网络指示灯的功能,其应用现象是协调器形成局域网失败时,网络指示灯闪烁,协调器形成局域网后,网络指示灯常亮;路由器和终端节点在未入网时,网络指示灯闪烁,入网后,网络指示灯常亮。其中终端节点在失去其父节点,重新请求入网时,网络指示灯会闪烁,当然这种情况就可以看做终端节点已经脱离网络了。
Zigbee 官方的协议栈中,网络指示灯使用的端口是 P1_4。顺着这个线索我们来看看 Z-STACK 的代码吧。
我们可以在协议栈中搜索“P1_4”关键字,可以看到:

“Hal_board_cfg.h”文件和“Mac_radio_defs.c”文件都用到了“P1_4”。我们先来看看“Hal_board_cfg.h”文件。
“Hal_board_cfg.h”:
在这里可以看出 P1_4 引脚是官方开发板上 LED3 的驱动引脚。
我们再看下“Mac_radio_defs.c”文件。
“Mac_radio_defs.c”:
这里的 P1_4 被用作 PA CC2591 和 CC2590 的引脚。所以当你添加“HAL_PA_LNA”之类的预编译来开启PA功能时,协议栈原本的网络指示灯就不能用了,这时候我们就要将网络指示灯改为别的IO口操作。
现在我们就顺着 LED3 的线索来看看 LED3 在哪些地方有应用。我们在协议栈中搜索“HAL_LED_3”可以看到有这几处应用了 LED3:

我们在查看上面的每一个文件后可以发现网络指示灯的关键代码在“ZDApp.c”的3个函数当中。
1)ZDO_NetworkFormationConfirmCB()
/*********************************************************************
 * @fn          ZDO_NetworkFormationConfirmCB
 *
 * @brief       This function reports the results of the request to
 *              initialize a coordinator in a network.
 *
 * @param       Status - Result of NLME_NetworkFormationRequest()
 *
 * @return      none
 */
void ZDO_NetworkFormationConfirmCB( ZStatus_t Status )
{
  nwkStatus = (byte)Status;

  if ( Status == ZSUCCESS )
  {
    // LED on shows Coordinator started
    HalLedSet ( HAL_LED_3, HAL_LED_MODE_ON );    // 组网成功,点亮网络指示灯

    // LED off forgets HOLD_AUTO_START
    HalLedSet (HAL_LED_4, HAL_LED_MODE_OFF);

#if defined ( ZBIT )
    SIM_SetColor(0xd0ffd0);
#endif

    if ( devState == DEV_HOLD )
    {
      // Began with HOLD_AUTO_START
      devState = DEV_COORD_STARTING;
    }
  }
#if defined(BLINK_LEDS)
  else
  { // 组网失败,闪烁网络指示灯
    HalLedSet ( HAL_LED_3, HAL_LED_MODE_FLASH );  // Flash LED to show failure
  }
#endif

  osal_set_event( ZDAppTaskID, ZDO_NETWORK_START );
}
上述函数为协调器网络形成确认回调函数,从上面代码我们可以看出,当协调器形成网络成功时,网络指示灯常亮,形成网络失败时,网络指示灯闪烁。
我们可以在这个函数中添加自己的网络指示灯应用代码。更改代码如下:
/*********************************************************************
 * @fn          ZDO_NetworkFormationConfirmCB
 *
 * @brief       This function reports the results of the request to
 *              initialize a coordinator in a network.
 *
 * @param       Status - Result of NLME_NetworkFormationRequest()
 *
 * @return      none
 */
void ZDO_NetworkFormationConfirmCB( ZStatus_t Status )
{
  nwkStatus = (byte)Status;

  if ( Status == ZSUCCESS )
  {
/*
* ----- commented by Jesse_黄嘉伟 2017/09/09 ------
*
    // LED on shows Coordinator started
    HalLedSet ( HAL_LED_3, HAL_LED_MODE_ON );
* 
*/
/* ------ Added by Jesse_黄嘉伟 2017/09/09 ----- */
    // 组网成功,点亮网络指示灯
    Control_IndicatorLight(LIGHT_NEK, LIGHT_ON);
/* ----------------------------------------- */    

    // LED off forgets HOLD_AUTO_START
    HalLedSet (HAL_LED_4, HAL_LED_MODE_OFF);

#if defined ( ZBIT )
    SIM_SetColor(0xd0ffd0);
#endif

    if ( devState == DEV_HOLD )
    {
      // Began with HOLD_AUTO_START
      devState = DEV_COORD_STARTING;
    }
  }
/*
* ----- commented by Jesse_黄嘉伟 2017/09/09 ------
*
#if defined(BLINK_LEDS)
  else
  {
    HalLedSet ( HAL_LED_3, HAL_LED_MODE_FLASH );  // Flash LED to show failure
  }
#endif
* 
*/
/* ------ Added by Jesse_黄嘉伟 2017/09/09 ----- */
  else
  {
    // 组网失败,熄灭网络指示灯
    Control_IndicatorLight(LIGHT_NEK, LIGHT_OFF);
  }
/* ----------------------------------------- */      

  osal_set_event( ZDAppTaskID, ZDO_NETWORK_START );
}
还有另外2个回调函数,分别是:ZDO_StartRouterConfirmCB() 和 ZDO_JoinConfirmCB()。
2)ZDO_StartRouterConfirmCB()
/*********************************************************************
 * @fn          ZDO_StartRouterConfirmCB
 *
 * @brief       This function reports the results of the request to
 *              start functioning as a router in a network.
 *
 * @param       Status - Result of NLME_StartRouterRequest()
 *
 * @return      none
 */
void ZDO_StartRouterConfirmCB( ZStatus_t Status )
{
  nwkStatus = (byte)Status;

  if ( Status == ZSUCCESS )
  {
    // LED on shows Router started
    HalLedSet ( HAL_LED_3, HAL_LED_MODE_ON );    // 入网成功,点亮网络指示灯
    // LED off forgets HOLD_AUTO_START
    HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF);
    if ( devState == DEV_HOLD )
    {
      // Began with HOLD_AUTO_START
      devState = DEV_END_DEVICE;
    }
  }
#if defined(BLINK_LEDS)
  else
  {  // 入网失败,闪烁网络指示灯
    HalLedSet( HAL_LED_3, HAL_LED_MODE_FLASH );  // Flash LED to show failure
  }
#endif

  osal_set_event( ZDAppTaskID, ZDO_ROUTER_START );
}
上述函数是路由器入网结果确认回调函数,路由器入网成功则点亮网络指示灯,路由器入网失败则闪烁网络指示灯。
更改程序如下:
/*********************************************************************
 * @fn          ZDO_StartRouterConfirmCB
 *
 * @brief       This function reports the results of the request to
 *              start functioning as a router in a network.
 *
 * @param       Status - Result of NLME_StartRouterRequest()
 *
 * @return      none
 */
void ZDO_StartRouterConfirmCB( ZStatus_t Status )
{
  nwkStatus = (byte)Status;


  if ( Status == ZSUCCESS )
  {
/*
* ----- commented by Jesse_黄嘉伟 2017/09/09 ------
*
    // LED on shows Router started
    HalLedSet ( HAL_LED_3, HAL_LED_MODE_ON );
* 
*/
/* ------ Added by Jesse_黄嘉伟 2017/09/09 ----- */
    // 入网成功,点亮网络指示灯
    Control_IndicatorLight(LIGHT_NEK, LIGHT_ON);
/* ----------------------------------------- */    
    // LED off forgets HOLD_AUTO_START
    HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF);
    if ( devState == DEV_HOLD )
    {
      // Began with HOLD_AUTO_START
      devState = DEV_END_DEVICE;
    }
  }
/*
* ----- commented by Jesse_黄嘉伟 2017/09/09 ------
*
#if defined(BLINK_LEDS)
  else
  {
    HalLedSet( HAL_LED_3, HAL_LED_MODE_FLASH );  // Flash LED to show failure
  }
#endif
* 
*/
/* ------ Added by Jesse_黄嘉伟 2017/09/09 ----- */
  else
  {
    // 入网失败,熄灭网络指示灯
    Control_IndicatorLight(LIGHT_NEK, LIGHT_OFF);
  }
/* ----------------------------------------- */      

  osal_set_event( ZDAppTaskID, ZDO_ROUTER_START );
}
3)ZDO_JoinConfirmCB()
/*********************************************************************
 * @fn          ZDO_JoinConfirmCB
 *
 * @brief       This function allows the next hight layer to be notified
 *              of the results of its request to join itself or another
 *              device to a network.
 *
 * @param       Status - Result of NLME_JoinRequest()
 *
 * @return      none
 */
void ZDO_JoinConfirmCB( uint16 PanId, ZStatus_t Status )
{
  (void)PanId;  // remove if this parameter is used.

  nwkStatus = (byte)Status;

  if ( Status == ZSUCCESS )
  {
    // LED on shows device joined
    HalLedSet ( HAL_LED_3, HAL_LED_MODE_ON );    // 入网成功,点亮网络指示灯
    // LED off forgets HOLD_AUTO_START
    HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF);
    if ( (devState == DEV_HOLD) )
    {
      // Began with HOLD_AUTO_START
      devState = DEV_NWK_JOINING;
    }

    if ( !ZG_SECURE_ENABLED )
    {
      // Notify to save info into NV
      ZDApp_NVUpdate();
    }
  }
  else
  {  // 入网失败,闪烁网络指示灯
#if defined(BLINK_LEDS)
    HalLedSet ( HAL_LED_3, HAL_LED_MODE_FLASH );  // Flash LED to show failure
#endif
  }

  // Pass the join confirm to higher layer if callback registered
  if (zdoCBFunc[ZDO_JOIN_CNF_CBID] != NULL )
  {
    zdoJoinCnf_t joinCnf;

    joinCnf.status = Status;
    joinCnf.deviceAddr = _NIB.nwkDevAddress;
    joinCnf.parentAddr = _NIB.nwkCoordAddress;

    zdoCBFunc[ZDO_JOIN_CNF_CBID]( (void*)&joinCnf );
  }

  // Notify ZDApp
  ZDApp_SendMsg( ZDAppTaskID, ZDO_NWK_JOIN_IND, sizeof(osal_event_hdr_t), (byte*)NULL );

}
上述函数为终端设备入网结果确认回调函数,入网成功则点亮网络指示灯,入网失败则闪烁网络指示灯。
其修改代码如下:
/*********************************************************************
 * @fn          ZDO_JoinConfirmCB
 *
 * @brief       This function allows the next hight layer to be notified
 *              of the results of its request to join itself or another
 *              device to a network.
 *
 * @param       Status - Result of NLME_JoinRequest()
 *
 * @return      none
 */
void ZDO_JoinConfirmCB( uint16 PanId, ZStatus_t Status )
{
  (void)PanId;  // remove if this parameter is used.

  nwkStatus = (byte)Status;

  if ( Status == ZSUCCESS )
  {
/*
* ----- commented by Jesse_黄嘉伟 2017/09/09 ------
*
    // LED on shows Router started
    HalLedSet ( HAL_LED_3, HAL_LED_MODE_ON );
* 
*/
/* ------ Added by Jesse_黄嘉伟 2017/09/09 ----- */
    // 入网成功,点亮网络指示灯
    Control_IndicatorLight(LIGHT_NEK, LIGHT_ON);
/* ----------------------------------------- */        
    // LED off forgets HOLD_AUTO_START
    HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF);
    if ( (devState == DEV_HOLD) )
    {
      // Began with HOLD_AUTO_START
      devState = DEV_NWK_JOINING;
    }

    if ( !ZG_SECURE_ENABLED )
    {
      // Notify to save info into NV
      ZDApp_NVUpdate();
    }
  }
  else
  {
/*
* ----- commented by Jesse_黄嘉伟 2017/09/09 ------
*
#if defined(BLINK_LEDS)
    HalLedSet ( HAL_LED_3, HAL_LED_MODE_FLASH );  // Flash LED to show failure
#endif
* 
*/
/* ------ Added by Jesse_黄嘉伟 2017/09/09 ----- */
    // 入网失败,熄灭网络指示灯
    Control_IndicatorLight(LIGHT_NEK, LIGHT_OFF);
/* ----------------------------------------- */        
  }

  // Pass the join confirm to higher layer if callback registered
  if (zdoCBFunc[ZDO_JOIN_CNF_CBID] != NULL )
  {
    zdoJoinCnf_t joinCnf;

    joinCnf.status = Status;
    joinCnf.deviceAddr = _NIB.nwkDevAddress;
    joinCnf.parentAddr = _NIB.nwkCoordAddress;

    zdoCBFunc[ZDO_JOIN_CNF_CBID]( (void*)&joinCnf );
  }

  // Notify ZDApp
  ZDApp_SendMsg( ZDAppTaskID, ZDO_NWK_JOIN_IND, sizeof(osal_event_hdr_t), (byte*)NULL );
}

在上面三个函数中添加自己的应用代码就能实现自己的网络指示灯应用功能了,如有疑问或补充,可在博客下方留言哦。

猜你喜欢

转载自blog.csdn.net/u012993936/article/details/77914052
今日推荐