本章參考資料:《STM32F4xx 參考手冊》、庫幫助文檔《stm32f4xx_dsp_stdperiph_lib_um.chm》。
按鍵檢測使用到 GPIO 外設的基本輸入功能,本章中不再贅述 GPIO 外設的概念,如您忘記了,可重讀前面「GPIO 框圖剖析」小節, STM32 標準庫中 GPIO 初始化結構體GPIO_TypeDef 的定義與「定義引腳模式的枚舉類型」小節中講解的相同。
10.1 硬體設計:
按鍵機械觸點斷開、閉合時,由於觸點的彈性作用,按鍵開關不會馬上穩定接通或一下子斷開,使用按鍵時會產生圖 10-1 中的帶波紋信號,需要用軟體消抖處理濾波,不方便輸入檢測。本實驗板連接的按鍵帶硬體消抖功能,見圖 10-2,它利用電容充放電的延時,消除了波紋,從而簡化軟體的處理,軟體只需要直接檢測引腳的電平即可。
從按鍵的原理圖可知,這些按鍵在沒有被按下的時候, GPIO 引腳的輸入狀態為低電平(按鍵所在的電路不通,引腳接地),當按鍵按下時, GPIO 引腳的輸入狀態為高電平(按鍵所在的電路導通,引腳接到電源)。只要我們檢測引腳的輸入電平,即可判斷按鍵是否被按下。
若您使用的實驗板按鍵的連接方式或引腳不一樣,只需根據我們的工程修改引腳即可,程序的控制原理相同。
10.2 軟體設計:
同 LED 的工程,為了使工程更加有條理,我們把按鍵相關的代碼獨立分開存儲,方便以後移植。在「工程模板」之上新建「bsp_key.c」及「bsp_key.h」文件,這些文件也可根據您的喜好命名,這些文件不屬於 STM32 標準庫的內容,是由我們自己根據應用需要編寫的。
10.2.1 編程要點:
1. 使能 GPIO 埠時鐘;
2. 初始化 GPIO 目標引腳為輸入模式(引腳默認電平受按鍵電路影響,浮空/上拉/下拉均沒有區別);
3. 編寫簡單測試程序,檢測按鍵的狀態,實現按鍵控制 LED 燈。
10.2.2 代碼分析:
1. 按鍵引腳宏定義:
同樣,在編寫按鍵驅動時,也要考慮更改硬體環境的情況。我們把按鍵檢測引腳相關的宏定義到 「bsp_key.h」文件中,見代碼清單 10-1。
代碼清單 10-1 按鍵檢測引腳相關的宏
//引腳定義
/*******************************************************/
#define KEY1_PIN GPIO_Pin_0
#define KEY1_GPIO_PORT GPIOA
#define KEY1_GPIO_CLK RCC_AHB1Periph_GPIOA
#define KEY2_PIN GPIO_Pin_13
#define KEY2_GPIO_PORT GPIOC
#define KEY2_GPIO_CLK RCC_AHB1Periph_GPIOC
/*******************************************************/
以上代碼根據按鍵的硬體連接, 把檢測按鍵輸入的 GPIO 埠、 GPIO 引腳號以及
GPIO 埠時鐘封裝起來了。
2. 按鍵 GPIO 初始化函數:
利用上面的宏,編寫按鍵的初始化函數,見代碼清單 10-2。
代碼清單 10-2 按鍵 GPIO 初始化函數
/**
* @brief 配置按鍵用到的 I/O 口
* @param 無
* @retval 無
*/
void Key_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*開啟按鍵 GPIO 口的時鐘*/
RCC_AHB1PeriphClockCmd(KEY1_GPIO_CLK|KEY2_GPIO_CLK,ENABLE);
/*選擇按鍵的引腳*/
GPIO_InitStructure.GPIO_Pin = KEY1_PIN;
/*設置引腳為輸入模式*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
/*設置引腳不上拉也不下拉*/
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
/*使用上面的結構體初始化按鍵*/
GPIO_Init(KEY2_GPIO_PORT, &GPIO_InitStructure);
/*選擇按鍵的引腳*/
GPIO_InitStructure.GPIO_Pin = KEY2_PIN;
/*使用上面的結構體初始化按鍵*/
GPIO_Init(KEY2_GPIO_PORT, &GPIO_InitStructure);
}
同為 GPIO 的初始化函數,初始化的流程與「LED GPIO 初始化函數」章節中的類似,主要區別是引腳的模式。函數執行流程如下:
(1) 使用 GPIO_InitTypeDef 定義 GPIO 初始化結構體變量,以便下面用於存儲 GPIO 配置。
(2) 調用庫函數 RCC_AHB1PeriphClockCmd 來使能按鍵的 GPIO 埠時鐘,調用時我們使用「|」操作同時配置兩個按鍵的時鐘。
(3) 向 GPIO 初始化結構體賦值,把引腳初始化成浮空輸入模式,其中的 GPIO_Pin 使用宏「KEYx_PIN」來賦值,使函數的實現方便移植。 由於引腳的默認電平受按鍵電路影響,所以設置成「浮空/上拉/下拉」模式均沒有區別。
(4) 使用以上初始化結構體的配置,調用 GPIO_Init 函數向寄存器寫入參數,完成 GPIO 的初始化,這裡的 GPIO 埠使用「KEYx_GPIO_PORT」宏來賦值,也是為了程序移植方便。
(5) 使用同樣的初始化結構體,只修改控制的引腳和埠,初始化其它按鍵檢測時使用的GPIO 引腳。
3. 檢測按鍵的狀態:
初始化按鍵後,就可以通過檢測對應引腳的電平來判斷按鍵狀態了,見代碼清單 10-3。
代碼清單 10-3 檢測按鍵的狀態
/** 按鍵按下標置宏
* 按鍵按下為高電平,設置 KEY_ON=1, KEY_OFF=0
* 若按鍵按下為低電平,把宏設置成 KEY_ON=0 , KEY_OFF=1 即可
*/
#define KEY_ON 1
#define KEY_OFF 0
/**
* @brief 檢測是否有按鍵按下
* @param GPIOx:具體的埠, x 可以是(A...K)
* @param GPIO_PIN:具體的埠位, 可以是 GPIO_PIN_x(x 可以是 0...15)
* @retval 按鍵的狀態
* @arg KEY_ON:按鍵按下
* @arg KEY_OFF:按鍵沒按下
*/
uint8_t Key_Scan(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin)
{
/*檢測是否有按鍵按下 */
if (GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON ) {
/*等待按鍵釋放 */
while (GPIO_ReadInputDataBit(GPIOx,GPIO_Pin) == KEY_ON);
return KEY_ON;
} else
return KEY_OFF;
}
在這裡我們定義了一個 Key_Scan 函數用於掃描按鍵狀態。 GPIO 引腳的輸入電平可通過讀取 IDR 寄存器對應的數據位來感知,而 STM32 標準庫提供了庫函數GPIO_ReadInputDataBit 來獲取位狀態,該函數輸入 GPIO 埠及引腳號,函數返回該引腳的電平狀態,高電平返回 1,低電平返回 0。 Key_Scan 函數中以 GPIO_ReadInputDataBit 的返回值與自定義的宏「KEY_ON」對比,若檢測到按鍵按下,則使用 while 循環持續檢測按鍵狀態,直到按鍵釋放,按鍵釋放後 Key_Scan 函數返回一個「KEY_ON」值;若沒有檢測到按鍵按下,則函數直接返回「KEY_OFF」。若按鍵的硬體沒有做消抖處理,需要在這個 Key_Scan 函數中做軟體濾波,防止波紋抖動引起誤觸發。
4. 主函數:
接下來我們使用主函數編寫按鍵檢測流程,見代碼清單 10-4。
代碼清單 10-4 按鍵檢測主函數
/**
* @brief 主函數
* @param 無
* @retval 無
*/
int main(void)
{
/* LED 埠初始化 */
LED_GPIO_Config();
/*初始化按鍵*/
Key_GPIO_Config();
/* 輪詢按鍵狀態,若按鍵按下則反轉 LED */
while (1) {
if ( Key_Scan(KEY1_GPIO_PORT,KEY1_PIN) == KEY_ON ) {
/*LED1 反轉*/
LED1_TOGGLE;
}
if ( Key_Scan(KEY2_GPIO_PORT,KEY2_PIN) == KEY_ON ) {
/*LED2 反轉*/
LED2_TOGGLE;
}
}
}
代碼中初始化 LED 燈及按鍵後,在 while 函數裡不斷調用 Key_Scan 函數,並判斷其返回值,若返回值表示按鍵按下,則反轉 LED 燈的狀態。
10.2.3 下載驗證:
把編譯好的程序下載到開發板並復位,按下按鍵可以控制 LED 燈亮、滅狀態。
推薦閱讀
需求:LIN馬達控制器:AFS(DHL+AFL)——彎道輔助照明系統DHL:上極限,下極限,零位,馬達老化循環;AFL:左極限,右極限,零位,馬達老化循環;所有參數可配置:上極限,下極限,零位,左極限,右極限,馬達循環上極限,馬達循環下極限,馬達循環次數,馬達循環等待時間;保存至少30款產品的配置,配置界面需要有添加,讀取,查找,刪除功能。方案:STM32 + LIN + 串口(使用NXP的串口屏,TJA系列的LIN晶片)STM32的LIN接口作為主節點,馬達作為從節點。系統設計:RTX多任務設計,串口處理任務,顯示屏處理任務,LIN發送任務;(1)、串口處理任務:點擊串口屏會獲取到點擊的坐標值,串口中斷接受到數據加入到隊列;任務
發表於 2020-12-09
需求:(1)、點燈控制器:在線節拍,離線節拍;(2)、PWM控制盒:在線PWM,離線PWM;(3)、電流測試模塊:檢測車燈電流校準係數;方案:點燈控制器:STM32 + CAN + GPIO節拍:比如亮多長時間,滅多長時間;大節拍中嵌套多個小節拍,每個燈對應相同或者不同的節拍。上位機下發控制指令,表明此時是在線還是離線。(離線跑的節拍是在在線模式下下載的)在線模式:如果是直接輸出,按照指定格式下發CAN消息,MCU接受消息並解析,切繼電器點燈;如果是存儲節拍,MCU內部Flash存儲上位機通過CAN下發的點燈節拍。離線模式:從內部Flash中讀取節拍,並控制繼電器點燈;模式切換按鈕:不僅可以通過上位機控制在線/離線模式,還可
發表於 2020-12-09
功能:模擬人開車時,ACR和ABL的變化。 主控制器:STM32(CAN,串口,網口,輸入,輸出)上位機:LibView ACR:卷收器(座椅上面的安全帶)ABL:電機(座椅右下角接安全帶的插孔)PUMA:控制器發送CAN給PUMA,PUMA控制ACR和ABL(DBC文件的解析);ACR通過CAN控制,ABL通過PWM控制電機。 STM32硬體接口:按鍵盒8路輸入,網口與工控機軟體通信,CAN1直接控制ACR,CAN2給PUMA信號控制ACR,串口與上位機軟體通信(控制方向盤震動)。 主要有兩塊功能:靜態模式和遊戲模式。 靜態模式:UC-WinRoad沒工作時,STM32檢測
發表於 2020-12-09
, GPIO_InitTypeDef* GPIO_InitStruct){ uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00; uint32_t tmpreg = 0x00, pinmask = 0x00; /* 斷言,用於檢查輸入的參數是否正確 */ assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode)); assert
發表於 2020-12-09
專業開發工業設備診斷邊緣人工智慧(AI)的深度技術軟體公司Octonion 發布了一個STM32Cube擴展軟體包。該軟體包是針對來自橫跨多重電子應用領域的全球領先的半導體供應商意法半導體(STMicroelectronics,簡稱ST;紐約證券交易所代碼:STM)的工業級STM32L4 +微控制器開發板的優化過的狀態監測解決方案。 Octonions的新軟體包支持意法半導體在快速增長的工業狀態監測和預測性維護市場上發起的使用STM32微控制器和微處理器開發人工智慧應用的市場活動。Octonion的I-CUBE-OCTMI 軟體包是一個運行在STM32 超低功耗MCU上的自我維護系統,系統
發表於 2020-12-09
stm32f10x_conf.h:打開stm32f10x_gpio.h和stm32f10x_rcc.h;stm32f10x_gpio.c 和 stm32f10x_rcc.c加入工程模板中,只說重點。【stm32f10x_rcc.c用於配置系統時鐘 和外設時鐘,由於每個外設都要配置時鐘,所以它是每個外設都需要用到的庫文件。】// 新建led.h led.c#ifndef _LED_H_#define _LED_H_ #include "stm32f10x.h" #define ON 0#define OFF 1 #define LED1
發表於 2020-12-08