在使用按键的时候,为了消除按键抖动带来的干扰,必须要对按键进行消抖处理。其中最常采用的方法是延时法,就是通过让单片机等待一定的时间后,再进行按键状态判断。这种方法将导致主程序卡死,cpu在进行无意义的循环等待,为了提高单片机的工作效率,可以采用定时器中断处理按键,可以很好的解决delay延时阻塞主程序的问题,并且可以很简单的设置按下触发或者是松手触发。
制作出来的实物图如下:
单片机定时器中断处理按键思路:
STM32单片机主程序如下:
- int main()
- {
- uint8_t i,temp=0;
- OLED_Init();
- Key_Init();//按键初始化
- OLED_ShowString(1,1,"KEY:");
- while(1)
- {
- i=KEY_ValueReturn();//获取按键返回值
- if(i){temp=i;}
- OLED_ShowNum(1,5,temp,2);//显示按键返回值
- if(i==2)//如果按键2按下,变量vol++
- {
- vol++;
- i=0;
- }
- if(i==3)//如果按键3按下,变量vol--
- {
- vol--;
- i=0;
- }
- OLED_ShowNum(4,1,vol,3);//显示变量vol
- }
- }
复制代码 简单说一下定时器处理按键的思路,首先设置好TIM定时器中断,在定时器中断里进行判断是否有按键按下,如果没有按键按下,则一直返回0;如果按键按下,则和上一次的按键状态作比较,条件成立则返回对应的按键值。比如上一次进入定时器中断,读取到的按键返回值为0,这一次按键返回值是1,则最终结果返回1;如果上一次中断按键返回值是0,这次是按键2按下,则最终结果返回2,其他按键同理。由于定时器中断是每隔一定的时间进行的,单片机采集的都是按键按下时候的瞬时状态,这样就避免了抖动带来的干扰。
定时器中断处理按键代码如下:
- #include "stm32f10x.h"
- #include "delay.h"
- uint8_t KEY_Num,KEY_Value;
- static uint8_t KEY_LastState,KEY_NowState;
- uint8_t TEST_i;
- /****
- *@brief 初始化按键
- *@parameter 无
- *@ReturnValue 无
- */
- void Key_Init(void)
- {
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);// 开启GPIOB时钟
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//开启TIM2时钟
-
- GPIO_InitTypeDef GPIO_InitStructure;//GPIO初始化
- GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
- GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
- GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
- GPIO_Init(GPIOB,&GPIO_InitStructure);
-
- TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//TIM2定时器初始化
- TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//不对内部时钟分频
- TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数模式
- TIM_TimeBaseInitStructure.TIM_Period=20-1;
- TIM_TimeBaseInitStructure.TIM_Prescaler=7200-1
- TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//通用定时器没有重复计数器,设置为0
- TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
-
- TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//打开TIM2的更新中断
-
- TIM_InternalClockConfig(TIM2);//选择内部时钟源
-
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组
-
- NVIC_InitTypeDef NVIC_InitStructure;
- NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
- NVIC_Init(&NVIC_InitStructure);
-
- TIM_Cmd(TIM2,ENABLE);
- }
- uint8_t Test_return(void)
- {
- return TEST_i;
- }
- /****
- *@brief 判断哪个按键被按下
- *@parameter 无
- *@ReturnValue 无
- */
- uint8_t KEY_Numble(void)
- {
- uint8_t i=0;
- if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)==0) { i=1; }
- if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==0) { i=2; }
- if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==0) { i=3; }
- if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)==0) { i=4; }
- TEST_i=i;
- return i;
- }
- uint8_t KEY_ValueReturn(void)
- {
- uint8_t i;
- i=KEY_Value;
- KEY_Value=0;
- return i;
- }
- /****
- *@brief //TIM2定时器中断函数
- *@parameter 无
- *@ReturnValue 无
- */
- void TIM2_IRQHandler(void)//TIM2定时器中断函数
- {
- KEY_LastState=KEY_NowState;
- KEY_NowState=KEY_Numble();
-
- // if(KEY_LastState ==0 && KEY_NowState ==1)//按键按下时候触发
- // {
- // KEY_Value=1;
- // }
- // if(KEY_LastState ==0 && KEY_NowState ==2)
- // {
- // KEY_Value=2;
- // }
- // if(KEY_LastState ==0 && KEY_NowState ==3)
- // {
- // KEY_Value=3;
- // }
- // if(KEY_LastState ==0 && KEY_NowState ==4)
- // {
- // KEY_Value=4;
- // }
-
- if(KEY_LastState ==1 && KEY_NowState ==0)//按键松开时候触发
- {
- KEY_Value=1;
- }
- if(KEY_LastState ==2 && KEY_NowState ==0)
- {
- KEY_Value=2;
- }
- if(KEY_LastState ==3 && KEY_NowState ==0)
- {
- KEY_Value=3;
- }
- if(KEY_LastState ==4 && KEY_NowState ==0)
- {
- KEY_Value=4;
- }
-
- TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
- }
复制代码
Keil代码下载:
定时器处理按键.7z
(212.21 KB, 下载次数: 25)
|