SDK:nRF5_SDK_12.2.0
实验一用于讲解 nRF52832 SDK v12.2.0 关于 LED 灯及 BUTTON 按键的板级支持函数及使用方法。利用板级支持函数可以控制在硬件上设置 LED 灯的有效状态(高电平亮还是低电平亮),在软件上配置 LED 的管脚和数量则可以方便地读取并设置 LED 的状态,达到快速开发的目的,BUTTON 按键与 LED 灯实现原理类似。
官方例程代码入口 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);
}
}
}
上文例程的 bsp 前缀函数位于在 MDK5 Project:Board Definition\boards.c 文件中,该文件用于存放板级支持函数(如 LED、BUTTON),其头文件为 boards.h。
在 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 应填入列表 */
在 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;
● 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 ,此处不再讲解。)
接下通过一个实验演示上文函数,让 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);
}
}
官方 SDK 外设工程目录下还有基于 FreeRTOS 的 blinky_freertos 例程可供学习。此外上文提到的nrf_delay_ms() 毫秒级延时函数是利用软件机器周期延时,外设工程目录下有一个 blinky_systick 例程利用滴答定时器准确延时(在nRF52832中,默认不使用 systick,似乎为了节省功耗?)