本篇博文最后改动时间: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.0\Projects\ble\SimpleBLEPeripheral\Source\GUA”路径下)
//******************************************************************************    
//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;        //清中断标志   
}  
//****************************************************************************** //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
4)在IAR设置中加入按键驱动源文件路径
$PROJ_DIR$\..\..\SimpleBLEPeripheral\Source\GUA
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  
}  
static void GUA_Key_Short_Process(void); static void GUA_Key_Long_Process(void);
1)按键初始化(SimpleBLEPeripheral.c的SimpleBLEPeripheral_Init中)
//按键初始化 Key_Init(); RegisterForKey(simpleBLEPeripheral_TaskID, SBP_KEY_DEBOUNCE_EVT);
//GUA #include "Key.h" //GUA
//香瓜 //按键扫描时间 #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,则直接判定为长按键。
//香瓜 //按键按下的时长 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亮灭。
因此。实验成功。
原文:http://www.cnblogs.com/clnchanpin/p/7147592.html