一、简介
本篇介绍如何在SimpleBLECentral工程和SimpleBLEPeripheral工程中使用按键,并且剖析按键的初始化、响应的流程。
二、实验平台
协议栈版本:BLE-CC254x-1.4.0
编译软件:IAR 8.20.2
硬件平台:Smart RF开发板
三、版权声明
博主:甜甜的大香瓜
声明:喝水不忘挖井人,转载请注明出处。
原文地址:http://blog.csdn.net/feilusia
联系方式:[email protected]
技术交流QQ群:127442605
四、硬件原理图
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、修改应用层代码(SimpleBLEPeripheral.c中)
1)应用层的按键事件入口处
2)simpleBLEPeripheral_HandleKeys的声明
3)simpleBLEPeripheral_HandleKeys函数
把工程默认的按键处理也都删了,否则代码编译会报错。
4)注册按键事件
2、按键驱动代码修改(hal_key.c)
1)修改按键S1的边沿触发方式
#define HAL_KEY_SW_6_EDGE HAL_KEY_RISING_EDGE//HAL_KEY_FALLING_EDGE由于我的板子适合上升沿触发,而协议栈默认是下降沿触发,因此这里配置成上升沿。
2)修改五向按键的边沿触发方式
#define HAL_KEY_JOY_MOVE_EDGE HAL_KEY_RISING_EDGE//HAL_KEY_FALLING_EDGE
3)更正协议栈的错误代码
// /* 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函数
// 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"); } }
按键按下时是中断方式发现按键,并发送0x20键值给应用层,此时显示“key is press!”。
按键松开时是扫描方式扫到按键,并发送0x00键值给应用层,此时显示“key is loosen!”。
实验结果与我分析的一致。