轮训方式连接:https://blog.csdn.net/Golf_research/article/details/52760320 

目录:

1:概述
2:stm32外部中断配置

3:code

概述:

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次防抖,一次是在按键中断处理函数中,一次是在主程序按键扫描中;

//main.c
#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;}}elseLED3_OFF;if(led2_flash_flag == 1)    //LED2闪烁{led2_flag = !led2_flag;if(led2_flag==1){LED2_ON;}else{LED2_OFF;}}elseLED2_OFF;if(led1_flash_flag==1) //LED1闪烁{led1_flag = !led1_flag;if(led1_flag==1){LED1_ON;}else{LED1_OFF;}}elseLED1_OFF;}}
}
//Key_Board.c#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;GPIO_Init(GPIOC, &GPIO_InitStruct);/*按键中断初始化*//*设置中断分组*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);/*完成外部线路映射*/GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource5);/*NVIC寄存器初始化*/NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;//外部中断5NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能外部中断NVIC_Init(&NVIC_InitStructure);//配置/*EXIT寄存器初始 配置EXTI_Line0*/EXTI_InitStructure.EXTI_Line = EXTI_Line5;//LINE5EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//中断事件EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿触发EXTI_InitStructure.EXTI_LineCmd = ENABLE;//使能LINE5EXTI_Init(&EXTI_InitStructure);//初始化
}/*按键中断处理函数*/
void EXTI9_5_IRQHandler()
{delay_timing = 0;while(delay_timing<10);   //延时防抖,如果sysclk的中断优先级低于按键的中断优先级,程序会死掉if(K1 == 0){get_keyvalue_flag = 1;}EXTI_ClearITPendingBit(EXTI_Line5);
}/*获得键值*/
void Get_Key_Value(void)
{if(K1 == 0)         //当K1按键按下{if(k1_shortpress_happen==0){k1_shortpress_happen = 1;      //开始一次按键键值扫描key1_timing = 0;               //按键按下计时变量清0,开始计时,此值每1ms加1,sysclk中断函数中实现自加}elseif(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;}}}elseif(k1_doublepress_happen == 1)         //第一次短按后,等待500ms,如未再发生短按,跟新按键短按键值{if(key1_doublepress_timing > 500){k1_doublepress_happen = 0;k1_value.short_press = 1;}}}
}/*按键事件处理函数 根据键值 进行相应的事件处理*/
void Key_Func(void)
{if(k1_value.short_press == 1){k1_value.short_press = 0;led1_flash_flag = !led1_flash_flag;get_keyvalue_flag = 0;          }if(k1_value.long_press == 1){k1_value.long_press = 0;led2_flash_flag = !led2_flash_flag;get_keyvalue_flag = 0;}if(k1_value.double_press == 1){k1_value.double_press = 0;led3_flash_flag = !led3_flash_flag;get_keyvalue_flag = 0;}
}

(转)嵌入式按键驱动,支持短按、长按、双击(中断方式)相关推荐

  1. 51单片机学习笔记:基于状态机的按键对时程序(短按,长按,连发)

    之前的电子钟程序中,用的按键消抖处理方法是10ms的延时,这种方法效率比较低 所以现在利用状态机原理重写一下,效率很高啊 4个独立按键中用到3个, keys5用于切换对时分秒等状态,keys2是减小数 ...

  2. 修改嵌入式linux驱动支持不同的LCD

    本文中使用的是周立功EPC-287开发板,其中处理器是Freescale ARM9 i.MX287.厂家提供的linux内核源码包含了几种支持的lcd,在内核源码目录下通过make ARCH=arm  ...

  3. Linux驱动之按键驱动长按检测

    现在发现一个问题,Linux下的按键驱动,增加了长按检测.但是在长按的时候不往应用层上报长按的值,很奇怪先做个记录待以后分析.现在的模式是,周一到周五发现问题,到周末才会专心写博客填坑了. ===== ...

  4. 基于Linux2.6下的按键驱动开发步骤

    实验平台:友善之臂s3c2410 编译环境:ubuntu > arm-linux-gcc3.4.5 内核版本:Linux2.6 实验目的:在Linux下完成arm板上的8*8按键驱动开发,最终实 ...

  5. 【ESP32】按键驱动,长按、短按,可设置多个按键

    文章目录 一.ESP32 二.实现 1.源文件 2.头文件 三.调用 总结 一.ESP32 之后的项目要用到ESP32,对按键驱动进行移植 二.实现 1.源文件 支持短按.长按和多个按键. 我在这里设 ...

  6. STM32-蓝桥杯嵌入式之三行按键检测(按键的长、短,单击、双击)

    STM32-蓝桥杯嵌入式之三行按键检测(按键的长.短,单击.双击) 目录 STM32-蓝桥杯嵌入式之三行按键检测(按键的长.短,单击.双击) 一.检测按键下降沿分析 二.检测按键上升沿分析 三.按键检 ...

  7. 有限状态机的嵌入式Linux按键驱动设计(转载)

    本文转载自边缘之火<有限状态机的嵌入式Linux按键驱动设计(转载)> 原文链接:  http://www.eccn.com/design_2010052509381340.htm 秦国栋 ...

  8. 单片机按键开发库-支持连击、长按等操作

    Multi-Function Button Dectection Multi-Function Button Dectection,简称MFBD,是一个基于嵌入式C语言的按键库,自动消抖,支持单击.长 ...

  9. STM32超级简便的按键代码 只需三行 可实现短按+长按

    [蓝桥杯]STM32三行按键详解 长按 短按 用的是国信长天的嵌入式方向的开发板,使用的芯片是STM32F103RBT6,基于stm32f1的固件库编程. 当初写下这篇博客的本意也是让自己的知识更加巩 ...

最新文章

  1. Java这个高级特性,很多人还没用过!
  2. 收藏——CodeProject - 使用特性(attributes)和激活机制来实现工厂模式
  3. 【Luogu】P3950部落冲突(树链剖分)
  4. Python Gevent – 高性能的 Python 并发框架
  5. 右键计算机菜单,右键菜单设置方法步骤【图文】
  6. Activiti 手工任务(manualTask)
  7. mysql查询字段信息
  8. 从零基础入门Tensorflow2.0 ----七、36. 文本生成之---2. 构建模型
  9. Redfish协议测试工具–Postman
  10. 在杭州云栖大会,我们看到了一个新的阿里巴巴
  11. 箱形图的优缺点,python绘制箱形图
  12. 服务器主板主要组成部分(个人笔记,请勿参考)
  13. Android吃鸡 3dtouch,绝地求生刺激战场3Dtouch怎么用 3Dtouch安卓手机可以用吗
  14. JS实现合并单元格的两种方法
  15. 用Java实现平衡二叉树
  16. 《权力的游戏》Python探索性分析
  17. Centos 7 如何关闭提示(You have new mail in /var/spool/mail/root)
  18. POJ_1845_Sumdiv_各种数学
  19. 碧蓝ajax,贝雷帽黑丝双马尾 令人迷恋的阿贾克斯舰娘
  20. 中国一些著名网站的主题颜色

热门文章

  1. POJ1769(线段树+DP)
  2. MongoDB:MapReduce基础及实例
  3. Linux系统编程(18)——正则表达式实用举例
  4. string 与stringbuilder的区别
  5. grafana+zabbix 部署分布式监控系统
  6. Ubunt更换阿里云镜像源
  7. curl: (7) Failed connect to localhost:9200; Connection refused
  8. Excel中 使用链接 批量导入图片
  9. 关于LIMIT(超出界限时,SQL执行也没有问题,而且结果集中只会到有数据的最后一条记录,不会出现空,已经过测试)
  10. 【HDFS】HDFS与getconf结合使用,获取配置信息