判断按键值_ALIENTEK 阿波罗 STM32F767 开发板资料连载第七章 按键输入实验
1)實驗平臺:alientek 阿波羅 STM32F767 開發板2)摘自《STM32F7 開發指南(HAL 庫版)》關注官方微信號公眾號,獲取更多資料:正點原子
第七章 按鍵輸入實驗
上一章,我們介紹了 STM32F7 的 IO 口作為輸出的使用,這一章,我們將向大家介紹如何
使用 STM32F7 的 IO 口作為輸入用。在本章中,我們將利用板載的 4 個按鍵,來控制板載的兩
個 LED 的亮滅。通過本章的學習,你將了解到 STM32F7 的 IO 口作為輸入口的使用方法。本
章分為如下幾個小節:
7.1 STM32F7 IO 口簡介
7.2 硬件設計
7.3 軟件設計
7.4 下載驗證
7.5 STM32CubeMX 配置 IO 口輸出
7.1 STM32F7 IO 口簡介
STM32F7 的 IO 口在上一章已經有了比較詳細的介紹,這里我們不再多說。STM32F7 的 IO
口做輸入使用的時候,是通過調用函數 HAL_GPIO_ReadPin ()來讀取 IO 口的狀態的。了解了這
點,就可以開始我們的代碼編寫了。
這一章,我們將通過 ALIENTEK 阿波羅 STM32 開發板上載有的 4 個按鈕(KEY_UP、KEY0、
KEY1 和 KEY2),來控制板上的 2 個 LED(DS0 和 DS1),其中 KEY_UP 控制 DS0,DS1 互斥
點亮;KEY2 控制 DS0,按一次亮,再按一次滅;KEY1 控制 DS1,效果同 KEY2;KEY0 則同
時控制 DS0 和 DS1,按一次,他們的狀態就翻轉一次。
7.2 硬件設計
本實驗用到的硬件資源有:
1) 指示燈 DS0、DS1。
2) 4 個按鍵:KEY0、KEY1、KEY2、和 KEY_UP。
DS0、DS1 和 STM32F767 的連接在上一章已經介紹過了,在阿波羅 STM32 開發板上的按
鍵 KEY0 連接在 PH3 上、KEY1 連接在 PH2 上、KEY2 連接在 PC13 上、KEY_UP 連接在 PA0
上。如圖 7.2.1 所示:
圖 7.2.1 按鍵與 STM32F767 連接原理圖
這里需要注意的是:KEY0、KEY1 和 KEY2 是低電平有效的,而 KEY_UP 是高電平有效
的,并且外部都沒有上下拉電阻,所以,需要在 STM32F767 內部設置上下拉。
7.3 軟件設計
從這章開始,我們的軟件設計主要是通過直接打開我們光盤的實驗工程,而不再講解怎么
加入文件和頭文件目錄。工程中添加相關文件的方法在我們前面實驗已經講解非常詳細。
打開按鍵實驗工程可以看到,工程引入了 key.c 文件以及頭文件 key.h。下面我們首先打開
key.c 文件,關鍵代碼如下:
#include "key.h"
#include "delay.h"
//按鍵初始化函數
void KEY_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOA_CLK_ENABLE();
//開啟 GPIOA 時鐘
__HAL_RCC_GPIOC_CLK_ENABLE();
//開啟 GPIOC 時鐘
__HAL_RCC_GPIOH_CLK_ENABLE();
//開啟 GPIOH 時鐘
GPIO_Initure.Pin=GPIO_PIN_0;
//PA0
GPIO_Initure.Mode=GPIO_MODE_INPUT; //輸入
GPIO_Initure.Pull=GPIO_PULLDOWN; //下拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
HAL_GPIO_Init(GPIOA,&GPIO_Initure);
GPIO_Initure.Pin=GPIO_PIN_13; //PC13
GPIO_Initure.Mode=GPIO_MODE_INPUT; //輸入
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
HAL_GPIO_Init(GPIOC,&GPIO_Initure);
GPIO_Initure.Pin=GPIO_PIN_2|GPIO_PIN_3; //PH2,3
HAL_GPIO_Init(GPIOH,&GPIO_Initure);
}
//按鍵處理函數
//返回按鍵值
//mode:0,不支持連續按;1,支持連續按;
//0,沒有任何按鍵按下 1,WKUP 按下 WK_UP
//注意此函數有響應優先級,KEY0>KEY1>KEY2>WK_UP!!
u8 KEY_Scan(u8 mode)
{
static u8 key_up=1; //按鍵松開標志
if(mode==1)key_up=1; //支持連按
if(key_up&&(KEY0==0||KEY1==0||KEY2==0||WK_UP==1))
{
delay_ms(10);
key_up=0;
if(KEY0==0)
return KEY0_PRES;
else if(KEY1==0) return KEY1_PRES;
else if(KEY2==0)
return KEY2_PRES;
else if(WK_UP==1) return WKUP_PRES;
}else if(KEY0==1&&KEY1==1&&KEY2==1&&WK_UP==0)key_up=1;
return 0; //無按鍵按下
}
這段代碼包含 2 個函數,void KEY_Init(void)和 u8 KEY_Scan(u8 mode),KEY_Init 是用來
初始化按鍵輸入的 IO 口的。實現 PA0、PC13、PH2 和 PH3 的輸入設置,這里和第六章的輸出
配置差不多,只是這里用來設置成的是輸入而第六章是輸出。
KEY_Scan 函數,則是用來掃描這 4 個 IO 口是否有按鍵按下。KEY_Scan 函數,支持兩種
掃描方式,通過 mode 參數來設置。
當 mode 為 0 的時候,KEY_Scan 函數將不支持連續按,掃描某個按鍵,該按鍵按下之后必
須要松開,才能第二次觸發,否則不會再響應這個按鍵,這樣的好處就是可以防止按一次多次
觸發,而壞處就是在需要長按的時候比較不合適。
當 mode 為 1 的時候,KEY_Scan 函數將支持連續按,如果某個按鍵一直按下,則會一直返
回這個按鍵的鍵值,這樣可以方便的實現長按檢測。
有了 mode 這個參數,大家就可以根據自己的需要,選擇不同的方式。這里要提醒大家,
因為該函數里面有 static 變量,所以該函數不是一個可重入函數,在有 OS 的情況下,這個大家
要留意下。同時還有一點要注意的就是,該函數的按鍵掃描是有優先級的,最優先的是 KEY0,
第二優先的是 KEY1,接著 KEY2,最后是 KEY_UP 按鍵。該函數有返回值,如果有按鍵按下,
則返回非 0 值,如果沒有或者按鍵不正確,則返回 0。
接下來我們看看頭文件 key.h 里面的代碼:
#ifndef _KEY_H
#define _KEY_H
#include "sys.h"
/*下面的方式是通過直接操作 HAL 庫函數方式讀取 IO*/
#define KEY0 HAL_GPIO_ReadPin(GPIOH,GPIO_PIN_3) //KEY0 按鍵 PH3
#define KEY1 HAL_GPIO_ReadPin(GPIOH,GPIO_PIN_2) //KEY1 按鍵 PH2
#define KEY2 HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_13) //KEY2 按鍵 PC13
#define WK_UP HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) //WKUP 按鍵 PA0
#define KEY0_PRES 1
#define KEY1_PRES
2
#define KEY2_PRES
3
#define WKUP_PRES 4
void KEY_Init(void);
u8 KEY_Scan(u8 mode);
#endif
這段代碼里面最關鍵就是 4 個宏定義:
#define KEY0 HAL_GPIO_ReadPin(GPIOH,GPIO_PIN_3) //KEY0 按鍵 PH3
#define KEY1 HAL_GPIO_ReadPin(GPIOH,GPIO_PIN_2) //KEY1 按鍵 PH2
#define KEY2 HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_13) //KEY2 按鍵 PC13
#define WK_UP HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) //WKUP 按鍵 PA0
這里使用的是調用 HAL 庫函數 HAL_GPIO_ReadPin 來實現讀取某個 IO 口的輸入電平。函
數 HAL_GPIO_ReadPin 的使用方法在上一章跑馬燈實驗我們已經講解,這里我們就不累贅了。
在 key.h 中,我們還定義了 KEY0_PRES / KEY1_PRES/ KEY2_PRES/WKUP_PRESS 等 4
個宏定義,分別對應開發板四個按鍵(KEY0/KEY1/KEY2/ KEY_UP)按鍵按下時 KEY_Scan
返回的值。通過宏定義的方式判斷返回值,方便大家記憶和使用。
最后,我們看看 main.c 里面編寫的主函數代碼如下:
int main(void)
{
u8 key;
u8 led0sta=1,led1sta=1;
//LED0,LED1 的當前狀態
Cache_Enable(); //打開 L1-Cache
HAL_Init();
//初始化 HAL 庫
Stm32_Clock_Init(432,25,2,9); //設置時鐘,216Mhz
delay_init(216); //延時初始化
uart_init(115200);
//串口初始化
LED_Init(); //初始化 LED
KEY_Init(); //按鍵初始化
while(1)
{
key=KEY_Scan(0);
//得到鍵值
if(key)
{
switch(key)
{
case WKUP_PRES:
//控制 LED0,LED1 互斥點亮
led1sta=!led1sta;
led0sta=!led1sta;
break;
case KEY2_PRES:
//控制 LED0 翻轉
led0sta=!led0sta;
break;
case KEY1_PRES:
//控制 LED1 翻轉
led1sta=!led1sta;
break;
case KEY0_PRES:
//同時控制 LED0,LED1 翻轉
led0sta=!led0sta;
led1sta=!led1sta;
break;
}
LED0(led0sta);
//控制 LED0 狀態
LED1(led1sta);
//控制 LED1 狀態
}else delay_ms(10);
}
}
主函數代碼比較簡單,先進行一系列的初始化操作,然后在死循環中調用按鍵掃描函數
KEY_Scan()掃描按鍵值,最后根據按鍵值控制 LED 的狀態。
7.4 下載驗證
同樣,我們還是通過 ST LINK 來下載代碼,在下載完之后,我們可以按 KEY0、KEY1、
KEY2 和 KEY_UP 來看看 DS0 和 DS1 的變化,是否和我們預期的結果一致?
至此,我們的本章的學習就結束了。本章,作為 STM32F767 的入門第二個例子,介紹了
STM32F767 的 IO 作為輸入的使用方法,同時鞏固了前面的學習。希望大家在開發板上實際驗
證一下,從而加深印象。
7.5 STM32CubeMX 配置 IO 口輸出
上一章我們講解了使用 STM32CubeMX 工具配置 GPIO 的一般方法。本章我們主要教大家
配置 IO 口為輸入模式,操作方法和配置 IO 口為輸出模式基本一致。這里我們就直接列出 IO
口配置截圖,具體方法請參考 4.8 小節和上一章跑馬燈實驗。
根據 7.2 小節講解,阿波羅開發板上有 4 個按鍵,分別連接四個 IO 口 PA0,PC13,PH2
和 PH3。其中 WK_UP 按鍵按下后對應的 PA0 輸入為高電平,所以默認情況下,該 IO 口(PA0)
要初始化為下拉輸入,其他 IO 口初始化為上拉輸入即可。
使用 STM32CubeMX 打開光盤工程模板(雙擊工程目錄的 Template.ioc),目錄為“4,程
序源碼標準例程-庫函數版本實驗 0-3 Template 工程模板-使用 STM32CubeMX 配置”。我們首
先在 IO 口引腳圖上,依次設置四個 IO 口為輸入模式 GPIO_Input。這里我們以 PA0 為例,操作
方法如下圖 7.5.1 所示:
圖 7.5.1 配置 PA0 為輸入模式
同樣的方法,我們依次配置 PC13 , PH2 和 PH3 為 輸 入 模 式 。 然 后 我 們 進 入
Configuration->GPIO 配置界面,配置四個 IO 口詳細參數。在配置界面點擊 PA0 可以發現,當
我們在前面設置 IO 口為輸入 GPIO_Input 之后,其配置參數只剩下模式 GPIO Mode 和上下拉
GPIO Pull-up/Pull-down,并且模式值中只有輸入模式 Input Mode 可選。這里,我們配置 PA0 為
下拉輸入,其他三個 IO 口配置為上拉輸入即可。配置方法如下圖 7.5.2 所示:
圖 7.5.2 配置 IO 口詳細參數
配置完成 IO 口參數之后,接下來我們同樣生成工程。打開生成的工程會發現,main.c 文件
中添加了函數 MX_GPIO_Init 函數,內容如下:
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin : PC13 */
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/*Configure GPIO pin : PA0 */
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : PH2 PH3 */
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
}
該函數實現的功能和按鍵輸入實驗中 KEY_Init 函數實現的功能一模一樣。有興趣的同學可
以直接復制該函數內容替換按鍵輸入實驗中的 KEY_Init 函數內容,替換后會發現實現現象完全
一致。
使用 STM32CubeMX 配置 IO 口為輸入模式方法就給大家介紹到這里。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的判断按键值_ALIENTEK 阿波罗 STM32F767 开发板资料连载第七章 按键输入实验的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 双十一浦发银行优惠福利尽享 瓜分11亿积
- 下一篇: 三个方面分析:光大携程菁英白金信用卡值得