我本仁慈,奈何苍天不许
分类: 嵌入式
2016-07-21 14:12:09
原文地址:BLE-NRF51822教程12-sdk中按键功能的使用 作者:ifndef
这一讲介绍一下sdk9.0中如何使用按键模块来实现自定义的按键功能。
关于sdk5.1中如何使用按键。在教程 剖析心率demo 教程中有关于按键的注册和按键事件发生后会如何回调自己注册的回调函数详细说明。
本讲教程也是在 sdk中的的uart例子 的基础上修改实现按键功能。Uart例子在以下目录中
XXX\Keil_v5\ARM\Pack\NordicSemiconductor\nRF_Examples\9.0.0\ble_peripheral\ble_app_uart
9.0sdk 中实现了一个BSP(板级支持包),主要是整合了按键模块的功能和一些”板级指令”以及与ble事件的交互。
板级指令主要是如下一些形如 BSP_INDICATE_IDLE,BSP_INDICATE_SCANNING,BSP_INDICATE_ADVERTISING等的指令。Bsp模块会根据这些指令来控制设备不同的外在表现。
比如在收到 IDLE指令是表示设备再空闲。Bsp模块会控制所有led灯处于关闭状态。而在收到SCANNING(作为主设备时)或者ADVERTISNG(作为从设备) 指令时控制某个特定的LED按照一定频率闪烁。
与BLE事件的交互其本质也是控制板子的”外在表现”,只不过控制的依据是BLE事件。比如bsp_btn_ble_sleep_mode_prepare 。该函数会在 广播超时事件发生后被调用。目的是为了在进入深度睡眠前 将某个按键设置为唤醒按键从而使设备在将来需要时再通过按键来唤醒。
再比如bsp_btn_ble_on_ble_evt 该函数, 该函数是放在BLE事件派发函数ble_evt_dispatch函数中的,其内部的实现就是判断是连接事件还是断开连接事件然后再做一些配置。
比如收到的ble事件是连接,那么可能就会配置一个按键用来可以在将来主动断开连接。
如果收到的是断开连接事件可能会配置某个按键来使设备可以通过按键进入睡眠状态。
对于使用 sdk中提供的按键功能。需要做的首先是初始化。bsp_init(BSP模块的初始化)和bsp_btn_ble_init(用来初始化上面说的bsp和BLE事件的交互)
通常sdk中提供的例子都会将这两个函数在封装到buttons_leds_init 函数中。
对于使用按键功能来说,要做的事情就比较少了。首先需要注册按键以及对应的事件
bsp_event_to_button_action_assign 该函数有3个参数,第一个参数是button id。通常与板子板子相关。比如我用的官方板pca10028有四个按键那么使用的id就是0-3,第二个参数是触发动作如APP_BUTTON_PUSH,APP_BUTTON_RELEASE分别表示注册的按键事件是按键按下和按键释放。 第三个参数是第二个参数指明的触发条件被触发后会产生的BSP事件。
第三个参数可能有点不容易理解。BSP模块中实现的按键功能在注册的按键事件触发后,不管是哪个按键,执行的处理函数都是一样的,处理过程就是根据按键按下或释放将上面说的bsp_event_to_button_action_assign的第三个参数,也就是bsp事件,传递给最终的bsp事件处理函数。 而这个 最终的bsp事件处理函数就是bsp_init函数中的第三个参数注册的回调函数。
也就是说。对于使用按键 我们要做的就是 选择一个按键,然后选择相应的动作,然后设置按键按下后会产生的事件。 然后我们在按键按下后要做的处理就是添加到 上面说的 bsp事件处理回调函数中(bsp_init函数中的第三个参数注册的回调函数)。
这样在你的按键按下时(注册的是push事件),就会产生对应的注册事件传递给BSP事件处理函数,函数中就会根据传递过来的事件执行你自己添加的处理函数。
比如uart模块中的BSP事件处理函数中就处理三个bsp事件
voidbsp_event_handler(bsp_event_t event)
{
uint32_t err_code;
switch (event)
{
case BSP_EVENT_SLEEP:
//注册为睡眠按键的按键被按下后就是执行这个分支
…………
……………
case BSP_EVENT_DISCONNECT:
//注册为断开连接按键的按键被按下后就是执行这个分支
………………………..
………………………….
case BSP_EVENT_WHITELIST_OFF:
……………………….
……………………..
default:
break;
}
}
Sdk中已经定义了很多事件
通常sdk中的例子里只使用了上面定义的几个事件。 所以我们在注册自己的按键事件时可以随便选择一个上面定义过的例子中没有使用的事件,然后在bsp事件处理函数中添加对这个事件的捕获 ( case 你的事件) 以及你的按键处理函数。
或者你也可以找到这个枚举结构体定义的地方然后 添加一个自己定义的特殊的事件。并在bsp事件处理函数中 捕获并作处理就可以了。
下面介绍实际操作。
因为uart中已经做过 bsp的初始化了(在buttons_leds_init函数中)
所以我们要做的就只是注册一个按键和对应的事件。
然后添加自己的处理代码就行了
在main函数中添加按键注册
int main(void)
{
uint32_t err_code;
boolerase_bonds;
uint8_t start_string[] = START_STRING;
// Initialize.
APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_MAX_TIMERS, APP_TIMER_OP_QUEUE_SIZE, false);
uart_init();
buttons_leds_init(&erase_bonds);
ble_stack_init();
gap_params_init();
services_init();
advertising_init();
conn_params_init();bsp_event_to_button_action_assign(3,BSP_BUTTON_ACTION_PUSH,BSP_EVENT_KEY_7;
……….
………
}
我的是官方板子pca10028有四个按键,我用的按键4,id就是3.
这里我设置了按键按下后会产生BSP_EVENT_KEY_7.其实合适的事件应该是BSP_EVENT_KEY_3, 这里用7 是为了说明产生说明事件完全是你自己定义的。Uart例子中key_7事件没被用到,那我这里就可以用他。而且你完全也可以不用他已经定义过的事件,自己去定义一个也行。
然后就是添加按键处理函数了。我在这里添加了打印处理
在main.c文件中的函数bsp_event_handler中捕获事件并作处理就行了
voidbsp_event_handler(bsp_event_t event)
{
uint32_t err_code;
switch (event)
{
case BSP_EVENT_SLEEP:
………………….
Break;
case BSP_EVENT_DISCONNECT:
……………………
break;
case BSP_EVENT_WHITELIST_OFF:
………………….
break;
case BSP_EVENT_KEY_7:
printf("push");
break;
default:
break;
}
}