??【藍橋杯嵌入式】專題正在持續(xù)更新中,原理圖解析?,各模塊分析?以及歷年真題講解?都在這兒哦,歡迎大家前往訂閱本專題,獲取更多詳細信息哦??????
??本系列專欄 - ?藍橋杯嵌入式_勾欄聽曲_0的博客
??歡迎大家 ??? ?點贊?? ?評論?? ?收藏??
??個人主頁 - 勾欄聽曲_0的博客??
??希望本文能對你有所幫助,如有不足請指正,共同進步吧??
??立班超志,守蘇武節(jié),歌武穆詞,做易水別。??
目錄
原理圖解析
設置STM32CubeMX
按鍵配置
定時器配置
手搓代碼
中斷回調(服務)函數
?按鍵判斷函數
按鍵單擊判斷函數
按鍵雙擊判斷函數
按鍵長按判斷函數
原理圖解析
我們以PB1為例來分析,假如按鍵沒有被按下,那么PB1的電平就與左上角的VDD相等,也就是PB1 = 1;如果按鍵被按下,那么右下角的接地就會被導通,PB1的電平3就與GND相等,也就是PB1 = 2。
這樣我們就能通過以上原理對按鍵進行判斷,但是按鍵判斷是一個事件觸發(fā)程序,所以我們要使用定時器來使開發(fā)板能在任意時間都能對按鍵進行判斷。因此我們再下一步設置STM32CubeMX中需要對定時器初始化。
設置STM32CubeMX
按鍵配置
首先我們先根據按鍵的原理圖配置好引腳,需要注意的是,再前幾篇文章中講LCD與LED我們講引腳都是設置為GPIO_Output,但是按鍵的四個引腳,我們需要設置為GPIO_input,如圖:
?然后在左側選擇GPIO中的按鍵的四個引腳,上下拉模式設為上拉,為以下狀態(tài):
定時器配置
關于定時器的詳細知識點與解析可前往?【藍橋杯嵌入式】STM32定時器的配置,解析預分頻系數和重裝載值與時鐘頻率的關系 這篇博客,在這里我們只講定時器的應用
如果大家有去做過省賽或國賽題目,就都會看到過對按鍵響應時間是有要求的,一般都是響應時間在0.1秒內,所以我們的定時器可以就設置為0.01秒。
以下是使能中斷?
?
手搓代碼
中斷回調(服務)函數
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
以下就是中斷回調函數,很長,記不住怎么辦。別擔心,還有辦法,我們打開keil5,在Project下找到stm32g4xx_it.c,在里面找到stm32g4xx_hal-tim.h并打開他,翻到最下面,再往上滑一點點,大概兩千五百多行的位置,就可以找到這個函數啦,我們就可以直接復制使用。
?
?按鍵判斷函數
實現創(chuàng)建一個按鍵的結構體,其含義寫在注釋中了:
struct keys
{
uchar judge_sta; //判斷按鍵按鍵按下的動作到了第幾步
bool key_sta; //如果按鍵被按下,為0
bool key_flag; //如果確認被按下,為1
};
?具體實現按鍵判斷函數的思路:
1.判斷中斷回調函數收到的中斷信號是不是我們剛剛給按鍵設置的定時器3的信號,如果是就進入按鍵判斷函數
2.讀取每個按鍵這一時刻的電平
3.判斷有哪些按鍵為按下的狀態(tài)(低電平)
4.按鍵抖動判斷
5.狀態(tài)重置文章來源:http://www.zghlxwxcb.cn/news/detail-797301.html
按鍵單擊判斷函數
具體實現代碼如下,代碼中也有詳細注釋,希望能有所幫助:文章來源地址http://www.zghlxwxcb.cn/news/detail-797301.html
struct keys key[4]={0,0,0,0};
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM3) //判斷中斷信號是否來自定時器3
{
key[0].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0); //讀按鍵PB0現在的狀態(tài),如果被按下,PB0 = 0;如果沒有被按下,PB0 = 1;
key[1].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
key[2].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
key[3].key_sta=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
for(int i = 0;i < 4; i++ ) //確認是哪個或哪些按鍵被按下了
{
switch (key[i].judge_sta)
{
case 0:
{
if(key[i].key_sta==0) key[i].judge_sta = 1; //第一次判斷是否按下
}
break;
case 1:
{
if(key[i].key_sta==0) //進入下一次定時器掃描,按鍵還是按下狀態(tài),那么就確認為按下,以此來消抖
{
key[i].judge_sta = 2;
key[i].key_flag = 1;
}
else //否則就是抖動,本次不算按鍵被按下
key[i].judge_sta = 0;
}
break;
case 2:
{
if(key[i].key_sta==1) key[i].judge_sta = 0; //判斷是否松手,松手后按鍵狀態(tài)重置
}
break;
}
}
}
}
按鍵雙擊判斷函數
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM3) //判斷中斷信號是否來自定時器3
{
key[0].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0); //讀按鍵PB0現在的狀態(tài),如果被按下,PB0 = 0;如果沒有被按下,PB0 = 1;
key[1].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
key[2].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
key[3].key_sta=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
for(int i = 0;i < 4; i++ ) //確認是哪個或哪些按鍵被按下了
{
switch (key[i].judge_sta)
{
case 0:
{
if(key[i].key_sta==0) key[i].judge_sta = 1; //第一次判斷是否按下
}
break;
case 1:
{
if(key[i].key_sta==0) //進入下一次定時器掃描,按鍵還是按下狀態(tài),那么就確認為按下,以此來消抖
{
if(a == i && key[a].key_time < 70) //小于70,說明上次按下后到這次按下時間間隔小于0.7秒
{
key[i].double_key_flag = 1; //這是一次雙擊事件
}
else
{
key[i].key_flag = 1;
a = i; //記錄這一次是上面按鍵被按下
}
key[i].judge_sta = 2;
}
else //否則就是抖動,本次不算按鍵被按下
key[i].judge_sta = 0;
}
break;
case 2:
{
if(key[i].key_sta==1) key[i].judge_sta = 0; //判斷是否松手,松手后按鍵狀態(tài)重置
key[i].key_time = 0;
}
break;
}
}
key[a].key_time++; //第一次被按下之后,開始計時
}
}
按鍵長按判斷函數
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM3)
{
key[0].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
key[1].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
key[2].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
key[3].key_sta=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
for(int i = 0;i < 4; i++ )
{
switch (key[i].judge_sta)
{
case 0:
{
if(key[i].key_sta==0)
{
key[i].judge_sta = 1; //第一次判斷是否按下
key[i].key_time = 0;
}
}
break;
case 1:
{
if(key[i].key_sta==0) //進入下一次定時器掃描,按鍵還是按下狀態(tài),那么就確認為按下,以此來消抖
{
key[i].judge_sta = 2;
}
else
key[i].judge_sta = 0;
}
break;
case 2:
{
if(key[i].key_sta==1) //判斷是否松手
{
if(key[i].key_time < 100)
{
key[i].key_flag = 1;
}
// if(key[i].key_time > 100) //一次掃描10毫秒,100次1000毫秒,就是判斷是否長按超過1000毫秒
// //松手后,才會執(zhí)行相應反應
// {
// key[i].long_flag = 1;
// }
key[i].judge_sta = 0;
}
else
{
key[i].key_time++;
if(key[i].key_time > 100) //一次掃描10毫秒,100次1000毫秒,就是判斷是否長按超過1000毫秒//未松手時,就會執(zhí)行相應反應
{
key[i].long_flag = 1;
}
}
}
break;
}
}
}
}
到了這里,關于【藍橋杯嵌入式】定時器實現按鍵單擊,雙擊,消抖以及長按的代碼實現的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!