本篇博文最后修改时间:2017年01月06日,11:06。
一、简介
本文介绍如何在SimpleBLECentral工程和SimpleBLEPeripheral工程中使用按键,并且剖析按键的初始化、响应的流程。
二、实验平台
协议栈版本:BLE-CC254x-1.4.0
编译软件:IAR 8.20.2
硬件平台:Smart RF开发板(主芯片CC2541)
三、版权声明
博主:甜甜的大香瓜
声明:喝水不忘挖井人,转载请注明出处。
原文地址:http://blog.csdn.NET/feilusia
联系方式:897503845@qq.com
香瓜BLE之CC2541群:127442605
香瓜BLE之CC2640群:557278427
五、基础知识
暂无
六、硬件原理图
1、普通按键
触发引脚:P0_1
常态:低电平
按下:高电平
松开:低电平
适合触发方式:上升沿触发
2、五向按键
原理:五向按键每一端连接或与芯片SN74HC32D,使得按下五向按键即可触发P2_0。随即从P0_6采集双级运算放大芯片TLV272输出的电压,来确定是五向按键的哪个脚。
1)触发
触发引脚:P2_0
触发引脚常态:低电平
触发引脚按下:高电平
触发引脚松开:低电平
适合触发方式:上升沿触发
2)采集
采集引脚:P0_6
无按键时电压:2.39V
按center键时电压:2.39V
按up键时电压:0.41V
按down键时电压:1.36V
按left键时电压:1.85V
按right键时电压:2.05V
七、实验步骤(SimpleBLEPeripheral工程)
注:SimpleBLECentral工程步骤也类似,只是少了几步去除代码中的宏定义“CC2540_MINIDK”的步骤。
1、IAR的宏定义
要想使用按键,首先在IAR的设置中的宏定义里添加“HAL_KEY = TRUE”;反之,则“HAL_KEY = FALSE”。
注:由于协议栈中有下面这段代码,因此即使IAR的宏定义设置中没有添加“HAL_KEY = TRUE”也可以使用按键。
/* Set to TRUE enable KEY usage, FALSE disable it */
#ifndef HAL_KEY
#define HAL_KEY TRUE
#endif
建议在IAR的宏定义中手动添加,以防出现不必要的错误。
2、修改应用层代码
1)应用层的按键事件入口处(SimpleBLEPeripheral.c中)
2)simpleBLEPeripheral_HandleKeys的声明(SimpleBLEPeripheral.c中)
3)simpleBLEPeripheral_HandleKeys函数(SimpleBLEPeripheral.c中)
把工程默认的按键处理也都删了,否则代码编译会报错。
4)注册按键事件(SimpleBLEPeripheral.c中)
2、按键驱动代码修改
1)修改按键S1的边沿触发方式(hal_key.c中)
#define HAL_KEY_SW_6_EDGE HAL_KEY_RISING_EDGE//HAL_KEY_FALLING_EDGE
由于我的板子适合上升沿触发,而协议栈默认是下降沿触发,因此这里配置成上升沿。
2)修改五向按键的边沿触发方式(hal_key.c中)
#define HAL_KEY_JOY_MOVE_EDGE HAL_KEY_RISING_EDGE//HAL_KEY_FALLING_EDGE
3)更正协议栈的错误代码(hal_key.c中)
// /* Rising/Falling edge configuratinn */
// HAL_KEY_JOY_MOVE_ICTL &= ~(HAL_KEY_JOY_MOVE_EDGEBIT); /* Clear the edge bit */
// /* For falling edge, the bit must be set. */
// #if (HAL_KEY_JOY_MOVE_EDGE == HAL_KEY_FALLING_EDGE)
// HAL_KEY_JOY_MOVE_ICTL |= HAL_KEY_JOY_MOVE_EDGEBIT;
// #endif
/* Rising/Falling edge configuratinn */
PICTL &= ~(HAL_KEY_JOY_MOVE_EDGEBIT); /* Clear the edge bit */
/* For falling edge, the bit must be set. */
#if (HAL_KEY_JOY_MOVE_EDGE == HAL_KEY_FALLING_EDGE)
PICTL |= HAL_KEY_JOY_MOVE_EDGEBIT;
#endif
原代码错将中断使能寄存器HAL_KEY_JOY_MOVE_ICTL(P2IEN)当做PICTL寄存器。详情如下:
#define HAL_KEY_JOY_MOVE_ICTL P2IEN /* Port Interrupt Control register */
4)修改HalKeyPoll函数(hal_key.c中)
// if (!(HAL_KEY_SW_6_PORT & HAL_KEY_SW_6_BIT)) /* Key is active low */
// {
// keys |= HAL_KEY_SW_6;
// }
if ((HAL_KEY_SW_6_PORT & HAL_KEY_SW_6_BIT)) /* Key is active high */
{
keys |= HAL_KEY_SW_6;
}
1.4.0的协议栈才要这么做。
八、解析按键初始化
1、复位按键的相关参数、变量
2、注册任务ID
3、正式初始化按键配置
下图默认开启中断,并且按键的回调函数注册为OnBoard_KeyCallback。
九、解析按键响应
1、扫描按键值
1)当硬件有按键时,则进入中断服务函数halProcessKeyInterrupt
2)HAL_KEY_EVENT事件
在Hal_ProcessEvent中的HAL_KEY_EVENT事件中扫描按键。
3)扫描按键值HalKeyPoll
2、将按键值送往上层的应用层
1)OnBoard_KeyCallback函数
2)OnBoard_SendKeys函数
通过osal_msg_send传递的消息,都会到选中的任务下的默认事件下(此时也就是simpleBLEPeripheral_TaskID任务的SYS_EVENT_MSG事件)。
3)应用层处理
十、解析按键中一处难点
1、难懂的代码
/* If any key is currently pressed down and interrupt
is still enabled, disable interrupt and switch to polling */
if( keys != 0 )
{
if( OnboardKeyIntEnable == HAL_KEY_INTERRUPT_ENABLE )
{
OnboardKeyIntEnable = HAL_KEY_INTERRUPT_DISABLE;
HalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback);
}
}
/* If no key is currently pressed down and interrupt
is disabled, enable interrupt and turn off polling */
else
{
if( OnboardKeyIntEnable == HAL_KEY_INTERRUPT_DISABLE )
{
OnboardKeyIntEnable = HAL_KEY_INTERRUPT_ENABLE;
HalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback);
}
}
OnBoard_KeyCallback函数中还有上面的一段代码很难理解,百度后无果,自己也是单步执行跑完按键流程后才理解这段代码的用途。
这段代码是实现中断方式和扫描方式互相切换。
作用是检测键值是否松开:
1)当“硬件上的按键不按为高电平,按下为低电平”时:下降沿触发时我们可以知道何时按键松开。
2)当“硬件上的按键不按为低电平,按下为高电平”时:上升沿触发时我们可以知道何时按键松开。
注:下面这个框中代码就是用于中断方式与查询方式来回切换用的。
它是指查询到键值回零后、由查询方式转为中断方式时,停止定时器。
2、详细分析
下面以“硬件上的按键不按为低电平,按下为高电平”、“上升沿触发”为前提,看下面的按键流程:
功能:中断方式检测按键按下、扫描方式检测按键松开。(按键松开会通知用户)
1)按键S1按下:
触发上升沿中断,发送键值“0x20”给应用层。
由中断触发方式切换成扫描方式。
2)按键S1松开:
扫描到引脚变化,则发送键值“0x00”给应用层。
由扫描方式切换回中断触发方式。
3、小实验
接下来测试下按键流程是否跟我解析的一致,这里只测试上升沿触发的情况。
1、代码修改:
static void simpleBLEPeripheral_HandleKeys( uint8 shift, uint8 keys )
{
VOID shift; // Intentionally unreferenced parameter
if ( keys & HAL_KEY_SW_6 )//上升沿触发,按键按下
{
NPI_PrintString("key is press!\r\n");
}
if ( keys == 0x00 ) //上升沿触发,按键松开
{
NPI_PrintString("key is loosen!\r\n");
}
}
2、实验现象:
按键按下时是中断方式发现按键,并发送0x20键值给应用层,此时显示“key is press!”。
按键松开时是扫描方式扫到按键,并发送0x00键值给应用层,此时显示“key is loosen!”。
实验结果与我分析的一致。