BLE开发笔记——协议栈HAL驱动控制LED

已经了解了OSAL工作原理和完成了启动过程的简单分析,那么我们可以尝试协议栈开发了,首先可以玩一下LED的控制,我有一个CC2541-DK MINI Keyfob,本文就以此为测试平台。

准备工作

新建完整的协议栈工程

这里以SimpleBLEPeripheral例程为基础新建工程,方法可以参考 BLE开发笔记——简单新建属于自己的协议栈工程

配置工程

  • 选择配置文件CC2541
  • 右键单击工程,选择Options…,启动Options窗口
  • 选择左边栏General Options下的C/C++ Compiler,然后在右侧选择Preprocessor选项卡,操作正确的话,应该会看到Defined symbols:(one per line),要修改其中的宏定义:
    • 修改HAL_LED=FALSEHAL_LED=TRUE
    • 修改POWER_SAVINGxPOWER_SAVING以禁用低功耗管理

注:

上述禁用低功耗的原因是协议栈默认LED为耗能元件,系统每次在进入休眠模式的时候会把LED关闭,当唤醒的时候有回复LED的状态,如果不禁用低功耗,LED会一直循环闪烁。

配置硬件

如果你所使用的硬件平台是TI官方开发套件或者是仿TI的硬件,此部分的操作可以忽略,不过我认为还是需要了解一下的。

如果是非官方的设计,对应HAL驱动中LED管脚有可能与官方蓝牙开发套件的设计有区别,官方开发板上LED1对应芯片的P1_0管脚,如果多于一个LED,那么LED2对应P1_1,LED3对应P1_4,LED的配置文件可以在IAR工程目录HAL--->Target--->CC2540EB--->Config找到,名为hal_board_cfg.h,所以我们可以修改此文件来适配自己设计的硬件电路,默认LED配置代码如下:

/* LED Configuration */

#if defined (HAL_BOARD_CC2530EB_REV17) && !defined (HAL_PA_LNA) && !defined (HAL_PA_LNA_CC2590)
    #define HAL_NUM_LEDS                 3
#elif defined (HAL_BOARD_CC2530EB_REV13) || defined (HAL_PA_LNA) || defined (HAL_PA_LNA_CC2590)
    #define HAL_NUM_LEDS                 1
#else
    #error Unknown Board Indentifier
#endif

#define HAL_LED_BLINK_DELAY()   st( { volatile uint32 i; for (i=0; i<0x5800; i++) { }; } )

/* 1 - Green */
#define LED1_BV                        BV(0)
#define LED1_SBIT                      P1_0
#define LED1_DDR                       P1DIR
#define LED1_POLARITY                  ACTIVE_HIGH

#ifdef HAL_BOARD_CC2530EB_REV17
    /* 2 - Red */
    #define LED2_BV                      BV(1)
    #define LED2_SBIT                    P1_1
    #define LED2_DDR                     P1DIR
    #define LED2_POLARITY                ACTIVE_HIGH

    /* 3 - Yellow */
    #define LED3_BV                      BV(4)
    #define LED3_SBIT                    P1_4
    #define LED3_DDR                     P1DIR
    #define LED3_POLARITY                ACTIVE_HIGH
#endif

还要注意LED1_POLARITY是来配置IO控制LED发光的有效电平的,默认的Active_HIGH代表IO输出高电平时LED亮,假如我们所用的硬件电路LED连接在了P0_3上,而且是低电平点亮LED,那么若想用LED1控制,那么可以修改LED1的四句配置为下面的样子:

/* 1 - Green */
#define LED1_BV                        BV(3)
#define LED1_SBIT                      P0_3
#define LED1_DDR                       P0DIR
#define LED1_POLARITY                  ACTIVE_LOW

HAL_LED函数及宏定义

控制LED使用的是HalLedSet函数,有两个参数,第一个参数是LED名称宏定义,第二个参数是LED工作模式宏定义,使用如下:

HalLedSet( HAL_LED_1, HAL_LED_MODE_ON );

这里我们只需要操作LED1,所以第一个参数就用HAL_LED_1就行,LED工作模式宏定义如下:

#define HAL_LED_MODE_OFF     0x00   // 关闭LED
#define HAL_LED_MODE_ON      0x01   // 打开LED
#define HAL_LED_MODE_BLINK   0x02   // 闪烁一次
#define HAL_LED_MODE_FLASH   0x04   // 不断的闪烁,最多255次
#define HAL_LED_MODE_TOGGLE  0x08   // 翻转LED状态

点亮LED

  • 首先我们要保证初始化的时候LED是灭的,所以在SimpleBLEPeripheral_Init函数(在simpleBLEPeripheral.c文件中)的最后执行关闭LED的语句:

    void SimpleBLEPeripheral_Init( uint8 task_id )
    {
        simpleBLEPeripheral_TaskID = task_id;
    
        // Setup the GAP
        VOID GAP_SetParamValue( TGAP_CONN_PAUSE_PERIPHERAL, DEFAULT_CONN_PAUSE_PERIPHERAL );
    
        .
        .
        .
    
        // 关闭LED
        HalLedSet( HAL_LED_1, HAL_LED_MODE_OFF );
        // Setup a delayed profile startup
        osal_set_event( simpleBLEPeripheral_TaskID, SBP_START_DEVICE_EVT );
    
    }
    
  • 然后在SimpleBLEPeripheral_ProcessEventSBP_START_DEVICE_EVT**事件处理中加上点亮LED的语句:

    if ( events & SBP_START_DEVICE_EVT )
    {
        // Start the Device
        VOID GAPRole_StartDevice( &simpleBLEPeripheral_PeripheralCBs );
    
        // Start Bond Manager
        VOID GAPBondMgr_Register( &simpleBLEPeripheral_BondMgrCBs );
    
        // 点亮LED
        HalLedSet( HAL_LED_1, HAL_LED_MODE_ON );
    
        // Set timer for first periodic event
        osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD );
    
        return ( events ^ SBP_START_DEVICE_EVT );
    }
    
  • 编译下载到电路板上,顺利的话可以看到启动后LED保持常亮。

BLINK和FLASH

LED的BLINK和FLASH工作模式效果都是闪烁,不过BLINK是闪烁一次,FLASH是闪烁多次,我们也可以用上面点亮LED的方式测试BLINK和FLASH工作模式,只需更改上面HalLedSet( HAL_LED_1, HAL_LED_MODE_ON );即可,工作模式改为HAL_LED_MODE_BLINKHAL_LED_MODE_FLASH。_

其实我们可以配置闪烁的周期时间和LED亮所占时间比,FLASH还可以设置闪烁次数,虽然可以闪烁多次,但最多可以闪烁255次,找到工程文件的hal_led.h文件,会看到如下的配置代码(在这里加了注释):

/* Defaults */
#define HAL_LED_DEFAULT_MAX_LEDS      4         // LED数量
#define HAL_LED_DEFAULT_DUTY_CYCLE    5         // LED亮的占空比,数值是百分比,这里是闪烁周期时间的5%
#define HAL_LED_DEFAULT_FLASH_COUNT   50        // FLASH工作模式的闪烁次数  
#define HAL_LED_DEFAULT_FLASH_TIME    1000      // 闪烁周期时间,单位ms,这里周期是1s

可以根据自己需求更改上述的宏定义即可。

LED状态翻转

工作模式使用宏定义HAL_LED_MODE_TOGGLE,在这里我们可以使用定时器触发事件的方式测试这个工作模式。

  • 任务初始化中关闭LED

    void SimpleBLEPeripheral_Init( uint8 task_id )
    {
        simpleBLEPeripheral_TaskID = task_id;
    
        // Setup the GAP
        VOID GAP_SetParamValue( TGAP_CONN_PAUSE_PERIPHERAL, DEFAULT_CONN_PAUSE_PERIPHERAL );
    
        .
        .
        .
    
        // 关闭LED
        HalLedSet( HAL_LED_1, HAL_LED_MODE_OFF );
        // Setup a delayed profile startup
        osal_set_event( simpleBLEPeripheral_TaskID, SBP_START_DEVICE_EVT );
    
    }
    
  • 定义LED翻转事件,这个需要在simpleBLEPeripheral.h文件中添加事件的宏定义SBP_LED_TOGGLE_EVT,默认有两个事件的宏定义,只需添加我们的就可以,事件标识ID是WORD,所以最多可以设置16个事件,一位一个事件,如下的样子:

    // Simple BLE Peripheral Task Events
    #define SBP_START_DEVICE_EVT                              0x0001
    #define SBP_PERIODIC_EVT                                  0x0002
    #define SBP_LED_TOGGLE_EVT                                0x0004
    
  • 添加事件的触发定时器,在SimpleBLEPeripheral_ProcessEvent的设备启动事件处理中添加即可:

    if ( events & SBP_START_DEVICE_EVT )
    {
        // Start the Device
        VOID GAPRole_StartDevice( &simpleBLEPeripheral_PeripheralCBs );
    
        // Start Bond Manager
        VOID GAPBondMgr_Register( &simpleBLEPeripheral_BondMgrCBs );
    
        // 为LED翻转事件设置触发定时器,时间为500ms    
        osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_LED_TOGGLE_EVT, 500 );
    
        // Set timer for first periodic event
        osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD );
    
        return ( events ^ SBP_START_DEVICE_EVT );
    }
    
  • 可以在设备启动事件处理代码的下面,添加LED翻转事件的处理代码,每个事件的处理后面一定要清掉事件标识:

    // LED翻转事件
    if ( events & SBP_LED_TOGGLE_EVT )
    {
        HalLedSet( HAL_LED_1, HAL_LED_MODE_TOGGLE );                                // 翻转LED
        osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_LED_TOGGLE_EVT, 500 );  // 重新设置定时器以实现周期触发事件
        return ( events ^ SBP_LED_TOGGLE_EVT );                                     // 处理完事件,消除事件标识
    }
    
  • 编译,下载程序到开发板,一切顺利的话,led每500ms就会翻转一次状态。


ble

2381 字

2016-05-05 08:44 +0800