低功耗蓝牙cc2541学习笔记之LED-2

文章转自:http://blog.csdn.net/anobodykey/article/details/8486578

InitBoard()看注释上说是初始化板子上的I/O资源,进入到该函数实现体中,

void InitBoard( byte level )
{
  if ( level == OB_COLD )
  {
    // Interrupts off
    osal_int_disable( INTS_ALL );
    // Turn all LEDs off
    HalLedSet( HAL_LED_ALL, HAL_LED_MODE_OFF );
    // Check for Brown-Out reset
    ChkReset();
  }
  else  // !OB_COLD
  {
#ifdef ZTOOL_PORT
    MT_SysResetInd();
#endif

     /* Initialize Key stuff */
    OnboardKeyIntEnable = HAL_KEY_INTERRUPT_DISABLE;
    HalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback);
  }
}

从主函数中传递进来的是OB_COLD,该值为0,进来之后又是关闭中断,(貌似前面也没有打开过),之后进入HalLedSet()函数中,关闭所有LEDs,进入该函数中,

uint8 HalLedSet (uint8 leds, uint8 mode)
{

#if (defined (BLINK_LEDS)) && (HAL_LED == TRUE)
  uint8 led;
  HalLedControl_t *sts;

  switch (mode)
  {
    case HAL_LED_MODE_BLINK:
      /* Default blink, 1 time, D% duty cycle */
      HalLedBlink (leds, 1, HAL_LED_DEFAULT_DUTY_CYCLE, HAL_LED_DEFAULT_FLASH_TIME);
      break;

    case HAL_LED_MODE_FLASH:
      /* Default flash, N times, D% duty cycle */
      HalLedBlink (leds, HAL_LED_DEFAULT_FLASH_COUNT, HAL_LED_DEFAULT_DUTY_CYCLE, HAL_LED_DEFAULT_FLASH_TIME);
      break;

    case HAL_LED_MODE_ON:
    case HAL_LED_MODE_OFF:
    case HAL_LED_MODE_TOGGLE:

      led = HAL_LED_1;
      leds &= HAL_LED_ALL;
      sts = HalLedStatusControl.HalLedControlTable;

      while (leds)
      {
        if (leds & led)
        {
          if (mode != HAL_LED_MODE_TOGGLE)
          {
            sts->mode = mode;  /* ON or OFF */
          }
          else
          {
            sts->mode ^= HAL_LED_MODE_ON;  /* Toggle */
          }
          HalLedOnOff (led, sts->mode);
          leds ^= led;
        }
        led <<= 1;
        sts++;
      }
      break;

    default:
      break;
  }

#elif (HAL_LED == TRUE)
  LedOnOff(leds, mode);
#else
  // HAL LED is disabled, suppress unused argument warnings
  (void) leds;
  (void) mode;
#endif /* BLINK_LEDS && HAL_LED   */

  return ( HalLedState );

}

首先是两个宏定义判断BLINK_LEDS以及HAL_LED,用于判断板子是否有LED资源,是否使能闪烁功能,可以找到定义处两个条件都符合,而后是一个HalLedControl_t结构体变量,查看该结构体定义

typedef struct {
  uint8 mode;       /* Operation mode */
  uint8 todo;       /* Blink cycles left */
  uint8 onPct;      /* On cycle percentage */
  uint16 time;      /* On/off cycle time (msec) */
  uint32 next;      /* Time for next change */
} HalLedControl_t;

用该结构体来控制LED资源,了解一下就行,接下来就是对mode的判断有5的宏定义

/* Modes */
#define HAL_LED_MODE_OFF     0x00
#define HAL_LED_MODE_ON      0x01
#define HAL_LED_MODE_BLINK   0x02
#define HAL_LED_MODE_FLASH   0x04
#define HAL_LED_MODE_TOGGLE  0x08

在switch中可以看到BLINK与FLASH的区别就是BLINK只闪烁一次,而FLASH闪烁N次,两者都调用的是HalLedBlink (uint8 leds, uint8 numBlinks, uint8 percent, uint16 period)函数,只是第二个参数不同,这些参数有一些默认值如下

/* Defaults */
#define HAL_LED_DEFAULT_MAX_LEDS      4
#define HAL_LED_DEFAULT_DUTY_CYCLE    5
#define HAL_LED_DEFAULT_FLASH_COUNT   50
#define HAL_LED_DEFAULT_FLASH_TIME    1000
进入HalLedBlink函数查看

void HalLedBlink (uint8 leds, uint8 numBlinks, uint8 percent, uint16 period)
{
#if (defined (BLINK_LEDS)) && (HAL_LED == TRUE)
  uint8 led;
  HalLedControl_t *sts;

  if (leds && percent && period)
  {
    if (percent < 100)
    {
      led = HAL_LED_1;
      leds &= HAL_LED_ALL;
      sts = HalLedStatusControl.HalLedControlTable;

      while (leds)
      {
        if (leds & led)
        {
          /* Store the current state of the led before going to blinking */
          preBlinkState |= (led & HalLedState);

          sts->mode  = HAL_LED_MODE_OFF;                    /* Stop previous blink */
          sts->time  = period;                              /* Time for one on/off cycle */
          sts->onPct = percent;                             /* % of cycle LED is on */
          sts->todo  = numBlinks;                           /* Number of blink cycles */
          if (!numBlinks) sts->mode |= HAL_LED_MODE_FLASH;  /* Continuous */
          sts->next = osal_GetSystemClock();                /* Start now */
          sts->mode |= HAL_LED_MODE_BLINK;                  /* Enable blinking */
          leds ^= led;
        }
        led <<= 1;
        sts++;
      }
      osal_set_event (Hal_TaskID, HAL_LED_BLINK_EVENT);
    }
    else
    {
      HalLedSet (leds, HAL_LED_MODE_ON);                    /* >= 100%, turn on */
    }
  }
  else
  {
    HalLedSet (leds, HAL_LED_MODE_OFF);                     /* No on time, turn off */
  }
#elif (HAL_LED == TRUE)
  percent = (leds & HalLedState) ? HAL_LED_MODE_OFF : HAL_LED_MODE_ON;
  HalLedOnOff (leds, percent);                              /* Toggle */
#else
  // HAL LED is disabled, suppress unused argument warnings
  (void) leds;
  (void) numBlinks;
  (void) percent;
  (void) period;
#endif /* BLINK_LEDS && HAL_LED */
}
一进来是宏定义判断,没啥可说的,然后对参数进行判断,得保证参数正确才行,之后将led赋值为LED1,leds与LED_ALL相与得到需要闪烁的leds值,后面用到了一个HalLedStatusControl变量,查看定义

#ifdef BLINK_LEDS
  static HalLedStatus_t HalLedStatusControl;
#endif
typedef struct
{
  HalLedControl_t HalLedControlTable[HAL_LED_DEFAULT_MAX_LEDS];
  uint8           sleepActive;
} HalLedStatus_t;
#define HAL_LED_DEFAULT_MAX_LEDS      4

相当于建立了一个数组,里面放的是4个led资源,统一管理,并将sts指针指向HalLedControlTable,然后扫描leds的每一位从低位开始,闪烁置位的LED资源,这里面用到了preBlinkState变量,

static uint8 preBlinkState;            // Original State before going to blink mode
                                       // bit 0, 1, 2, 3 represent led 0, 1, 2, 3

用于存储进入闪烁模式之前的状态,以及HalLedState变量,存储当前LED状态,HalLedState变量的值在别处有修改,跟其他结合着看就明白了,然后就是为sts指向的HalLedControl_t成员变量赋值,if (!numBlinks) sts->mode |= HAL_LED_MODE_FLASH;这句话说是继续的意思,但目前没理解还,先继续往下看,用到一个osal_GetSystemClock()函数:

uint32 osal_GetSystemClock( void )
{
  return ( osal_systemClock );
}

// Milliseconds since last reboot
static uint32 osal_systemClock;

返回的是一个32位整型值,显示当前时钟,现在也还没理解这个next的含义,接着更换模式为BLINK,然后将这位清零,然后扫描下一位,4个LED资源扫描完毕之后(虽然这个板子只有两个LED),进入了osal_set_event()函数有两个参数

uint8 Hal_TaskID;
#define HAL_LED_BLINK_EVENT   0x0002

uint8 osal_set_event( uint8 task_id, uint16 event_flag )
{
  if ( task_id < tasksCnt )
  {
    halIntState_t   intState;
    HAL_ENTER_CRITICAL_SECTION(intState);    // Hold off interrupts
    tasksEvents[task_id] |= event_flag;  // Stuff the event bit(s)
    HAL_EXIT_CRITICAL_SECTION(intState);     // Release interrupts
  }
   else
    return ( INVALID_TASK );

  return ( SUCCESS );
}

看名字的意思是设置ID和LED的BLINK事件,进入该函数有个tasksCnt变量

const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] );
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
  GenericApp_ProcessEvent
};

typedef unsigned short (*pTaskEventHandlerFn)( unsigned char task_id, unsigned short event );

InitBoard()函数貌似比前面的要复杂的多,跳了好几层,tasksCnt是事件的个数,目前还不能知道具体值,这个应该涉及到os层了,鸭梨来了那,首先判断任务ID是否超过任务数,检查其合法性,又碰到一个宏定义,形似函数并且字母都是大写的肯定就是宏定义了,

#define HAL_ENTER_CRITICAL_SECTION(x)   st( x = EA;  HAL_DISABLE_INTERRUPTS(); )
#define HAL_EXIT_CRITICAL_SECTION(x)    st( EA = x; )

第一个宏定义先获取当前EA的值,然后关掉中断,第二个宏定义是将EA的值恢复原值,要说好处嘛,可以不用管当前中断是否打开,对程序也没有影响,他们中间那条语句是为该任务设置事件标志,tasksEvents是一个指针,目前还没见到初始化,留待以后查看,最后返回到上一层。

回到HalLedBlink()函数,当percent大于等于100时,也就是超过100%,LED应当长亮即HalLedSet()函数来实现,当leds、percent、period有不合法的值时LED长灭,通用是用HalLedSet()函数实现,跑到HalLedBlink()函数的调用者去了,先把HalLedBlink()函数看完之后再去继续查看HalLedSet()函数吧,当没有定义BLINK_LEDS时,只是改变LED的状态,这里他用percent存储结果有点误人,不过这样可以充分利用内存资源,不用重新定义一个变量存储结果,加个注释会更好,leds和HalLedState相与得到当前状态,如果为1,那么就利用HalLedOnOff()函数关闭它,如果为0,就打开它,总之就是使得LED状态取反。这一节涉及到的函数实在是太多了,不晓得后面会不会更多?

HalLedOnOff()函数比较简单

void HalLedOnOff (uint8 leds, uint8 mode)
{
  if (leds & HAL_LED_1)
  {
    if (mode == HAL_LED_MODE_ON)
    {
      HAL_TURN_ON_LED1();
    }
    else
    {
      HAL_TURN_OFF_LED1();
    }
  }

  if (leds & HAL_LED_2)
  {
    if (mode == HAL_LED_MODE_ON)
    {
      HAL_TURN_ON_LED2();
    }
    else
    {
      HAL_TURN_OFF_LED2();
    }
  }

  if (leds & HAL_LED_3)
  {
    if (mode == HAL_LED_MODE_ON)
    {
      HAL_TURN_ON_LED3();
    }
    else
    {
      HAL_TURN_OFF_LED3();
    }
  }

  if (leds & HAL_LED_4)
  {
    if (mode == HAL_LED_MODE_ON)
    {
      HAL_TURN_ON_LED4();
    }
    else
    {
      HAL_TURN_OFF_LED4();
    }
  }

  /* Remember current state */
  if (mode)
  {
    HalLedState |= leds;
  }
  else
  {
    HalLedState &= (leds ^ 0xFF);
  }
}

最后,将HalLedState赋为新的状态值。至此,HalLedBlink()函数就查看完了,返回到上一层HalLedSet()函数中继续查看。

在switch的判断中只剩下ON、OFF、以及TOGGLE三个case了,共用一段代码,比BLINK的简单多了也,有一个不理解的地方,当mode为TOGGLE时sts->mode又和ON异或了一下,除非当前mode是OFF,之后就会执行点亮LED操作,而当模式为On,都是执行的关掉LED操作,其他模式执行的也是关闭操作,但却为HalLedState相应位置1,总感觉有点矛盾?!当系统没有定义LED闪烁的时候直接调用LedOnOff()函数,可惜没有找到实现体,虽然这个函数的确不会执行。至此,HalLedSet()函数查看完毕了,返回上一层InitBoard()函数,进入到ChkRest()函数中,进行低压复位检测,进入该函数查看

void ChkReset( void )
{
  uint8 led;
  uint8 rib;

  // Isolate reset indicator bits
  rib = SLEEPSTA & LRESET;

  if ( rib == RESETPO )
  {
    // Put code here to handle Power-On reset
  }
  else if ( rib == RESETEX )
  {
    // Put code here to handle External reset
  }
  else if ( rib == RESETWD )
  {
    // Put code here to handle WatchDog reset
  }
  else
  {
    // Unknown, hang and blink
    HAL_DISABLE_INTERRUPTS();
    led = HAL_LED_4;
    while ( 1 ) {
      HalLedSet( led, HAL_LED_MODE_ON );
      MicroWait( 62500 );
      MicroWait( 62500 );
      HalLedSet( led, HAL_LED_MODE_OFF );
      MicroWait( 37500 );
      MicroWait( 37500 );
      if ( !(led >>= 1) )
        led = HAL_LED_4;
    }
  }
}

在该函数中是检测SLEEPSTA的RST属性,LRESET的值为0x18,即检测SLEEPSTA的3、4位如下


当值不是00,01,10的情况下,就是我们所需要的检测

// Reset bit definitions
#define LRESET     0x18  // Last reset bit mask
#define RESETPO    0x00  // Power-On reset
#define RESETEX    0x08  // External reset
#define RESETWD    0x10  // WatchDog reset

这里是进行闪烁操作,这里是从LED4开始到LED1循环闪烁,代码前面都叙述过了,在此就不赘述了,返回上一层InitBorad()函数。

在else中即非冷启动下有一个宏定义,通过查找定义找到如下代码

#if defined (ZTOOL_P1)
  #define ZTOOL_PORT SERIAL_PORT1
#elif defined (ZTOOL_P2)
  #define ZTOOL_PORT SERIAL_PORT2
#else
  #undef ZTOOL_PORT
#endif

取的是第一个定义,但是ZTOOL_P1却找不到定义,也许在别处还有吧,进入MT_SystemResetInd()函数中查看

void MT_SysResetInd(void)
{
  uint8 retArray[6];

  retArray[0] = ResetReason();   /* Reason */
  retArray[1] = 0x00;            /* Transport Revision */
  retArray[2] = 0x00;            /* Product */
  retArray[3] = 0x00;            /* Major Revision */
  retArray[4] = 0x00;            /* Minor Revision */
  retArray[5] = 0x00;            /* Hardware Revision */

  /* Send out Reset Response message */
  MT_BuildAndSendZToolResponse(((uint8)MT_RPC_CMD_AREQ | (uint8)MT_RPC_SYS_SYS), MT_SYS_RESET_IND,
                                sizeof(retArray), retArray);
}

/* Reset reason for reset indication */
#define ResetReason() ((SLEEPSTA >> 3) & 0x03)
typedef enum {
  MT_RPC_CMD_POLL = 0x00,
  MT_RPC_CMD_SREQ = 0x20,
  MT_RPC_CMD_AREQ = 0x40,
  MT_RPC_CMD_SRSP = 0x60,
  MT_RPC_CMD_RES4 = 0x80,
  MT_RPC_CMD_RES5 = 0xA0,
  MT_RPC_CMD_RES6 = 0xC0,
  MT_RPC_CMD_RES7 = 0xE0
} mtRpcCmdType_t;

typedef enum {
  MT_RPC_SYS_RES0,   /* Reserved. */
  MT_RPC_SYS_SYS,
  MT_RPC_SYS_MAC,
  MT_RPC_SYS_NWK,
  MT_RPC_SYS_AF,
  MT_RPC_SYS_ZDO,
  MT_RPC_SYS_SAPI,   /* Simple API. */
  MT_RPC_SYS_UTIL,
  MT_RPC_SYS_DBG,
  MT_RPC_SYS_APP,
  MT_RPC_SYS_MAX     /* Maximum value, must be last */
  /* 10-32 available, not yet assigned. */
} mtRpcSysType_t;
#define MT_SYS_RESET_IND                     0x80

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值