本篇博文最后改动时间:2017年01月06日,11:06。
一、简单介绍
本文以SimpleBLEPeripheral为例,介绍怎样将普通IO口(P12)自己定义为长短按键,实现按键3S以内松开为短按键、3S之后松开为长按键。
注:本文加入按键方法不与协议栈的按键相冲突,协议栈自带的按键仍可正常使用。
二、实验平台
协议栈版本号: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、编写并加入自己定义的按键驱动
1)写一个按键驱动Key.C(存放在“……BLE-CC254x-1.4.0ProjectsleSimpleBLEPeripheralSourceGUA”路径下)
//****************************************************************************** //name: Key.c //introduce: 香瓜自己定义的按键驱动 //author: 甜甜的大香瓜 //changetime: 2016.2.23 //email: 897503845@qq.com //****************************************************************************** #include <ioCC2540.h> #include "Key.h" /*********************宏定义************************/ //注冊时使用的宏 #define NO_TASK_ID 0xFF //没有注冊时的任务id #define NO_EVEN_ID 0x0000 //没有注冊时的事件id //中断消抖时使用的宏 #define KEY_DEBOUNCE_VALUE 20 //消抖时间20ms #ifndef false #define false 0 #endif #ifndef true #define true 1 #endif typedef signed char int8; //!< Signed 8 bit integer typedef unsigned char uint8; //!< Unsigned 8 bit integer typedef signed short int16; //!< Signed 16 bit integer typedef unsigned short uint16; //!< Unsigned 16 bit integer typedef signed long int32; //!< Signed 32 bit integer typedef unsigned long uint32; //!< Unsigned 32 bit integer /*********************内部变量************************/ static U8 registeredKeyTaskID = NO_TASK_ID; static U16 registeredKeyEvenID = NO_EVEN_ID; /*********************函数声明************************/ extern uint8 osal_start_timerEx( uint8 task_id, uint16 event_id, uint32 timeout_value ); //****************************************************************************** //name: Key_Init //introduce: 按键初始化 //parameter: none //return: none //author: 甜甜的大香瓜 //changetime: 2016.1.8 //****************************************************************************** void Key_Init(void) { P1SEL &= ~(1 << 2); //P12设置为IO口 P1DIR &= ~(1 << 2); //P12设置为输入 P1INP &= ~(1 << 2); //P1上拉下拉模式 P2INP &= ~(1 << 6); //P1上拉 P1_2 = 1; //P12拉高 P1IFG &= ~(1 << 2); //初始化P12中断标志位 PICTL |= (1 << 1); //下降沿触发 P1IEN |= (1 << 2); //使能P12中断 IEN2 |= (1 << 4); //同意P1口中断; } //****************************************************************************** //name: RegisterForKey //introduce: 注冊任务号、处理事件号 //parameter: task_id:任务id // even_id:事件id //return: true:注冊成功 // flase:注冊不成功 //author: 甜甜的大香瓜 //changetime: 2016.1.8 //****************************************************************************** U8 RegisterForKey(U8 task_id, U16 even_id) { // Allow only the first task if ( registeredKeyTaskID == NO_TASK_ID ) { registeredKeyTaskID = task_id; } else return ( false ); // Allow only the first even if ( registeredKeyEvenID == NO_EVEN_ID ) { registeredKeyEvenID = even_id; } else return ( false ); return ( true ); } //****************************************************************************** //name: Key_Check_Pin //introduce: 按键检測高低电平状态 //parameter: none //return: KEY_LOOSEN:此时无按键按下 // KEY_PRESS:此时按键按下 //author: 甜甜的大香瓜 //changetime: 2016.1.8 //****************************************************************************** U8 Key_Check_Pin(void) { if(P1 & (1 << 2)) { return KEY_LOOSEN; } else { return KEY_PRESS; } } //****************************************************************************** //name: P1_ISR //introduce: P1的中断入口 //parameter: none //return: none //author: 甜甜的大香瓜 //changetime: 2016.1.8 //****************************************************************************** #pragma vector = P1INT_VECTOR __interrupt void P1_ISR(void) { if(Key_Check_Pin() == KEY_PRESS) { osal_start_timerEx(registeredKeyTaskID, registeredKeyEvenID, KEY_DEBOUNCE_VALUE); } P1IFG = 0; //清中断标志 P1IF = 0; //清中断标志 }
2)写一个按键头文件Key.h(存放在“……BLE-CC254x-1.4.0ProjectsleSimpleBLEPeripheralSourceGUA”路径下)
//****************************************************************************** //name: Key.h //introduce: 香瓜自己定义的按键驱动 //author: 甜甜的大香瓜 //changetime: 2016.2.23 //email: 897503845@qq.com //****************************************************************************** #ifndef KEY_H #define KEY_H #ifndef U8 typedef unsigned char U8; #endif #ifndef U16 typedef unsigned short U16; #endif //检測io口状态时使用的宏 #define KEY_LOOSEN 0x01 #define KEY_PRESS 0x00 extern void Key_Init(void); extern U8 RegisterForKey(U8 task_id, U16 even_id); extern U8 Key_Check_Pin(void); #endif
3)project中加入Key.c和Key.h
4)在IAR设置中加入按键驱动源文件路径
$PROJ_DIR$....SimpleBLEPeripheralSourceGUA
2、定义按键消抖事件、按键处理事件
1)定义按键消抖事件、按键处理事件(SimpleBLEPeripheral.c的SimpleBLEPeripheral_ProcessEvent中)
//按键消抖事件 if ( events & SBP_KEY_DEBOUNCE_EVT ) { //防止抖动,确定是按键 if(Key_Check_Pin() == KEY_PRESS) { //定时300ms检測一次按键。假设3S内松开则为短按键,超过3S松开则为长按键 osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_KEY_CHECK_PROCESS_EVT, SBP_KEY_CHECK_PROCESS_EVT_PERIOD ); } return (events ^ SBP_KEY_DEBOUNCE_EVT); } //按键检測处理事件 if ( events & SBP_KEY_CHECK_PROCESS_EVT ) { //检測是否按键已经松开 if(Key_Check_Pin() == KEY_PRESS) { //假设超时,则算长按键,直接进行长按键的处理 if(++nKey_Time > KEY_TIMER_OVER) { //标记为长按键 nKey_State = KEY_STATE_LONG; //时长清零 nKey_Time = 0; } else { //定时300ms检測一次按键。假设3S内松开则为短按键,超过3S松开则为长按键 osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_KEY_CHECK_PROCESS_EVT, SBP_KEY_CHECK_PROCESS_EVT_PERIOD ); } } else { //标记为短按键 nKey_State = KEY_STATE_SHORT; //时长清零 nKey_Time = 0; } switch(nKey_State) { //短按键处理 case KEY_STATE_SHORT: { //运行短按键函数 GUA_Key_Short_Process(); //清除标志 nKey_State = KEY_STATE_IDLE; break; } //长按键处理 case KEY_STATE_LONG: { //运行长按键函数 GUA_Key_Long_Process(); //清除标志 nKey_State = KEY_STATE_IDLE; break; } //其它 default:break; } return (events ^ SBP_KEY_CHECK_PROCESS_EVT); }
#define SBP_KEY_DEBOUNCE_EVT 0x1000 //按键消抖时间 #define SBP_KEY_CHECK_PROCESS_EVT 0x2000 //按键检測处理事件
3、定义并声明长、短按键处理函数(SimpleBLEPeripheral.c中)
1)定义长、短按键处理函数
//****************************************************************************** //name: GUA_Key_Short_Process //introduce: 短按键处理函数 //parameter: none //return: none //author: 甜甜的大香瓜 //changetime: 2016.02.23 //****************************************************************************** static void GUA_Key_Short_Process(void) { //test P1_0 = ~P1_0; //这里測试按一次按键,就取反一次P1_0,方便观察P1_0相应的led P1SEL &= ~(1 << 0); //设置为IO口 P1DIR |= (1 << 0); //设置为输出 //test } //****************************************************************************** //name: GUA_Key_Long_Process //introduce: 长按键处理函数 //parameter: none //return: none //author: 甜甜的大香瓜 //changetime: 2016.02.23 //****************************************************************************** static void GUA_Key_Long_Process(void) { //test P1_1 = ~P1_1; //这里測试按一次长按键按键,就取反一次P1_1,方便观察P1_1相应的led P1SEL &= ~(1 << 1); //设置为IO口 P1DIR |= (1 << 1); //设置为输出 //test }
2)声明长、短按键处理函数
static void GUA_Key_Short_Process(void); static void GUA_Key_Long_Process(void);
4、在应用层中使用按键
1)按键初始化(SimpleBLEPeripheral.c的SimpleBLEPeripheral_Init中)
//按键初始化 Key_Init(); RegisterForKey(simpleBLEPeripheral_TaskID, SBP_KEY_DEBOUNCE_EVT);
2)应用层代码中加入按键驱动头文件(SimpleBLEPeripheral.c中)
//GUA #include "Key.h" //GUA
3)加入必要的宏(SimpleBLEPeripheral.c中)
//香瓜 //按键扫描时间 #define SBP_KEY_CHECK_PROCESS_EVT_PERIOD 300 //超过这个时长。则算长按键 #define KEY_TIMER_OVER 10 //按键状态 #define KEY_STATE_IDLE 0 #define KEY_STATE_SHORT 1 #define KEY_STATE_LONG 2 //香瓜
这里设置为300ms检測一次按键,而且计数加1。假设计数到KEY_TIMER_OVER,则直接判定为长按键。
4)加入必要的静态变量(SimpleBLEPeripheral.c中)
//香瓜 //按键按下的时长 static uint8 nKey_Time = 0; //按键状态 static uint8 nKey_State = KEY_STATE_IDLE; //香瓜
七、注意事项
暂无
八、实验结果
手头没有按键,因此拿一根跳线,一端接在GND,还有一端不停地触碰P12引脚,则会发现:
1)跳线触碰P12引脚3S以内时(短按键)
P10相应的LED1的状态会变化一次。
2)跳线触碰P12引脚3S以上时(长按键)
P11相应的LED2的状态会变化一次。
实现了将普通IO口P12改动为长、短按键。并通过长短按键的不同,分别触发P11的led2亮灭、P10的led1亮灭。
因此。实验成功。