嵌入式按键驱动,支持短按、长按、双击(轮询方式)

发布者:心愿成真最新更新时间:2019-01-14 来源: eefocus关键字:按键驱动  短按  长按  双击  轮询方式 手机看文章 扫描二维码
随时随地手机看文章

目录:


1:概述


2:代码功能


3:代码分享


概述:


代码利用轮询方式对按键状态进行扫描,扫描得出按键的键值(短按、长按、双击),然后根据键值进行相应的事件处理;


平台:奋斗STM32F103 V5开发板  开发环境:KEIL MDK5




代码功能:


短按K1按键,LED1灯闪烁,闪烁间隔250ms;


长按K1按键1.5S以上,三个LED同时闪烁,闪烁间隔250ms;


双击K1按键,实现三个LED的流水灯;




代码分享:


main.c函数:



/*

*FUNC:轮询按键键值,实现按键短按(单击)、长按、双击功能

*MCU:stm32f103

*DATE:2016/10/07

*/

#include "Key_Board.h"

#include "Rcc_Driver.h"

#include "Led_Driver.h"

#include "Sysclk_Driver.h"

 

/*led闪烁标志 为1--led亮 为0--led灭*/

bool led_flag = 0;

bool led1_flag = 0;

 

/*任务:led闪烁时间间隔*/

volatile unsigned int led_flash_timing = 0;

 

/*任务:按键轮询时间间隔*/

volatile unsigned int key_scan_timing = 0;

unsigned char i = 0;

 

int main()

{

RCC_PeriphClock_Config();                              //模块时钟初始化

Key_Init();                                            //按键初始化  

Led_Init();                                            //按键初始化

SysTick_Init(INT_1MS,SysTick_CLKSource_HCLK_Div8);     //内核滴答定时器配置

 

while(1)

{

/*任务1:10ms进行一次按键键值扫描和按键事件处理*/

if(key_scan_timing > 10)

{

key_scan_timing = 0;

Key_Scan();           //扫描按键是否按下,上报按键键值

Key_Func();           //根据按键键值,对应事件的标志位置1

}


/*任务2:完成led闪烁*/

if(led_flash_timing > 250)

{

led_flash_timing = 0;

if(led_water_flag == 1)     //led流水灯:LED1 LED2 LED3

{

if(++i > 3)

i = 1;

switch(i)

{

case 1:

LED1_ON;

LED3_OFF;

break;

case 2:

LED2_ON;

LED1_OFF;

break;

case 3:

LED3_ON;

LED2_OFF;

break;

}

}

else

if(led_all_flash_flag == 1)    //LED1 LED2 LED3同时闪烁

{

led_flag = !led_flag;

if(led_flag==1)

{

LED1_ON;

LED2_ON;

LED3_ON;

}

else

{

LED1_OFF;

LED2_OFF;

LED3_OFF;

}

}

else

if(led1_flash_flag==1) //LED1闪烁

{

led1_flag = !led1_flag;

if(led1_flag==1)

{

LED1_ON;

}

else

{

LED1_OFF;

}

}

else    //当没有按键事件需要处理时,熄灭三个led灯

{

LED1_OFF;

LED2_OFF;

LED3_OFF;

}

}

}

}

 

 



按键扫面函数(Key_Scan(void))和按键事件处理函数(Key_Func(void)):


Key_Board.c:



#include "Key_Board.h"

 

/*记录按键按下时间 时间小于1.5S,按键为短按;时间大于1.5S,按键为长按*/

volatile unsigned int key1_timing = 0;

 

/*记录两次短按之间的时间间隔*/

volatile unsigned int key1_doublepress_timing = 0;

 

/*定义按键键值结构体*/

Key_Value k1_value;

 

/*K1按键短按标志位*/

bool k1_shortpress_happen = 0;

 

/*K1按键长按标志位*/

bool k1_longpress_happen = 0;

 

/*K1按键双击标志位*/

bool k1_doublepress_happen = 0;

 

/*led1闪烁时间标志位,主函数检测到此标志位为1时,led1开始闪烁,否则,结束闪烁*/

bool led1_flash_flag = 0;

 

/*3个led全部闪烁标志位,主函数检测到此标志为1时,三个led灯开始同时闪烁,否则结束闪烁*/

bool led_all_flash_flag = 0;

 

/*流水灯事件标志位*/

bool led_water_flag = 0;

 

/*按键初始化

*设置GPIOC2/GPIOC3/GPIOC5为上拉输入,按键按下为低电平,按键抬起为高电平

*/

void Key_Init(void)

{

GPIO_InitTypeDef GPIO_InitStruct;

GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;

GPIO_InitStruct.GPIO_Pin  = GPIO_Pin_5;

GPIO_Init(GPIOC, &GPIO_InitStruct);

}

 

/*按键键值扫描函数*/

void Key_Scan(void)

{

/*程序不支持两个按键同时按下*/

// if((K1==0&&K2==0) || (K1==0&&K3==0) || (K2==0&&K3==0))

// return ;


if(K1==0)         //当K1按键按下

{

if(k1_shortpress_happen==0)

{

k1_shortpress_happen = 1;      //开始一次按键键值扫描

key1_timing = 0;               //按键按下计时变量清0,开始计时,此值每1ms加1,sysclk中断函数中实现自加

}


if(k1_shortpress_happen==1)

{

if(key1_timing > 1500)         //按键按下时间超过1.5S,长按事件发生,置k1_value.long_press为1

{

k1_value.long_press = 1;

k1_shortpress_happen = 0;    //按键短按标志位置0

}

}

}


if(K1==1)         //当K1按键抬起

{

if(k1_shortpress_happen==1)      //按键抬起后,k1_shortpress_happen等于1,说明按键为短按,不是长按

{

k1_shortpress_happen = 0; 

if(k1_doublepress_happen==0)

{

k1_doublepress_happen = 1;    //按键双击标志位置1,等待确认按键是否为双击

key1_doublepress_timing = 0;  //开始计时,同样1ms自增加1

}

else

{

if(key1_doublepress_timing < 500)  //第一次短按发生后,在500ms时间内,发生第二次短按,完成一次双击,跟新按键键值

{

k1_doublepress_happen = 0;

k1_value.double_press = 1;

}

}

}

else

if(k1_doublepress_happen == 1)         //第一次短按后,等待500ms,如未再发生短按,跟新按键短按键值

{

if(key1_doublepress_timing > 500)

{

k1_doublepress_happen = 0;

k1_value.short_press = 1;

}

}

else

if(k1_longpress_happen==1)

k1_longpress_happen = 0;

}

}

 

/*按键事件处理函数 根据键值 进行相应的事件处理*/

void Key_Func(void)

{

if(k1_value.short_press == 1)

{

k1_value.short_press = 0;

//led1_flash_flag = (led1_flash_flag==TRUE? FALSE:TRUE);

led1_flash_flag = !led1_flash_flag;

}


if(k1_value.long_press == 1)

{

k1_value.long_press = 0;

//led_all_flash_flag = (led_all_flash_flag==TRUE?FALSE:TRUE);

led_all_flash_flag = !led_all_flash_flag;

}


if(k1_value.double_press == 1)

{

k1_value.double_press = 0;

//led_water_flag = (led_water_flag==TRUE?FALSE:TRUE);

led_water_flag = !led_water_flag;

}

}

关键字:按键驱动  短按  长按  双击  轮询方式 引用地址:嵌入式按键驱动,支持短按、长按、双击(轮询方式)

上一篇:stm32f103按键轮询实现方法
下一篇:STM32F429(HAL库)_USART串口发送&接收(使用STM32CubeMX)

推荐阅读最新更新时间:2024-03-16 16:22

MINI2440 按键输入子系统 驱动及测试代码分析
按键输入子系统驱动: #include linux/module.h #include linux/types.h #include linux/fs.h #include linux/mm.h #include linux/device.h #include linux/errno.h /* for -EBUSY */ #include linux/ioport.h /* for request_region */ #include linux/delay.h /* for loops_per_jiffy */ #include asm/io.h /* for inb_p, outb_p, inb, outb,
[单片机]
S3C2440下linux按键驱动编写及测试程序
驱动程序tang2440_buttons.c #include linux/module.h #include linux/kernel.h #include linux/fs.h #include linux/init.h #include linux/delay.h #include linux/poll.h #include linux/irq.h #include asm/irq.h #include linux/interrupt.h #include asm/uaccess.h #include mach/regs-gpio.h #include mach/hardware.h #include linux/platf
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved