前言
本例程基于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次,串口打印如下: