历史上的今天
返回首页

历史上的今天

今天是:2025年01月14日(星期二)

正在发生

2019年01月14日 | 嵌入式按键驱动,支持短按、长按、双击(轮询方式)

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;

}

}

推荐阅读

史海拾趣

客益(Guestgood)公司的发展小趣事

机顶盒,全称为数字视频变换盒(Set Top Box,简称STB),是现代家庭娱乐中不可或缺的重要设备。它作为连接电视机与外部信号源的桥梁,主要功能在于接收数字电视信号,并将其转换成适合在电视机上播放的格式。机顶盒不仅能接收来自有线电缆、卫星天线、宽带网络及地面广播的信号,还具备强大的媒体处理能力和交互功能,极大地丰富了用户的观看体验。

从技术层面看,机顶盒经历了从模拟到数字的飞跃式发展。早期的机顶盒主要用于有线电视网络的信号解扰,而现代机顶盒则支持高清、甚至4K超高清视频内容的播放,为用户带来更为细腻的画面和震撼的音效。此外,机顶盒还集成了网络交互功能,用户可以通过机顶盒连接到互联网,享受在线购物、观看网络视频、玩游戏等多元化服务,使电视机从单向接收信息的设备转变为智能互动终端。

随着科技的进步,机顶盒的功能和应用场景也在不断扩展。例如,一些先进的机顶盒支持智能语音控制,用户可以通过语音指令搜索节目、调整设置,极大地提升了使用的便捷性。同时,机顶盒还具备存储功能,用户可以将喜欢的媒体文件存储在机顶盒中,随时通过电视屏幕进行观看,享受个性化的娱乐体验。

综上所述,机顶盒作为家庭娱乐的重要组成部分,不仅承载着传输和显示数字视频信号的基本功能,还通过不断的技术创新和应用拓展,为用户提供了更加丰富、便捷、智能的观影体验。随着技术的不断进步和市场的不断扩大,机顶盒将继续在家庭娱乐领域发挥重要作用。

C&D公司的发展小趣事

C&D公司深知品质是企业的生命线,因此始终坚守品质至上的原则。公司建立了严格的质量管理体系,从原材料采购到生产制造,再到产品出厂,每一个环节都严格把控,确保产品的品质达到最高标准。同时,C&D公司还注重品牌建设,通过广告宣传、社交媒体营销等方式,提升品牌知名度和美誉度。

ACP Optoelectronic Technology Co Ltd公司的发展小趣事

在国内市场取得一定成绩后,ACP Optoelectronic Technology Co Ltd开始积极拓展国际市场。公司积极参加国际电子展会和技术交流活动,与海外企业建立合作关系,拓展销售渠道。经过几年的努力,ACP Optoelectronic Technology Co Ltd的产品已经成功打入多个国际市场,公司也逐渐发展成为一家具有国际影响力的光电企业。

意瑞(COSEMITECH)公司的发展小趣事

随着技术的不断成熟和产品的不断优化,意瑞半导体的市场影响力逐渐扩大。其高集成度、高性能的芯片广泛应用于国内外主流OEM及全球知名Tier1厂商。在汽车电子领域,公司布局了动力总成、车身控制、电源管理和底盘安全等模块,其产品在多家主机厂成功导入并量产,性能超过了国外老牌芯片,成为该品类中本土鲜有的实现汽车市场大批量出货的产品。

Harwin公司的发展小趣事

Harbour Industries始终将产品质量视为企业的生命线。为了确保产品质量达到国际一流水平,公司不断引入先进的质量管理体系。1990年代末期,Harbour成功通过了ISO9001产品质量认证。这一认证不仅标志着公司的质量管理体系已经达到了国际标准,也为其在全球市场中的竞争提供了有力保障。此外,Harbour还实行了“过程管理”来确定和控制产品成本,进一步提升了其市场竞争力和盈利能力。

AXTAL公司的发展小趣事

创新是AXTAL公司不断发展的动力源泉。公司注重研发投入,持续推出具有竞争力的新产品和技术。同时,AXTAL还积极与高校、科研机构等合作,共同开展前沿技术的研发和应用。这些创新举措不仅提升了公司的技术实力和市场竞争力,也为整个电子行业的发展注入了新的活力。

这五个故事只是AXTAL公司发展起来历程中的一部分。它们从不同的角度展示了公司在创立、技术与品质追求、全球布局、应对市场挑战以及持续创新等方面所取得的成就和进步。未来,随着电子行业的不断发展和变革,相信AXTAL公司将继续保持其领先地位,为行业的进步和发展做出更大的贡献。

问答坊 | AI 解惑

模拟电路的频率响应

想知道一模拟电路的频率响应曲线,如何测量,有没有相关的标准或者机构来测量的。 如果没有,我自己想能不能这样测量: 假设关心的频率范围是300k~400k,那用信号源发射300k的连续正弦波作为输入,然后用示波器得到模拟电路的输出信号,分析其频 ...…

查看全部问答>

FPGA数字示波器

本帖最后由 paulhyde 于 2014-9-15 03:27 编辑 基于FPGA制作数字示波器,大家可以看下。。。    …

查看全部问答>

高亮度LED在汽车照明应用的问题

毋庸置疑,采用高亮度LED照明将成为未来汽车的主要特征,这归功于LED相对于传统的白炽光照明方案所具有的许多基本优势。此外,采用LED照明也可带动汽车设计技术和设计风格上的变化。然而,正像任何创新技术一样,LED在被广泛用于汽车照明之前,仍需 ...…

查看全部问答>

散分!!!!!!!

恭喜发财,我散分,我发财,大家一起发财!!!!!!…

查看全部问答>

用vs2005 c#开发ppc程序是为什么汉字会变成方块

我把菜单写了关闭2个字,ide中显示正常,模拟器中显示确实方块,不知道在实际的机器上会是什么样子,如何解决。…

查看全部问答>

eVC++ 对web service 的调用可以么??

论坛以前有这个帖子可是没有明确的答复。 如果谁知道这个问题可以麻烦帮忙解答一下么?? 如果不能调用可以说出根据 或者 文章出处么/? 如果可以调用的话,可以介绍一下方法么?? 谢谢!!…

查看全部问答>

想做基于Wince的PDA的开发,请推荐几款?

正在读研究生呢,非常想做一些嵌入式方面的研究,最好是WinCE方面的。 这里的各位大侠在这方面都很有经验,所以请各位推荐几款市场上可以买的成品PDA,价格适中,2000元以内。 而且,可以用作开发。 现在,我看了几款在taobao网上,不敢买,怕买 ...…

查看全部问答>

从昆腾plc中取数的问题,

做一个管理软件,使用vb,需要从昆腾plc中通过tcp/ip方式取数,听说需要用modbus协议取数,对这个协议不熟悉,有Modbus的接口或者驱动之类的东西吗,thanks a lot…

查看全部问答>

MSP-EXP430FR5739

这款单片机 用IAR编吗?什么软件下载?…

查看全部问答>