3.1普通方式
3.1.1 普通方式工作原理
按鍵 GPIO 端口有兩個(gè)方案可以選擇,一是采用上拉輸入模式,因?yàn)榘存I在沒按下的時(shí)候,是默認(rèn)為高電平的,采且內(nèi)部上拉模式正好符合這個(gè)要求。第二個(gè)方案是直接采用浮空輸入模式,因?yàn)榘凑沼布娐穲D,在芯片外部接了上拉電阻,其實(shí)就沒必要再配置成內(nèi)部上拉輸入模式了,因?yàn)樵谕獠可侠c內(nèi)部上拉效果是一樣的。
圖1按鍵電路
3.1.2 STM32Cube生成工程
關(guān)于如何使用使用STM32Cube新建工程在前文已經(jīng)講解過了,這里直說配置GPIO部分內(nèi)容。本文要實(shí)現(xiàn)按鍵功能,通過按鍵實(shí)現(xiàn)LED的亮滅。我門在第一個(gè)程序的基礎(chǔ)上進(jìn)行修改即可,不必每次都新建工程。根據(jù)圖1所示的電路,KEY1的引腳是PA0,我們將PA0的GPIO設(shè)置為下拉的輸入模式,保留3個(gè)LED的GPIO配置。
圖2
初始化基本配置后,我們重新生成工程,接下來按鍵編程。
3.1.3普通方式的具體代碼分析
在看代碼前,我們先看看按鍵掃描編程的流程:
1)使能按鍵引腳時(shí)鐘,本文的引腳是PA0;
2)初始化按鍵,即初始化GPIO機(jī)構(gòu)體,在前文已經(jīng)詳細(xì)講解過了;
3)在無限循環(huán)中不斷讀取PA0的電平值,同時(shí)進(jìn)行按鍵消抖;
4)判斷按鍵被按下時(shí),進(jìn)行相應(yīng)的處理。
? GPIO 初始化配置
static void MX_GPIO_Init(void){ GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOG, GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_RESET); /*Configure GPIO pin : PA0 */ GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /*Configure GPIO pin : PB0 */ GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /*Configure GPIO pins : PG6 PG7 */ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);}
按鍵與 LED 的 GPIO 初始化函數(shù)類似,區(qū)別只是在這個(gè)函數(shù)中,要開啟的 GPIO 的端口時(shí)鐘不一樣,并且把檢測按鍵用的引腳 Pin 的模式設(shè)置為適合按鍵應(yīng)用的上拉輸入模式(由于接了外部上拉電阻,也可以使用浮空輸入,讀者可自行修改代碼做實(shí)驗(yàn))。若 GPIO 被設(shè)置為輸入模式,不需要設(shè)置 GPIO 端口的最大輸出速度。
? 按鍵狀態(tài)監(jiān)測及按鍵消抖
uint8_t Key_Scan(void)
{
if(HAL_GPIO_ReadPin(KEY_GPIO,GPIO_PIN_0) == KEY_DOWN_LEVEL )
{
HAL_Delay(10);
if(HAL_GPIO_ReadPin(KEY_GPIO,GPIO_PIN_0) == KEY_DOWN_LEVEL )
{
while(HAL_GPIO_ReadPin(KEY_GPIO,GPIO_PIN_0) == KEY_DOWN_LEVEL);
return KEY_DOWN;
}
else
{
return KEY_UP;
}
}
return KEY_UP;
}
相信延時(shí)消抖的原理大家在學(xué)習(xí)其他單片機(jī)時(shí)就已經(jīng)了解了,本函數(shù)的功能就是掃描輸入?yún)?shù)中指定的引腳,檢測其電平變化,并作延時(shí)消抖處理,最終對按鍵消息進(jìn)行確認(rèn)。
? 利用HAL_GPIO_ReadPin()函數(shù)讀取輸入數(shù)據(jù),若從相應(yīng)引腳讀取的數(shù)據(jù)等于 0(KEY_DOWN),低電平,表明可能有按鍵按下,調(diào)用延時(shí)函數(shù)。否則返回 KEY_UP,表示按鍵沒有被按下。
? 延時(shí)之后再次利用 HAL_GPIO_ReadPin()函數(shù)讀取輸入數(shù)據(jù),若依然為低電平,表明確實(shí)有按鍵被按下了。否則返回 KEY_UP,表示按鍵沒有被按下。
? 循環(huán)調(diào)用HAL_GPIO_ReadPin()函數(shù)一直檢測按鍵的電平,直至按鍵被釋放,被釋放后,返回表示按鍵被按下的標(biāo)志 KEY_DOWN。以上是按鍵消抖的流程,調(diào)用了一個(gè)庫函數(shù) HAL_GPIO_ReadPin()函數(shù)。輸入?yún)?shù)為要讀取的端口、引腳,返回引腳的輸入電平狀態(tài),高電平為 1,低電平為 0。
Main函數(shù)如下:
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
*
© Copyright (c) 2020 STMicroelectronics. * All rights reserved.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the 'License'; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include 'main.h'
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
typedef enum{
KEY_UP = 0,
KEY_DOWN = 1,
}KEYState_Type;
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define KEY_GPIO GPIOA
#define KEY_GPIO_PIN GPIO_PIN_0
#define KEY_DOWN_LEVEL 1
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
uint8_t Key_Scan(void);
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
if(KEY_DOWN_LEVEL == Key_Scan())
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_6);
HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_7);
}
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief Key Scan
* @retval uint8_t
*/
uint8_t Key_Scan(void)
{
if(HAL_GPIO_ReadPin(KEY_GPIO,GPIO_PIN_0) == KEY_DOWN_LEVEL )
{
HAL_Delay(10);
if(HAL_GPIO_ReadPin(KEY_GPIO,GPIO_PIN_0) == KEY_DOWN_LEVEL )
{
while(HAL_GPIO_ReadPin(KEY_GPIO,GPIO_PIN_0) == KEY_DOWN_LEVEL);
return KEY_DOWN;
}
else
{
return KEY_UP;
}
}
return KEY_UP;
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOG_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_RESET);
上一篇:LCD1602單片機(jī)(STC51/STM32)驅(qū)動(dòng)程序詳解
下一篇:STM32串口接收不定長數(shù)據(jù)(接收中斷+超時(shí)判斷)
- 熱門資源推薦
- 熱門放大器推薦
設(shè)計(jì)資源 培訓(xùn) 開發(fā)板 精華推薦
- 意法半導(dǎo)體推出用于匹配遠(yuǎn)距離無線微控制器STM32WL33的集成的匹配濾波芯片
- ESP32開發(fā)板連接TFT顯示屏ST7789跳坑記
- 如何讓ESP32支持analogWrite函數(shù)
- LGVL配合FreeType為可變字體設(shè)置字重-ESP32篇
- 使用樹莓派進(jìn)行 ESP32 Jtag 調(diào)試
- ESP32怎么在SPIFFS里面存儲html,css,js文件,以及網(wǎng)頁和arduino的通訊
- ESP32 freeRTOS使用測試
- API調(diào)用小記(Touchdesigner和ESP32)
- 關(guān)于ESP32/8266使用async-mqtt-client庫的一些基本介紹
- 典型應(yīng)用顯示使用 A8510 LED 驅(qū)動(dòng)器的 P-MOSFET 感應(yīng)進(jìn)行 VIN 到 GND 短路保護(hù)
- AD8310-EVAL,評估板經(jīng)過精心布局和測試,以展示 AD8310 的指定高速性能
- KeyBoard.Juk.Mx.32.Rev.A
- 簡單易懂的SWD(JTAG20P)-SWD轉(zhuǎn)接板
- 曼塔R2遙控器改裝版
- LT3990IMSE-3.3 3.3V 降壓轉(zhuǎn)換器的典型應(yīng)用
- 【航順】云臺小豬手
- 使用 Analog Devices 的 LT1317BCS8 的參考設(shè)計(jì)
- LTC2376-16、16 位、250ksps、低功率 SAR ADC 的典型應(yīng)用電路
- NCV33174DTBR2G 直流耦合反相放大器最大輸出擺幅的典型應(yīng)用,采用單 +5V 電源
- 步進(jìn)電機(jī)控制指令詳解
- 依利浦實(shí)驗(yàn)室人工智能平臺為Ceva NeuPro-Nano NPU優(yōu)化 推動(dòng)實(shí)現(xiàn)更智能的邊緣設(shè)備
- Bourns 全新推出兩款屏蔽功率電感器系列 專為 DDR5 電源管理電路開發(fā)
- Bourns 推出新型電流變壓器產(chǎn)品,采用坡莫合金 T 型磁芯結(jié)構(gòu),具備高匝數(shù)比特性
- 羅克韋爾自動(dòng)化推出 OptixEdge 高級邊緣網(wǎng)關(guān),助力客戶釋放數(shù)據(jù)潛力
- 通用汽車斥資 40 億美元,擬將主要制造業(yè)遷回美國
- 是德科技助力蔚來驗(yàn)證新一代 汽車無線系統(tǒng)
- 為敏感的器件打造超低噪聲電源
- Teledyne Space Imaging 發(fā)布通過航天級篩選的工業(yè)圖像傳感器
- 曝韓國電池供應(yīng)商LG與奇瑞簽署合作協(xié)議:訂單規(guī)模達(dá)8GWh!
- 阿里/百度/小米三大巨頭拿下智能音箱95%市場背后
- 看完這篇文章就知道新能源汽是否值得購買
- 特斯拉市值一路攀升,蔚來汽車向前追趕
- Batman和Robin---特斯拉MODEL 3 BMS的采樣芯片
- 5月份新能源汽車部分上牌數(shù)據(jù)分析
- 評芯而論:市值重登1萬億美元巔峰,蘋果的三大挑戰(zhàn)剛開始
- 任正非打算向西方出售5G技術(shù),塑造競爭對手
- 盧偉冰發(fā)四大質(zhì)問,駁斥塑料比玻璃機(jī)身更堅(jiān)固的言論
- 評芯而論:鴻海廣州面板廠量產(chǎn)暫緩,或?yàn)榧瘓F(tuán)財(cái)務(wù)
- 芯原微電子完成了上市輔導(dǎo),在科創(chuàng)板上市可期