天天看點

STM32F103 GPIO口的配置和應用詳解

STM32F103ZET6

  • 一共有7組IO口(有FT的辨別是可以識别5v的)
  • 每組IO口有16個IO
  • 一共16*7=112個IO

4種輸入模式:

(1) GPIO_Mode_AIN 模拟輸入

(2) GPIO_Mode_IN_FLOATING 浮空輸入

(3) GPIO_Mode_IPD 下拉輸入

(4) GPIO_Mode_IPU 上拉輸入

4種輸出模式:

(5) GPIO_Mode_Out_OD 開漏輸出

(6) GPIO_Mode_Out_PP 推挽輸出

(7) GPIO_Mode_AF_OD 複用開漏輸出

(8) GPIO_Mode_AF_PP 複用推挽輸出

四種輸入模式:

1、一圖記住上拉、下拉、浮空輸入模式:

STM32F103 GPIO口的配置和應用詳解

原理分析:圖中箭頭表示信号流動方向。從I/O引腳向左沿着箭頭方向,首先遇到兩個開關和電阻,與VDD相連的稱為上拉電阻,與Vss相連的稱為下拉電阻,再連接配接到施密特觸發器(信号轉換)把電壓信号轉化為0、1的數字信号,存儲在輸入資料寄存器(IDR)。然後通過設定配置寄存器(CRL、CRH)控制這兩個開關,于是就可以得到GPIO的上拉輸入、下拉輸入模式和浮空輸入模式,浮空就是既不接上拉也不接下拉。在上拉/下拉/浮空輸入模式中,輸出緩沖器被禁止(P-MOS和N-MOS),施密特觸發器輸入被激活,根據輸入配置(上拉,下拉或浮動)的不同,弱上拉和下拉電阻被連接配接,讀輸入資料寄存器的值可得到I/O狀态。

小結:

  1. 上拉輸入:接入上拉電阻,與電源接通,是以預設狀态下讀到的GPIO引腳電平為高電平,即為1
  2. 下拉輸入:接入下拉電阻,與地接通,是以預設狀态下讀到的GPIO引腳電平為低電平,即為0
  3. 浮空輸入:既不接上拉也不接下拉,是以輸入的是高電平就是高電平,低電平就是低電平
  4. 在輸入模式下可以通過ODR寄存器相對應的位來确定具體是上拉還是下拉,0是下拉,1是上拉。

2、一張圖記住模拟輸入:

STM32F103 GPIO口的配置和應用詳解

原理分析:圖中箭頭表示信号流動方向。可以看出模拟輸入模式關閉了施密特觸發器,也不接上、下拉電阻,經由另一線路把電壓信号傳送到片上外設子產品。如傳送給 ADC 模數轉換子產品,由ADC 采集電壓信号。是以使用 ADC外設時,必須設定為模拟輸入模式。在此模式中,輸出緩沖器被禁止,禁止施密特觸發輸入,實作了每個模拟I/O引腳上的零消耗,施密特觸發輸出值被強制置為0,弱上拉和下拉電阻被禁止,讀取輸入資料寄存器時數值為0。

小結:模拟輸入模式把圖中的紅色字型部分都禁止了。注意:GPIO在輸入模式下是不需要設定端口的最大輸出速度的。

四種輸出模式:

1、一張圖記住開漏和推挽輸出模式:

STM32F103 GPIO口的配置和應用詳解

原理分析:

開漏輸出:圖中箭頭表示信号流動方向。如果往輸出資料寄存器寫入0,因為N-MOS是接地的,低電平信号會激活N-MOS,是以輸出的IO口引腳為低電平。但是反過來是不成立的(另一個模式才可以),你肯定會想,如果寫入1,P-MOS接電源,是以輸出1,不是這樣的。開漏輸出模式P-MOS從不被激活,是以開漏模式隻可以輸出強低電平,高電平得靠外部電阻拉高,要得到高電平狀态需要上拉電阻才行。

推挽輸出:輸出資料寄存器上的0激活N-MOS,I/O口輸出低電平;而輸出資料寄存器上的1将激活P-MOS,I/O口輸出高電平。兩個管子輪流導通,一個負責灌電流,一個負責拉電流,使其負載能力和開關速度都比普通方式有很大提高。

小結:開漏就是推挽的二分之一。開漏模式隻可以輸出強低電平。

2、一張圖記住開漏複用和推挽複用輸出:

STM32F103 GPIO口的配置和應用詳解

當I/O端口被配置為複用功能時,其他配置跟開漏和推挽一樣的,隻不過開漏和推挽是由CPU來寫,而複用就是外設來寫0和1。至于選擇複用開漏輸出還是複用推挽輸出,是根據 GPIO 複用功能來選擇的,如 GPIO 的引腳用作序列槽輸出,則使用複用推挽輸出模式;如用在I2C、SMBUS 等這些需要“線與”功能的複用場合,就使用複用開漏模式。

小結:複用是外設來寫0和1。

GPIO相關寄存器配置

每一組IO口都有以下7個寄存器

- GPIOx_CRL:端口配置低寄存器(32位)
 - GPIOx_CRH:端口配置高寄存器(32位)
 - GPIOx_IDR:端口輸入寄存器(32位)
 - GPIOx_ODR:端口輸出寄存器(32位)
 - GPIOx_BSRR:端口位設定/清除寄存器(32位)
 - GPIOx_BRR:端口位清除寄存器(16位)
 - GPIOx_LCKR:端口配置鎖存寄存器(32位)不常用
           

1、CRL和CRH寄存器

這兩個32位寄存器是選擇輸入輸出模式的時候起作用的,每4個位控制一個IO口,一組IO口有16個,是以一共需要64位,CRL管理(0~7)的IO口,CRH管理(8 ~15)的IO口。相應的值在MDK中通過一個枚舉類型定義,隻需要選擇對應得值即可。

typedef enum
{ GPIO_Mode_AIN = 0x0,
  GPIO_Mode_IN_FLOATING = 0x04,
  GPIO_Mode_IPD = 0x28,
  GPIO_Mode_IPU = 0x48,
  GPIO_Mode_Out_OD = 0x14,
  GPIO_Mode_Out_PP = 0x10,
  GPIO_Mode_AF_OD = 0x1C,
  GPIO_Mode_AF_PP = 0x18
}GPIOMode_TypeDef;
           

2、ODR和IDR寄存器

STM32F103 GPIO口的配置和應用詳解

ODR寄存器隻用到了前面的16位。作用是控制GPIOx(x=A ~ G)的輸出,即設定某個IO口輸出低電平還是高電平,隻有在輸出模式下有效。

在固件庫中設定ODR寄存器來控制IO口的輸出狀态是通過這兩個函數來實作的:
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);//讀取一組
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);//讀取幾個

uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//讀取一組
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);//讀取幾個
兩個函數功能類似,差別是,前面的函數用來一次讀取一組I/O口所有I/O口輸出狀态
後面的函數用來一次讀取一組I/O口中一個或者幾個I/O口的輸出狀态。
           
STM32F103 GPIO口的配置和應用詳解

IDR寄存器也隻用到了前面的16位。該寄存器用于讀取GPIOx的輸入,讀取的某個I/O電平,如果對應的位為0(IDRy=0),則說明該腳輸入為低電平;如果是1(IDRy=1),則表示輸入的是高電平。用于寄存器設定的相關庫函數為:

前面的函數用來讀取一組I/O口的一個或者幾個I/O口輸入電平,後面的函數用來一次讀取一組I/O口中所有I/O口的輸入電平。
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef*GPIOx,uint16_t GPIO_Pin);//讀取一組
uint16_t GPIO_ReadInputData(GPIO_TypeDef*GPIOx);//讀取幾個
比如要讀取GPIOF.3的輸入電平,方法為:GPIO_ReadInputDataBit(GPIOF,GPIO_Pin_3)。
           

3、端口位 設定/清除寄存器(GPIOx_BSRR)

STM32F103 GPIO口的配置和應用詳解

該寄存器用來置位或複位I/O口,它和ODR寄存器具有類似的作用,都可以用來設定GPIO端口的輸出位是1還是0。如果同時設定了BSy和BRy的對應位,BSy位起作用。其中,對于低16位(0 ~ 15),在相應位ODRy寫1,對應的I/O口會輸出高電平,寫0,則對I/O口沒有任何影響。高16位(16~31)作用剛好相反,對相應的位ODRy寫1會輸出低電平,寫0沒有任何影響。即對于BSRR寄存器,寫0對I/O口電平是沒有任何影響的。要設定某個I/O口電平,隻需要設定相關位為1即可。而ODR寄存器要設定某個I/O口電平,首先需要讀出來ODR寄存器的值,然後對整個ODR寄存器重新指派來達到設定某個或某些I/O口的目的,而BSRR寄存器,就不需先讀,而是直接設定。BSRR 寄存器使用方法如下:

GPIOA->BSRR=1<1;//設定GPIOA.1為高電平
GPIOA->BSRR=1<(16+1);//設定GPIOA.1為低電平
           

操作BSRR寄存器來設定I/O電平的庫函數為:

//設定一組I/0口中的一個或者多個I/0口為高電平.
void GPIO_SetBits(GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin);
           

4、端口位清除寄存器(GPIOx_BRR)

STM32F103 GPIO口的配置和應用詳解

寄存器用來置位或複位I/O口,即設定GPIO端口輸出低電平。對于低16位(0~15),在相應位ODRy寫1,對應的I/O口會輸出低電平,寫0則對I/O口沒有任何影響。BRR 寄存器使用方法如下:

GPIOA->BRR=0×0001;//設定GPIOA.0為低電平
           

操作BRR寄存器來設定I/O電平的庫函數為:

//設定一組I/0口中的一個或者多個I/0口為低電平
void GPIO_ResetBits(GPIO_TypeDef*GPIOx,uint16_t GPIO_Pin);
           

繼續閱讀