在使用按鍵的時候,為了消除按鍵抖動帶來的干擾,必須要對按鍵進行消抖處理。其中最常采用的方法是延時法,就是通過讓單片機等待一定的時間后,再進行按鍵狀態判斷。這種方法將導致主程序卡死,cpu在進行無意義的循環等待,為了提高單片機的工作效率,可以采用定時器中斷處理按鍵,可以很好的解決delay延時阻塞主程序的問題,并且可以很簡單的設置按下觸發或者是松手觸發。
制作出來的實物圖如下:
51hei圖片_20221208190228.jpg (278.78 KB, 下載次數: 45)
下載附件
2022-12-8 19:02 上傳
單片機定時器中斷處理按鍵思路:
屏幕截圖(364).png (35.46 KB, 下載次數: 53)
下載附件
2022-12-8 16:57 上傳
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)
2022-12-8 18:57 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|