[nRF52832] 外设篇 | 实验一 LED 灯 及 BUTTON 按键

SDK:nRF5_SDK_12.2.0

1. 概述

  实验一用于讲解 nRF52832 SDK v12.2.0 关于 LED 灯及 BUTTON 按键的板级支持函数及使用方法。利用板级支持函数可以控制在硬件上设置 LED 灯的有效状态(高电平亮还是低电平亮),在软件上配置 LED 的管脚和数量则可以方便地读取并设置 LED 的状态,达到快速开发的目的,BUTTON 按键与 LED 灯实现原理类似。

1.1 工程目录

  • 进入官方 SDK 外设工程目录的 blinky 例程,该例程提供 LED 闪烁的模板;
    ..\nRF5_SDK_12.2.0_f012efa\examples\peripheral\blinky\
  • 依次进入 pca10040 板型,s132 版本协议栈,arm5(MDK5) 开发环境目录 ,打开 Keil 工程文件。
    …\blinky\pca10040\s132\arm5_no_pack\blinky_pca10040_s132.uvprojx

1.2 工程讲解

  官方例程代码入口 MDK5 Project:Application\main.c 中,如下文代码所示,在主函数 main() 中调用 bsp_board_leds_init() 函数初始化 LED 设备,while 循环任务中每隔 500ms 反转一次所有的 LED 灯(共 LEDS_NUMBER 个 LED 灯)的亮灭。

int main(void)
{
    /* Configure board. */
    bsp_board_leds_init();

    /* Toggle LEDs. */
    while (true)
    {
        for (int i = 0; i < LEDS_NUMBER; i++)
        {
            bsp_board_led_invert(i);
            nrf_delay_ms(500);
        }
    }
}

2. 定义与声明

  上文例程的 bsp 前缀函数位于在 MDK5 Project:Board Definition\boards.c 文件中,该文件用于存放板级支持函数(如 LED、BUTTON),其头文件为 boards.h

2.1 宏定义

  在 board.c 跟 board.h 文件中引用了一些 LED 前缀的宏定义,这些宏定义被定义在 pca10040.h(选择哪块板就是哪个板级配置头文件) 中,如下所示:

// LEDs definitions for PCA10040
#define LEDS_NUMBER    4                            /*!< 定义 LED 的个数 */
#define LED_START      17                           /*!< 定义第一个 LED 的控制管脚号 */
#define LED_1          17                           /*!< 定义 LED_1 的管脚号 */
#define LED_2          18                           /*!< 定义 LED_2 的管脚号 */
#define LED_3          19                           /*!< 定义 LED_3 的管脚号 */
#define LED_4          20                           /*!< 定义 LED_4 的管脚号 */
#define LED_STOP       20                           /*!< 定义最后一个 LED 控制管脚号 */

#define LEDS_ACTIVE_STATE 0                         /*!< 定义 LED 有效状态:0-低电平,1-高电平 */

#define LEDS_LIST { LED_1, LED_2, LED_3, LED_4 }    /*!< LED 列表,上面定义的 LED 应填入列表 */

2.1 LED 数组缓冲区

  在 board.c 声明了一个静态常量全局数组 m_board_led_list,用于存放 LED 列表,空间大小为 LEDS_NUMBER,内容为上文宏定义中的 LEDS_LIST ,由此我们可知当 led_idx = 0 时,m_board_led_list[led_idx] 为 LED_1,其他 LED 依次类推。

static const uint8_t m_board_led_list[LEDS_NUMBER] = LEDS_LIST;

3. 函数接口

void bsp_board_leds_init(void)

用途:初始化所有的 LED 灯设备
参数:无
返回:无

bool bsp_board_led_state_get(uint32_t led_idx)

用途:获取 led_idx 的 LED 的当前状态
参数:- led_idx:LED列表序号,最大等于LEDS_NUMBER-1
返回:- true(1):LED 亮
   - flase(0):LED 灭

  这里值得注意的是:在硬件上板级 LED 统一使用同一种有效状态,即 LEDS_ACTIVE_STATE 配置高电平亮(有效)或者低电平亮(有效),默认为0-低电平亮(有效),调用该函数对高低电平亮做了兼容,用户在软件上只需关注 true 跟 flase 就可以。
void bsp_board_led_on(uint32_t led_idx)

用途:设置 led_idx 的 LED 亮
参数:- led_idx:LED列表序号,最大等于LEDS_NUMBER-1
返回:无

void bsp_board_led_off(uint32_t led_idx)

用途:设置 led_idx 的 LED 灭
参数:- led_idx:LED列表序号,最大等于LEDS_NUMBER-1
返回:无

void bsp_board_led_invert(uint32_t led_idx)

用途:反转 led_idx 的 LED 状态
参数:- led_idx:LED列表序号,最大等于LEDS_NUMBER-1
返回:无

void bsp_board_leds_off(void)

用途:关闭所有的 LED 灯
参数:无
返回:无

void bsp_board_leds_on(void)

用途:打开所有的 LED 灯
参数:无
返回:无

uint32_t bsp_board_pin_to_led_idx(uint32_t pin_number)

用途:将 LED 的管脚序号转化成 LED 的灯序号
参数:- pin_number :GPIO管脚序号
返回:- 0xFFFFFFFF 无效管脚序号
   - 其他值: LED 的灯序号

uint32_t bsp_board_led_idx_to_pin(uint32_t led_idx)

用途:将 LED 的灯序号转化成 LED 的管脚序号
参数:- led_idx:LED列表序号,最大等于LEDS_NUMBER-1
返回:- GPIO管脚序号

  具体函数实现方式在board.c,相对比较简单,可自行通过阅读代码学习,该文件还包含 BUTTON 的板级支持函数,原理类似于 LED ,此处不再讲解。)

3. 实验

  接下通过一个实验演示上文函数,让 LED_0 1s 闪烁一次,LED_1 状态跟随 LED_0, LED2 状态与 LED_0 相反。

int main(void)
{
    /* 初始化所有的 LED 灯设备 */
    bsp_board_leds_init();
    while(true)
    {
        /* 反转 LED_0 状态 */
        bsp_board_led_invert(0);                    
        /* 读取 LED_0 状态 */
        if(true == bsp_board_led_state_get(0))      
        {
            /* 若 LED_0 亮,则点亮 LED_1, 熄灭 LED_2 */
            bsp_board_led_on(1);
            bsp_board_led_off(2);
        }
        else
        {
            /* 若 LED_0 灭,则熄灭 LED_1, 点亮 LED_2 */
            bsp_board_led_off(1);
            bsp_board_led_on(2);
        }
        /* 延时软件1s */
        nrf_delay_ms(1000);
    }
}

4. 拓展

  官方 SDK 外设工程目录下还有基于 FreeRTOS 的 blinky_freertos 例程可供学习。此外上文提到的nrf_delay_ms() 毫秒级延时函数是利用软件机器周期延时,外设工程目录下有一个 blinky_systick 例程利用滴答定时器准确延时(在nRF52832中,默认不使用 systick,似乎为了节省功耗?)

你可能感兴趣的:([nRF52832])