05-GPIO原理

一、概述

1、GPIO,即通用I/O(輸入/輸出)端口,是STM32可控制的引腳。STM32芯片的GPIO引腳與外部設備連接起來,可實現與外部通訊、控制外部硬件或者采集外部硬件數據的功能。

?2、GPIO的復用:引腳復用是指將單個引腳配置為多個功能的能力。在 STM32 中,每個引腳都可以配置為多個不同的功能,如GPIO(輸入/輸出數據)、定時器、UART、SPI等。這樣一來,通過配置引腳復用功能,可以實現多種硬件功能的連接和實現,提高了芯片的靈活性和可擴展性。引腳默認為IO口。

二、GPIO的工作模式

?1、八大模式和四種輸出速度

4種輸入模式

(1)浮空輸入(即不連接內部上下拉電阻)

(2)上拉輸入(連接上拉電阻)

(3)下拉輸入(連接下拉電阻)

(4)模擬輸入(用于檢測模擬信號的輸入)

4種輸出模式?

(5)開漏輸出(帶上拉或者下拉)

(6)復用開漏輸出(帶上拉或者下拉)

(7)推挽輸出(帶上拉或者下拉):程序員可以輸出高電平與低電平

(8)復用推挽輸出(帶上拉或者下拉):程序員可以低電平,想要輸出電平,芯片外部需要有上拉電阻。

4種最大輸出速度

(1)2MHZ? (低速)

(2)25MHZ??(中速)

(3)50MHZ??(快速)

(4)100MHZ??(高速)

2、上下拉電阻

上拉電阻:

  • 將一個不確定的信號,通過一個電阻與電源VCC相連,固定在高電平;
  • 上拉是對器件注入電流;灌電流
  • 當一個接有上拉電阻的IO端口設置為輸入狀態時,它的常態為高電平;

下拉電阻:

  • 將一個不確定的信號,通過一個電阻與地GND相連,固定在低電平;
  • 下拉是從器件輸出電流;拉電流
  • 當一個接有下拉電阻的IO端口設置為輸入狀態時,它的常態為低電平;

?三、寄存器編程

1、基本概念

寄存器是微處理器或微控制器內部的小型存儲單元,用于臨時存儲數據、指令或控制信號。寄存器通常由硬件實現,并且可以直接通過CPU訪問。寄存器的設計目的是為了提高處理器的性能,因為它們比內存訪問更快。在微控制器如STM32F407中,寄存器用于配置和控制各種外設的功能。

2、寄存器分類

  1. 通用寄存器:用于存儲數據或作為臨時存儲空間。
  2. 狀態寄存器:存儲有關處理器狀態的信息,如標志位。
  3. 控制寄存器:用于控制處理器的行為。
  4. 外設寄存器:用于配置和控制微控制器中的外設。

?3、常見寄存器及用途

GPIO寄存器:- GPIOx_MODER:配置GPIO引腳的工作模式(輸入、輸出、復用功能等)。
- GPIOx_OTYPER:配置GPIO引腳的輸出類型(推挽或開漏)。
- GPIOx_OSPEEDR:配置GPIO引腳的輸出速度。
- GPIOx_PUPDR:配置GPIO引腳的上拉/下拉電阻。
- GPIOx_IDR:讀取GPIO引腳的輸入值。
- GPIOx_ODR:設置GPIO引腳的輸出值。
- GPIOx_BSRR:設置或清除GPIO引腳的輸出值。
- GPIOx_LCKR:鎖定GPIO引腳的配置。時鐘控制寄存器:
- RCC_CR:控制時鐘源的選擇和啟動。
- RCC_PLLCFGR:配置PLL(Phase-Locked Loop)時鐘。
- RCC_CFGR:配置時鐘樹,包括AHB/APB總線時鐘。
- RCC_CIR:時鐘中斷寄存器。中斷寄存器:
- NVIC_ISER:中斷使能寄存器。
- NVIC_ICER:中斷清除使能寄存器。
- NVIC_ISPR:中斷掛起寄存器。
- NVIC_ICPR:中斷清除掛起寄存器。
- NVIC_IPR:中斷優先級寄存器。

4、寄存器地址 = 外設的基地址+偏移地址

下面的邊界地址即為外設的基地址

例如

RCC_AHB1ENR寄存器地址 = RCC基地址+偏移地址

RCC_AHB1ENR寄存器地址 = 0x40023800+0x30

寄存器分析;

5、寄存器點燈例子:

(1)理解LED電路原理圖

LED0連接在PF9

PF9輸出低電平,燈亮;輸出高電平,燈滅

led.c文件代碼:

#include "led.h"/************************************
引腳說明:
LED0連接在PF9
PF9輸出低電平,燈亮;輸出高電平,燈滅************************************/void Led_Init(void)
{    //將第5位置1,你使能GPIOF組時鐘RCC_AHB1ENR |= (0x01<<5);//配置PF9輸出模式GPIOF_MODER &= ~(0x01<<19); //19位清0GPIOF_MODER |= (0x01<<18);  //18位置1//配置PF9推挽輸出GPIOF_OTYPER &= ~(0x01<<9); //9位清0//配置PF9中速 25MHZGPIOF_OSPEEDR &= ~(0x01<<19); //19位清0GPIOF_OSPEEDR |= (0x01<<18);  //18位置1    //配置PF9中速無上下拉GPIOF_PUPDR &= ~(0x01<<19); //19位清0GPIOF_PUPDR &= ~(0x01<<18); //18位清0
}

main.c文件:


#include <stdio.h>
#include "led.h"//粗延時(就是延時不一定準確的意思)void delay(int n)
{int i, j;for(i=0; i<n; i++)for(j=0; j<10000; j++);
}int main(void)
{//初始化后GPIOF_ODR默認為低電平,所以燈亮Led_Init();while(1){//燈亮GPIOF_ODR &= ~(0x01<<9);  //9位清0delay(1000);//燈滅GPIOF_ODR |= (0x01<<9);  //9位置1delay(1000);        }return 0;
}

led.h文件:

#ifndef __LED_H
#define __LED_H//注意:0x40023800這個地址是根據不同的寄存器來決定的,編寫多個寄存器的時候要非常注意有沒有改
#define  RCC_AHB1ENR   	*((volatile unsigned int *)(0x40023800 + 0x30)) //值強制轉換為地址  通過解引用訪問地址空間
#define  GPIOF_MODER   	*((volatile unsigned int *)(0x40021400 + 0x00)) 
#define  GPIOF_OTYPER   *((volatile unsigned int *)(0x40021400 + 0x04)) 
#define  GPIOF_OSPEEDR  *((volatile unsigned int *)(0x40021400 + 0x08)) 
#define  GPIOF_PUPDR    *((volatile unsigned int *)(0x40021400 + 0x0C)) 
#define  GPIOF_ODR    	*((volatile unsigned int *)(0x40021400 + 0x14))
void Led_Init(void);#endif

四、使用庫函數編程來點燈的例子

1、背景

🔸優點:

  • 性能優化: 直接通過寄存器進行操作可以減少中間層的調用,提高程序執行效率。
  • 靈活性高: 寄存器編程允許開發者直接控制硬件,提供最大的靈活性來定制特定的功能。
  • 代碼緊湊: 通常情況下,寄存器級別的編程會生成更緊湊的代碼,有助于節省內存空間。

🔸缺點:

  • 易出錯: 寄存器編程需要對硬件有深入的理解,容易因為配置錯誤而導致問題。
  • 移植性差: 不同的微控制器可能有不同的寄存器布局和功能,這使得代碼難以在不同的硬件之間移植。
  • 調試困難: 錯誤往往不易被發現,調試過程可能會比較復雜且耗時。

2、庫函數的使用步驟

1、需要在keil5中添加RCC和GPIO庫

2、使能端口F(PF9屬于GPIOF組)的硬件時鐘(芯片所有外設都是關閉時鐘,原因為了降低功耗)

//使能GPIOF組時鐘
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);

3、(3)初始化引腳功能(推挽輸出 速度 上/下拉)

  GPIO_InitTypeDef    GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin    = GPIO_Pin_9; //引腳9GPIO_InitStruct.GPIO_Mode    = GPIO_Mode_OUT;//輸出GPIO_InitStruct.GPIO_OType    = GPIO_OType_PP;//推挽模式GPIO_InitStruct.GPIO_Speed    = GPIO_Speed_25MHz;//25MHZ速度GPIO_InitStruct.GPIO_PuPd    = GPIO_PuPd_NOPULL; //無上下拉GPIO_Init(GPIOF, &GPIO_InitStruct);

4、設置引腳電平

GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) //設置引腳為高電平
GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)//設置引腳為低電平

3、庫函數開發例子2(按鍵)

(1)理解KEY電路原理圖

KEY0連接PA0

KEY0按下,PA0為低電平

KEY0未按下,PA0為高電平

2、使能GPIO時鐘

    //使能GPIOA組時鐘RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);    

3、配置PA0引腳

引腳輸入時,不需要配置GPIO 端口輸出類型及GPIO 端口輸出速度

    //結構體變量GPIO_InitTypeDef    GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin    = GPIO_Pin_0;     //引腳0GPIO_InitStruct.GPIO_Mode    = GPIO_Mode_IN;    //輸入模式GPIO_InitStruct.GPIO_PuPd    = GPIO_PuPd_UP; //根據外面電路來設置即可

4、讀引腳電平

uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

具體代碼:四個按鍵控制四個燈

key.h文件:

#ifndef   _KEY_H
#define   _KEY_H#include "stm32f4xx.h"void key_init(void);
void led_init(void);enum
{key0 = 1,key1,key2,key3,
};u8 Key_Scan(u8 mode);#endif

key.c文件:

#include "key.h"//key2,key3,key4的引腳為PE組的2,3,4void key_init(void)
{// 使能GPIOA組時鐘RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN; // 入GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; // 上拉GPIO_Init(GPIOA, &GPIO_InitStruct);// 使能GPIOE組時鐘RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);GPIO_InitTypeDef GPIO_InitStruct1;GPIO_InitStruct1.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;GPIO_InitStruct1.GPIO_Mode = GPIO_Mode_IN; // 入GPIO_InitStruct1.GPIO_PuPd = GPIO_PuPd_UP; // 上拉GPIO_Init(GPIOE, &GPIO_InitStruct1);
}void led_init(void)
{// 使能GPIOF組時鐘RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; // 引腳9GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;			 // 輸出GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;			 // 推挽模式GPIO_InitStruct.GPIO_Speed = GPIO_Speed_25MHz;		 // 25MHZ速度GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;		 // 無上下拉GPIO_Init(GPIOF, &GPIO_InitStruct);// 使能GPIOE組時鐘RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);GPIO_InitTypeDef GPIO_InitStruct1;GPIO_InitStruct1.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14; // 引腳13GPIO_InitStruct1.GPIO_Mode = GPIO_Mode_OUT;			   // 輸出GPIO_InitStruct1.GPIO_OType = GPIO_OType_PP;		   // 推挽模式GPIO_InitStruct1.GPIO_Speed = GPIO_Speed_25MHz;		   // 25MHZ速度GPIO_InitStruct1.GPIO_PuPd = GPIO_PuPd_NOPULL;		   // 無上下拉GPIO_Init(GPIOE, &GPIO_InitStruct1);// 關閉所有LED(假設低電平點亮LED)GPIO_SetBits(GPIOF, GPIO_Pin_9 | GPIO_Pin_10);GPIO_SetBits(GPIOE, GPIO_Pin_13 | GPIO_Pin_14);
}void delays(int n)
{int i, j;for (i = 0; i < n; i++)for (j = 0; j < 10000; j++);
}// u8 == unsigned char
/************************************
函數功能:按鍵掃描
返回值:
成功:按下返回按鍵標志位,如:KEY0標志位1,KEY1標志位2,KEY2標志位3,KEY3標志位4
失敗:0u8 mode:是否支持連按
0:不支持連按
1:支持連按*************************************/
u8 Key_Scan(u8 mode)
{// key_up保存上一次的值static u8 key_up = 1; // 按鍵標志,表示未按下if (mode == 1) // 支持連按key_up = 1;if (key_up && (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 0) | (GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_2) == 0) | (GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_3) == 0) | (GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_4) == 0)){delays(15);key_up = 0; // 表示按下(防止重復觸發)if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 0){return key0; // KEY0標志值為1}if (GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_2) == 0){return key1; // KEY0標志值為1}if (GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_3) == 0){return key2; // KEY0標志值為1}if (GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_4) == 0){return key3; // KEY0標志值為1}}else if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == 1 | GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_2) == 1 | GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_3) == 1 | GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_4) == 1) // 未按下--也可以理解為松開{key_up = 1; // 按鍵松開key_up == 1}// 未操作按鍵(按鍵松開)return 0;
}

main.c文件:

#include <stdio.h>
#include "key.h"//粗延時(就是延時不一定準確的意思)void delay(int n)
{int i, j;for(i=0; i<n; i++)for(j=0; j<10000; j++);
}int main()
{//初始化后GPIOF_ODR默認為低電平,所以燈亮key_init();led_init();u8 value = 0;u8 key = 0;while(1){     //支持連按key = Key_Scan(1);if(key == key2){GPIO_ToggleBits(GPIOE, GPIO_Pin_13);}//不支持連按value = Key_Scan(0);if(value == key0){GPIO_ToggleBits(GPIOF, GPIO_Pin_9);}if(value == key1){GPIO_ToggleBits(GPIOF, GPIO_Pin_10);}
//		if(value == 3)
//		{
//			GPIO_ToggleBits(GPIOE, GPIO_Pin_13);
//		}if(value == key3){GPIO_ToggleBits(GPIOE, GPIO_Pin_14);}}return 0;
}

五、應用領域:如常見家里的電子門鎖。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/77264.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/77264.shtml
英文地址,請注明出處:http://en.pswp.cn/web/77264.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于LangChain4J的AI Services實踐:用聲明式接口重構LLM應用開發

基于LangChain4J的AI Services實踐&#xff1a;用聲明式接口重構LLM應用開發 前言&#xff1a;當Java開發遇上LLM編程困境 在LLM應用開發領域&#xff0c;Java開發者常面臨兩大痛點&#xff1a;一是需要手動編排Prompt工程、記憶管理和結果解析等底層組件&#xff0c;二是復雜…

深入解析 Docker 容器進程的 cgroup 和命名空間信息

深入解析 Docker 容器進程的 cgroup 和命名空間信息 在現代 Linux 系統中&#xff0c;控制組&#xff08;cgroup&#xff09;和命名空間&#xff08;namespace&#xff09;是實現容器化技術的核心機制。cgroup 用于管理和限制進程的資源使用&#xff08;如 CPU、內存、I/O&…

【汽車ECU電控數據管理篇】S19文件格式解析篇章

一、S19格式是啥 在電控文件管理的初期階段&#xff0c;我首次接觸到的是 A2L 和 HEX 文件。其中&#xff0c;A2L 文件主要承擔著描述性功能&#xff0c;它詳細地描述了各種參數和配置等相關信息。而 HEX 文件則是一種刷寫文件&#xff0c;其內部明確記錄了具體的地址以及對應的…

python編程相關的單詞

the: 在編程中&#xff0c;“the” 是一個常見的英語單詞&#xff0c;用于指定特定的對象或變量。例如&#xff0c;“the function” 指的是某個特定的函數。 the的拼寫是t,h,e.再讀一次t,h,e and: 在編程中&#xff0c;“and” 是一個邏輯運算符&#xff0c;用于連接兩個條件&…

網絡原理 - 4(TCP - 1)

目錄 TCP 協議 TCP 協議段格式 可靠傳輸 幾個 TCP 協議中的機制 1. 確認應答 2. 超時重傳 完&#xff01; TCP 協議 TCP 全稱為 “傳輸控制協議”&#xff08;Transmission Control Protocol&#xff09;&#xff0c;要對數據的傳輸進行一個詳細的控制。 TCP 協議段格…

python博客爬蟲列表

我希望對指定網頁的&#xff0c;博客列表&#xff0c;獲取url&#xff0c;然后保存成本地文件&#xff0c;用python實現 step1: import requests from bs4 import BeautifulSoup import jsondef get_blog_links(url):headers {User-Agent: Mozilla/5.0 (Windows NT 10.0; Win6…

軟件測試入門學習筆記

今天學習新知識&#xff0c;軟件測試。 什么是軟件測試&#xff1f; 使用人工和自動手段來運行或測試某個系統的過程&#xff0c;目的在于檢驗它是否滿足規定的需求或弄清實際結果與預期結果之間的差別。 軟件測試的目的&#xff1f; 1&#xff09;為了發現程序&#xff0…

uniapp開發2--uniapp中的條件編譯總結

以下是對 uni-app 中條件編譯的總結&#xff1a; 概念&#xff1a; 條件編譯是一種技術&#xff0c;允許你根據不同的平臺或環境&#xff0c;編譯不同的代碼。 在 uni-app 中&#xff0c;這意味著你可以編寫一套代碼&#xff0c;然后根據要編譯到的平臺&#xff08;例如微信小…

【k8s】sidecar邊車容器

一、Sidecar 模式簡介 Sidecar 模式是一種常見的微服務架構設計模式。它通過將附加功能或服務與主應用程序部署在同一容器或主機上&#xff0c;從而實現對主應用程序的增強和擴展。Sidecar 的名稱來源于摩托車的邊車&#xff0c;它與摩托車緊密相連&#xff0c;為主車提供額外…

MySQL索引使用一定有效嗎?如何排查索引效果?

MySQL索引使用一定有效嗎&#xff1f;如何排查索引效果&#xff1f; 1. 索引一定有效嗎&#xff1f; 不一定&#xff01; 即使你創建了索引&#xff0c;MySQL 也可能因為以下原因 不使用索引 或 索引效果不佳&#xff1a; 索引選擇錯誤&#xff1a;MySQL 優化器可能選擇了錯…

漏洞管理體系:從掃描評估到修復驗證的全生命周期實踐

漏洞管理體系&#xff1a;從掃描評估到修復驗證的全生命周期實踐 在網絡安全防御體系中&#xff0c;漏洞管理是“攻防博弈”的核心戰場。據NVD&#xff08;國家漏洞數據庫&#xff09;統計&#xff0c;2023年新增漏洞超21萬個&#xff0c;平均每天披露575個&#xff0c;其中32…

cdh平臺管理與運維最佳實踐

一、容量規劃:構建可持續擴展的數據湖底座 1.1 資源評估三維模型 #mermaid-svg-4Fd5JDKTgwqF1BUd {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-4Fd5JDKTgwqF1BUd .error-icon{fill:#552222;}#mermaid-svg-4Fd5J…

力扣347:前K個高頻元素

給你一個整數數組 nums 和一個整數 k &#xff0c;請你返回其中出現頻率前 k 高的元素。你可以按 任意順序 返回答案。 示例 1: 輸入: nums [1,1,1,2,2,3], k 2 輸出: [1,2]示例 2: 輸入: nums [1], k 1 輸出: [1]題解&#xff1a; 一、思路&#xff1a; 1.我希望將nu…

前饋神經網絡層

FeedForward Network 論文地址 https://arxiv.org/pdf/1706.03762 前饋網絡介紹 前饋網絡是Transformer模型中的關鍵組件&#xff0c;每個Transformer層包含一個多頭注意力模塊和一個前饋網絡模塊。該模塊通過兩次線性變換和激活函數&#xff0c;為模型提供非線性建模能力。其核…

如何將 sNp 文件導入并繪制到 AEDT (HFSS)

導入 sNp 文件 打開您的項目&#xff0c;右鍵單擊 “Result” 繪制結果 導入后&#xff0c;用戶可以選擇它進行打印。請參閱下面的示例。要點&#xff1a;確保從 Solution 中選擇它。

es-核心儲存原理介紹

原始數據 idusernamegradedescription1ahua87i like study2xiaowang92i like es3zhaoyun63i like java 倒排索引 description使用的text分詞&#xff0c;使用倒排索引 termidi1,2,3like1,2,3study1es2java3 分詞后&#xff0c;如果匹配 es&#xff0c;則需要逐行匹配&…

jmeter中監控服務器ServerAgent

插件下載&#xff1a; 將ServerAgent上傳至需要監控的服務器&#xff0c;mac/liunx啟動startAgent.sh&#xff08;啟動命令&#xff1a;./startAgent.sh&#xff09; 在jmeter中添加permon監控組件 配置需要監控的服務器IP地址&#xff0c;添加需要監控的資源 注意&#xf…

UML 狀態圖:以共享汽車系統狀態圖為例

目錄 一、初識 UML 狀態圖 二、共享汽車系統狀態圖詳解 &#xff08;一&#xff09;初始狀態與車輛空閑狀態 &#xff08;二&#xff09;用戶預定相關狀態 &#xff08;三&#xff09;等待取車與用戶取車狀態 &#xff08;四&#xff09;用戶還車及后續狀態 三、狀態圖繪…

橙子果品分級-目標檢測數據集(包括VOC格式、YOLO格式)

橙子果品分級-目標檢測數據集&#xff08;包括VOC格式、YOLO格式&#xff09; 數據集&#xff1a; 鏈接&#xff1a;https://pan.baidu.com/s/1jpdrylu06mm0r9pGVyb-AQ?pwd94a6 提取碼: 94a6 數據集信息介紹&#xff1a; 共有 9195 張圖像和一一對應的標注文件 標注文件格式…

uniapp 仿企微左邊公司切換頁

示例代碼&#xff1a; <template><view class"container"><!-- 遮罩層 --><view class"mask" v-if"showSidebar" click"closeSidebar"></view><!-- 側邊欄 --><view class"sidebar"…