找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1514|回复: 0
打印 上一主题 下一主题
收起左侧

单片机定时器中断扫描按键程序思路详解

[复制链接]
跳转到指定楼层
楼主
在使用按键的时候,为了消除按键抖动带来的干扰,必须要对按键进行消抖处理。其中最常采用的方法是延时法,就是通过让单片机等待一定的时间后,再进行按键状态判断。这种方法将导致主程序卡死,cpu在进行无意义的循环等待,为了提高单片机的工作效率,可以采用定时器中断处理按键,可以很好的解决delay延时阻塞主程序的问题,并且可以很简单的设置按下触发或者是松手触发。
制作出来的实物图如下:


单片机定时器中断处理按键思路:


STM32单片机主程序如下:
  1. int main()
  2. {        
  3. uint8_t i,temp=0;
  4. OLED_Init();
  5. Key_Init();//按键初始化
  6. OLED_ShowString(1,1,"KEY:");
  7. while(1)
  8. {
  9. i=KEY_ValueReturn();//获取按键返回值
  10. if(i){temp=i;}
  11. OLED_ShowNum(1,5,temp,2);//显示按键返回值
  12. if(i==2)//如果按键2按下,变量vol++
  13. {
  14. vol++;
  15. i=0;
  16. }
  17. if(i==3)//如果按键3按下,变量vol--
  18. {
  19. vol--;
  20. i=0;
  21. }
  22. OLED_ShowNum(4,1,vol,3);//显示变量vol
  23. }
  24. }
复制代码
简单说一下定时器处理按键的思路,首先设置好TIM定时器中断,在定时器中断里进行判断是否有按键按下,如果没有按键按下,则一直返回0;如果按键按下,则和上一次的按键状态作比较,条件成立则返回对应的按键值。比如上一次进入定时器中断,读取到的按键返回值为0,这一次按键返回值是1,则最终结果返回1;如果上一次中断按键返回值是0,这次是按键2按下,则最终结果返回2,其他按键同理。由于定时器中断是每隔一定的时间进行的,单片机采集的都是按键按下时候的瞬时状态,这样就避免了抖动带来的干扰。

定时器中断处理按键代码如下:
  1. #include "stm32f10x.h"
  2. #include "delay.h"

  3. uint8_t KEY_Num,KEY_Value;
  4. static uint8_t KEY_LastState,KEY_NowState;

  5. uint8_t TEST_i;
  6. /****
  7.         *@brief 初始化按键
  8.         *@parameter 无
  9.         *@ReturnValue 无
  10.         */
  11. void Key_Init(void)
  12. {
  13.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);// 开启GPIOB时钟
  14.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//开启TIM2时钟
  15.         
  16.         GPIO_InitTypeDef GPIO_InitStructure;//GPIO初始化
  17.         GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
  18.         GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
  19.         GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  20.         GPIO_Init(GPIOB,&GPIO_InitStructure);
  21.         
  22.         TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//TIM2定时器初始化
  23.         TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//不对内部时钟分频
  24.         TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数模式
  25.         TIM_TimeBaseInitStructure.TIM_Period=20-1;
  26.         TIM_TimeBaseInitStructure.TIM_Prescaler=7200-1
  27.         TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//通用定时器没有重复计数器,设置为0
  28.         TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
  29.         
  30.         TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//打开TIM2的更新中断
  31.         
  32.         TIM_InternalClockConfig(TIM2);//选择内部时钟源
  33.         
  34.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组
  35.         
  36.         NVIC_InitTypeDef NVIC_InitStructure;
  37.         NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;
  38.         NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
  39.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
  40.         NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
  41.         NVIC_Init(&NVIC_InitStructure);
  42.         
  43.         TIM_Cmd(TIM2,ENABLE);
  44. }

  45. uint8_t Test_return(void)
  46. {
  47.         return TEST_i;
  48. }
  49. /****
  50.         *@brief 判断哪个按键被按下
  51.         *@parameter 无
  52.         *@ReturnValue 无
  53.         */
  54. uint8_t KEY_Numble(void)
  55. {
  56.         uint8_t i=0;
  57.         if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)==0) { i=1; }
  58.         if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==0) { i=2; }
  59.         if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==0) { i=3; }
  60.         if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)==0) { i=4; }
  61.         TEST_i=i;
  62.         return i;
  63. }

  64. uint8_t KEY_ValueReturn(void)
  65. {
  66.         uint8_t i;
  67.         i=KEY_Value;
  68.         KEY_Value=0;
  69.         return i;
  70. }

  71. /****
  72.         *@brief //TIM2定时器中断函数
  73.         *@parameter 无
  74.         *@ReturnValue 无
  75.         */
  76. void TIM2_IRQHandler(void)//TIM2定时器中断函数
  77. {
  78.         KEY_LastState=KEY_NowState;
  79.         KEY_NowState=KEY_Numble();
  80.         
  81. //        if(KEY_LastState ==0 && KEY_NowState ==1)//按键按下时候触发
  82. //        {
  83. //                KEY_Value=1;
  84. //        }
  85. //        if(KEY_LastState ==0 && KEY_NowState ==2)
  86. //        {
  87. //                KEY_Value=2;
  88. //        }
  89. //        if(KEY_LastState ==0 && KEY_NowState ==3)
  90. //        {
  91. //                KEY_Value=3;
  92. //        }
  93. //        if(KEY_LastState ==0 && KEY_NowState ==4)
  94. //        {
  95. //                KEY_Value=4;
  96. //        }
  97.         
  98.         if(KEY_LastState ==1 && KEY_NowState ==0)//按键松开时候触发
  99.         {
  100.                 KEY_Value=1;
  101.         }
  102.         if(KEY_LastState ==2 && KEY_NowState ==0)
  103.         {
  104.                 KEY_Value=2;
  105.         }
  106.         if(KEY_LastState ==3 && KEY_NowState ==0)
  107.         {
  108.                 KEY_Value=3;
  109.         }
  110.         if(KEY_LastState ==4 && KEY_NowState ==0)
  111.         {
  112.                 KEY_Value=4;
  113.         }
  114.         
  115.         TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
  116. }
复制代码


Keil代码下载: 定时器处理按键.7z (212.21 KB, 下载次数: 20)

评分

参与人数 2黑币 +62 收起 理由
catlu + 12
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏7 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表