专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
嵌入式
嵌入式按键驱动:支持短按、长按、双击(中断方式)
2019-07-12 23:08
发布
生成海报
站内文章
/
嵌入式Linux
11453
0
1601
概述: 1:本篇利用按键中断输入方式,当按键触发,中断处理函数置按键扫描标志位为1,开始按键键值扫描,完成后,主程序根据键值(短按、长按、双击),完成相应的动作;
2:当K1按键短按:LED1闪烁;当K1按键长按,LED2闪烁;当K1按键双击,LED3闪烁;
3:优点:相比于轮询扫描按键键值的方式,按键响应速度更快,节约CPU资源; 4:参考资料:stm32中文参考手册(EXIT的有关说明)、Cortex-M3权威指南(NVIC的有关说明) 5:开发板:STM32f103ZERT 奋斗开发板V5 开发环境:KEIL MDK5 6:工程下载: stm32外部中断配置 1: 设置中断分组 设置中断优先级之前,一定要设置中断分组,本代码中有sysclk中断和按键外部中断,设置中断中断分组为2,2位主优先级和2位次优先级,需设置内部sysclk中断的优先级高于按键中断的优先级,内部中断使用NVIC_SetPriority()函数设置,具体函数参考core_cm3.h文件,外部中断优先级在NVIC_Init()函数中设置; 2:完成外部中断线路映射 使用GPIO_EXTILineConfig()函数完成中断线路的映射; 3:NVIC寄存器初始化 完成对应中断的使能和优先级设定,使用NVIC_Init()库函数完成初始化。注意:一定要给NVIC_InitStructure结构体的成员赋值,因为NVIC_InitTypeDef结构体是在函数内部定义的,并且没有赋初值,如果不设置的话,结构体中的成员使用编译器默认的初值,有可能会出现错误,因为中断优先级很重要,如果按键中断的优先级高于sysclk中断,按键处理函数中的按键防抖会死循环,具体见下面程序; 4:EXIT寄存器初始化 使能响应的外部中断,并且设置中断的触发方式,使用EXTI_Init()函数完成初始化; 5:程序进行了2次防抖,一次是在按键中断处理函数中,一次是在主程序按键扫描中;
#include "stm32f10x.h"
#include "Key_Board.h"
#include "Rcc_Driver.h"
#include "Led_Driver.h"
#include "Sysclk_Driver.h"
volatile
unsigned
int
led_flash_timing = 0;
volatile
unsigned
int
get_keyvalue_timing = 0;
bool
led1_flag = 0;
bool
led2_flag = 0;
bool
led3_flag = 0;
unsigned
char
i = 0;
int
main()
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//设置中断优先级分组
RCC_PeriphClock_Config();
//外设时钟初始化
SysTick_Init(INT_1MS,SysTick_CLKSource_HCLK_Div8);
//sysclk定时器初始化
Key_Init();
//K1按键初始化
Led_Init();
//LED初始化
while
(1)
{
if
((get_keyvalue_flag == 1) && (get_keyvalue_timing > 20))
//间隔20ms扫面一次,进行按键防抖
{
get_keyvalue_timing = 0;
Get_Key_Value();
Key_Func();
}
if
(led_flash_timing > 150)
{
led_flash_timing = 0;
if
(led3_flash_flag == 1)
//LED3闪烁
{
led3_flag = !led3_flag;
if
(led3_flag==1)
{
LED3_ON;
}
else
{
LED3_OFF;
}
}
else
LED3_OFF;
if
(led2_flash_flag == 1)
//LED2闪烁
{
led2_flag = !led2_flag;
if
(led2_flag==1)
{
LED2_ON;
}
else
{
LED2_OFF;
}
}
else
LED2_OFF;
if
(led1_flash_flag==1)
//LED1闪烁
{
led1_flag = !led1_flag;
if
(led1_flag==1)
{
LED1_ON;
}
else
{
LED1_OFF;
}
}
else
LED1_OFF;
}
}
}
Key_Board.c
[cpp]
view plain
copy
#include "Key_Board.h"
volatile
unsigned
int
delay_timing = 0;
/*记录按键按下时间 时间小于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
led2_flash_flag = 0;
/*流水灯事件标志位*/
bool
led3_flash_flag = 0;
/*获取键值标志*/
volatile
bool
get_keyvalue_flag = 0;
/*按键初始化
*k1=GPIOC5 设置GPIOC5为上拉输入
*/
void
Key_Init(
void
)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/*按键对应GPIO口初始化*/
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
Ta的文章
更多
>>
信息流广告、SEM、DSP广告以及联盟广告是什么?
0 个评论
嵌入式按键驱动:支持短按、长按、双击(中断方式)
0 个评论
对Linux系统休眠的理解
0 个评论
热门文章
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮