基于Telink 825x Sdk上按键短按及长按的功能实现

基于Telink 825x Sdk上按键短按及长按的功能实现

前言

本例程基于10ms的中断定时器扫描,实现了短按、长按的按键识别功能。

驱动代码编写

写一个头文件button.h:

#ifndef _BUTTON_H_
#define _BUTTON_H_

typedef enum {
   B_START = 0,  //启动
   B_STOP = 1,   //停止
}BUTTON_State;

typedef enum {
   NO_ACTION = 0x00,   //无动作
   SHORT_PRESS = 0x01, //短按
   LONG_PRESS = 0x02,  //长按
}BUTTON_Type;

typedef struct button_hander{
  unsigned char BST_BUF; //按键状态存储值
  unsigned int  BTI_CNT; //按键计数器值
  unsigned char btr;     //按键返回状态值
  unsigned char btn;     //按键值
  //unsigned char level;   //按键电平值
  unsigned char event;   //按键事件值
}BUTTON_Hander;


void Button_Init(void);  //按键初始化,放在user_init函数里面
void Button_Timer_Irq_Proc(void); //按键中断处理函数,放在irq_handler函数里面
#endif 

命名一个button.c文件,添加公共及驱动头文件

#include "button.h"
#include "drivers.h"
#include "tl_common.h"

定义按键的GPIO

#define BUTTON_PIN GPIO_PB6
BUTTON_Hander BP;

写一个按键处理函数,主要检测IO电平变化

/*按键处理函数*/
static unsigned char Button_Process(GPIO_PinTypeDef pin)
{
  //BP.level = gpio_read(pin);//电平检测
  //if(BP.level) {BP.level = 1;}
  //else { BP.level = 0;}
 // BP.btn = BP.level;
  BP.btn = (gpio_read(pin))?1:0;
  switch(BP.BST_BUF)
  {
    case B_START:
      BP.BST_BUF = (BP.btn == 0)?B_STOP:B_START;
      BP.btr = NO_ACTION;
      /*
      if(BP.btn == 0) //按键按下
      {
        BP.BST_BUF = B_STOP; 
        BP.btr = NO_ACTION;
      }
      else
      {
        BP.BST_BUF = B_START;
        BP.btr = NO_ACTION;
      }*/
    break;
    case B_STOP:  
      if(BP.btn == 1)  //按键释放
      {
        if(BP.BTI_CNT >= 10 && BP.BTI_CNT < 100)     //100ms~1s 短按
        {
          BP.btr = SHORT_PRESS;  //短按事件
          BP.BTI_CNT = 0;
        }
        else if(BP.BTI_CNT >= 100  && BP.BTI_CNT < 300)//1s-3s 长按
        {
          BP.btr = LONG_PRESS;   //长按事件
          BP.BTI_CNT = 0;
        }
        else
        {
          BP.btr = NO_ACTION;
          BP.BTI_CNT = 0;
        }
        BP.BST_BUF = B_START;  //切回按键初始状态
      }
      else
      {
        BP.BTI_CNT++;
        BP.btr = NO_ACTION;
      }
    break;
   }
   return BP.btr;
}

写一个按键事件函数,区分短按和长按的功能

/*按键事件函数*/
static int Button_Event(GPIO_PinTypeDef pin) 
{
  BP.event = Button_Process(pin);
  switch(BP.event)
  {
     case SHORT_PRESS://短按
     {
        printf("SHORT_PRESS!\r\n");
        BP.event = NO_ACTION;
        BP.BTI_CNT = 0;
        break;
     }
     case LONG_PRESS: //长按
     {
        printf("LONG_PRESS!\r\n");
        BP.event = NO_ACTION;
        BP.BTI_CNT = 0;
        break;
     }
     default:
         
     break;
  }
}

写一个10ms的定时器中断初始化函数

/*定时器中断初始化*/
void Button_Timer_Init(void)
{
	reg_irq_mask |= FLD_IRQ_TMR0_EN;	//timer0 10ms interval irq
	reg_tmr0_tick = 0; //clear counter
	reg_tmr0_capt = 10 * CLOCK_SYS_CLOCK_1MS;//set 10ms
	reg_tmr_sta = FLD_TMR_STA_TMR0; //clear irq status
	reg_tmr_ctrl |= FLD_TMR0_EN;  //start timer
  irq_enable();
}

写一个中断处理函数,把按键事件函数放在里面处理

/*中断处理函数*/
_attribute_ram_code_ void Button_Timer_Irq_Proc(void)
{
	if(reg_tmr_sta & FLD_TMR_STA_TMR0)
  {
		reg_tmr_sta = FLD_TMR_STA_TMR0; //clear irq status
		Button_Event(BUTTON_PIN); //触发按键事件,低电平有效
	}
}

写一个按键初始化函数,对参数进行初始化,GPIO进行初始化

/*button初始化函数*/
void Button_Init(void)
{
    BP.BST_BUF = B_START;//按键状态初始化
    BP.BTI_CNT = 0;//触发次数初始化
    BP.btr = NO_ACTION; //按键返回值初始化
   // BP.level = 0; //电平值初始化
    BP.event = NO_ACTION;//按键事件初始化
    gpio_set_func(BUTTON_PIN,AS_GPIO);
    gpio_set_output_en(BUTTON_PIN,0);//enable output
    gpio_set_input_en(BUTTON_PIN,1);
    gpio_setup_up_down_resistor(BUTTON_PIN,PM_PIN_PULLUP_10K);
    printf("button io init\r\n");
    Button_Timer_Init();
} 

移植使用

在project.mk里的添加$(OUT_PATH)/button.o \加入编译
在maic.c的头文件添加如下头文件

#include "button.h"

把Button_Timer_Irq_Proc();放在maic.c的irq_handler函数里

_attribute_ram_code_ void irq_handler(void)
{
   /*限于篇幅,此处代码有省*/
   //中断
   Button_Timer_Irq_Proc();
	 irq_blt_sdk_handler();
}

把Button_Init();放在main.c的main函数里

_attribute_ram_code_ int main (void)    //must run in ramcode
{
	blc_pm_select_internal_32k_crystal();
	cpu_wakeup_init();
	int deepRetWakeUp = pm_is_MCU_deepRetentionWakeup();  //MCU deep retention wakeUp
	rf_drv_init(RF_MODE_BLE_1M);
	gpio_init( !deepRetWakeUp );  //analog resistance will keep available in deepSleep mode, so no need initialize again
#if (CLOCK_SYS_CLOCK_HZ == 16000000)
	clock_init(SYS_CLK_16M_Crystal);
#elif (CLOCK_SYS_CLOCK_HZ == 24000000)
	clock_init(SYS_CLK_24M_Crystal);
#elif (CLOCK_SYS_CLOCK_HZ == 32000000)
	clock_init(SYS_CLK_32M_Crystal);
#endif
	blc_app_loadCustomizedParameters();  //load customized freq_offset cap value
	/*按键初始化*/
	Button_Init();
  /*限于篇幅,此处代码有省*/
	if( deepRetWakeUp )
	{
		/***/
	}
	else
	{
		/***/
	}
	irq_enable();
	while (1) //main_loop
	{
#if (MODULE_WATCHDOG_ENABLE)
		wd_clear(); //clear watch dog
#endif
		blt_sdk_main_loop();
		/***/
	}
}

测试效果

长按1次,短按8次,再长按2次,串口打印如下:
在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值