STM32筆記(17):按鍵控制-使用 GPIO 讀取

前一篇文章是第一次學會如何使用 GPIO 來控制 LED 的亮與滅:STM32筆記(15):使用 GPIO 控制紅綠燈 ,本篇將繼續使用 GPIO ,就由讀取 GPIO 的狀態來判斷按鍵是否被按下? 同時瞭解一下函式的用法。

[常用的GPIO函式(續)]

GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx , uint16_t GPIO_Pin)
讀取 IO 輸入引腳的值。
- 引數 GPIOx:對應的 GPIO,範圍是 GPIOA ~ GPIOG。
- 引數 GPIO_Pin:引腳編號,可以是GPIO_Pin_0 ~ GPIO_Pin_15 及 GPIO_Pin_All。
返回值:傳回一個 unit8_t 輸出管腳的值,僅有兩種狀態 Bit_SET(高電位),Bit_RESET(低電位)

GPIO_ReadInputData(GPIO_TypeDef* GPIOx)
讀取 IO 輸入的資料,該函式用於讀取一個 GPIOx 分組的所有資料。
- 引數 GPIOx:對應的 GPIO,範圍是 GPIOA ~ GPIOG。
返回值:一個 GPIOx 的所有資料(輸入狀態),也就是一組 16 位元的值。

GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx , uint16_t GPIO_Pin)
讀取 IO 輸出引腳的值。
- 引數 GPIOx:對應的 GPIO,範圍是 GPIOA ~ GPIOG。
- 引數 GPIO_Pin:引腳編號,可以是GPIO_Pin_0 ~ GPIO_Pin_15 及 GPIO_Pin_All。
返回值:傳回一個 unit8_t 輸出管腳的值,僅有兩種狀態 Bit_SET(高電位),Bit_RESET(低電位)

GPIO_ReadOutputData(GPIO_TypeDef* GPIOx)
讀取 IO 輸出的資料,該函式用於讀取一個 GPIOx 分組的所有資料。
- 引數 GPIOx:對應的 GPIO,範圍是 GPIOA ~ GPIOG。
返回值:一個 GPIOx 的所有資料(輸出狀態),也就是一組 16 位元的值。

[材料]

  • STM32F103C8T6 主板 x 1
  • OLED SSD1306 顯示器 x1
  • 麵包板 x1
  • LED x 1 個
  • 按鍵 x 1 個
  • STLINK V2 模擬下載器 x 1
  • 連接線 x N 條

[接線與電路圖]

LED 正極(長腳)接到 3.3v,另一腳接在 STM32F103 的 PA0,按鍵的一個接腳接在 GND,另一腳接在 PB14。STM32F103x 連接 SSD1306 方式如下:
STM32F103xSSD1306 OLED按鍵
3.3vVDD-
GNDGND其中一個 Pin
B8SCK/SCL-
B9SDA-
B14-另一個 Pin

[程式]

主程式一開始先對 OLED 進行初始化,再設定一個引腳 GPIO 連接 LED 燈,進入迴圈循環時,執行定義在 Button.c 檔案中的 Button_Press() ,如果按下,傳回 KeyNum 值,然後判斷 KeyNum 來決定是否讓 LED 燈亮或滅。主程式 main.c 如下:
#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "delay.h"
#include "sys.h"
#include "oled.h"
#include "bmp.h"
#include "button.h"

uint8_t KeyNum;

int main (void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  //開啟GPIOA的外設時鐘
	GPIO_InitTypeDef GPIO_InitStruct;    // 定義一個GPIO_InitTypeDef類型的結構體
	
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;  //選擇要控制的GPIOA引腳
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;   //設置引腳速率為2MHz
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;   //設置引腳為通用推輓輸出模式
	GPIO_Init(GPIOA, &GPIO_InitStruct);  			//調用庫函數,初始化GPIOA5引腳

	// 將引腳設為高電位
	GPIO_SetBits(GPIOA, GPIO_Pin_0);	
	
	delay_init();	    	 //延時函數初始化	  
	OLED_Init();		 //初始化OLED  
	Button_Init2();
	OLED_Clear(0);           //清除螢幕
	OLED_ShowString(2, 2, "Status:",16);	
	while (1)
	{
		KeyNum = Button_Press();
		if (KeyNum == 1) {
			GPIO_ResetBits(GPIOA, GPIO_Pin_0);		// 點亮 LED
			OLED_ShowString(60, 2, "On ",16); 
		}
		else {	
			GPIO_SetBits(GPIOA, GPIO_Pin_0);		// 熄滅 LED
			OLED_ShowString(60, 2, "Off",16);
		}
	}
}

Button.c 有兩個主要函式:
  • Button_Init2(void)是初始化按鍵 GPIO。
  • Button_Press(void)是讀取 GPIO 的狀態,判斷按鍵是否被按下?
#include "stm32f10x.h"                  // Device header
#include "delay.h"

void Button_Init2(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
}

uint8_t Button_Press(void)
{
extern uint8_t KeyNum;   // KeyNum 定義為全域變數
	if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0)	
	{
		delay_ms(20);
		while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0); //迴圈等到按鍵被按下
		delay_ms(20);
		KeyNum = !KeyNum; 
	}
	return KeyNum;
}

button.h 的內容如下:
#ifndef __BUTTON_H
#define __BUTTON_H

void Button_Init2(void);
uint8_t Button_Press(void);

#endif

完整的程式請參考 Github:3. Push button control led using GPIO

[結果]

初始設定 LED 為熄滅,按一下開,再按一下為亮/滅循環。


[參考資料]


Post a Comment

較新的 較舊