STM32開發--GPIO詳解


 一.GPIO的寄存器
32位配置寄存器:GPIOx_CRL,GPIOx_CRH
32位數據寄存器:GPIOx_IDR,GPIOx_ODR
32位置位/復位寄存器:GPIOx_BSRR
16位復位寄存器:GPIOx_BRR
32位鎖定寄存器:GPIOx_LCKR
 

 

 

 

 

GPIOx_CRL :端口配置低寄存器 (控制P0--P7端口)

一個IO位占4個位(4*8=32)P0--P7剛好32位,例如:P0端口:0-1控制輸入模式或者輸出模式及輸出速度,2-3控制輸入模式或者輸出模式的具體工作方式

 

GPIOx_CRH:端口配置高寄存器 (控制P8--P15端口)

一個IO位占4個位(4*8=32)P8--P15剛好32位,例如:P8端口:0-1控制輸入模式或者輸出模式及輸出速度,2-3控制輸入模式或者輸出模式的具體工作方式

GPIOx_IDR:端口輸入寄存器 

一個位控制一個IO口,0--15對應P0--P15

(注意:IDR寄存器低16位,每個位控制該組IO的一個IO口。對應的是IO口的輸入電平)

 

GPIOx_ODR:端口輸出寄存器

一個位控制一個IO口,0--15對應P0--P15

(注意:ODR寄存器跟IDR寄存器相反,是控制IO口輸出。低16位每個位控制一個IO口的輸出電平的高低。)

輸入模式的上下拉輸入到底是上拉還是下拉由端口輸出寄存器ODR決定。在輸入模式時,可設置ODR寄存器的第一位來決定上拉還是下拉

 

GPIOx_BSRR:端口位設置/清除寄存器

低16位(0--15)是置位,當對應位為1時對應端口置1,對應位為0時對應端口置不受影響

高16位(16--31)是復位,當對應位為1時對應端口置0,對應位為0時對應端口置不受影響

高低位同時作用時,則只有低16位起作用!

GPIOx_BRR :端口位清除寄存器

低16位對應16個端口,作用和GPIOx_BSRR的高16位一樣,都是復位清除功能

低16位(0--15)是復位,當對應位為1時對應端口置0,對應位為0時對應端口置不受影響

 

 

 GPIOx_LCKR:端口配置鎖存寄存器

 
 
 
 
二.GPIO的工作模式
 
根據數據手冊中列出的每個I/O端口的特定硬件特征, GPIO端口的每個位可以由軟件分別配置成多種模式。

4種輸入模式: 輸入浮空     

                        輸入上拉         

                        輸入下拉       

                        模擬輸入

4種輸出模式: 開漏輸出   

                        開漏復用功能   

                        推挽式輸出   

                        推挽式復用功能

 

1.浮空輸入GPIO_IN_FLOATING ——浮空輸入,可以做按鍵識別,IO狀態不確定,完全由外部輸入決定
施密特觸發器是開啟的,IO口的狀態可以直接送到輸入寄存器中,CPU可以直接讀取輸入寄存器。
電平進入后,不經過上下拉,在觸發施密特觸發器后,進入輸入數據寄存器,最后由CPU讀取。
浮空輸入狀態下,IO的電平狀態是不確定的,完全由外部輸入決定(輸入達到條件就觸發),如果在該引腳懸空的情況下,讀取該端口的電平是不確定的。
       
 
2.輸入上拉GPIO_IPU——IO內部上拉電阻輸入
 與前面浮空輸入模式相比,僅僅在數據通道的上部,接入一個上拉電阻,根據STM32的數據手冊,這個上拉電阻阻值介於30K~50K。同樣的,CPU可以隨時在輸入數據寄存器的另一端,讀取IO端口的電平狀態。
原本需要低電平觸發,有上拉電阻存在,使得端口為高電平,達到抗干擾作用,只接受低電平!
         
 
3.輸入下拉GPIO_IPD—— IO內部下拉電阻輸入
 與前面浮空輸入模式相比,僅僅在數據通道的上部,接入一個下拉電阻,根據STM32的數據手冊,這個下拉電阻阻值介於30K~50K。同樣的,CPU可以隨時在輸入數據寄存器的另一端,讀取IO端口的電平狀態。
原本需要高電平觸發,有下拉電阻存在,使得端口為低電平,達到抗干擾作用,只接受高電平!
         
 
4.模擬輸入GPIO_AIN ——應用ADC模擬輸入,或者低功耗下省電
施密特觸發器是關閉的,信號直接到ADC輸入;這里我們能看到所有的上拉、下拉電阻和施密特觸發器,均處於斷開狀態,因此輸入數據寄存器將不能反映端口上的電平狀態,也就是說模擬輸入模式下CPU不能在數據寄存器上讀到有效的數據
         

 

 

 

1.開漏輸出GPIO_OUT_OD ----開漏模式時,只有 N-MOS 管工作,輸出數 據 寄 存 器 可 控 制 I/O 輸 出 高 阻 態 或 低 電 平 。
      當CPU在編號1端通過“位設置/清楚寄存器”或“輸出數據寄存器”寫入數據后,該數據位通過編號2的輸出控制電路傳送到編號4的IO端口。 如果CPU寫入的是邏輯1,則編號3的N-MOS管將處於關閉狀態,此時IO端口的電平將由外部的上拉電阻決定;如果CPU寫入的是邏輯0,則編號3的N-MOS管將處於開啟狀態,此時IO端口的電平被編號3的N-MOS管拉到了VSS的零電位。
      在上圖的上半部,施密特觸發器處於開啟狀態,這意味着CPU可以在“輸入數據寄存器”的另一端,隨時監控IO端口的狀態;通過這個特性還實現了虛擬的IO端口雙向通信只要CPU輸出邏輯1,由於編號3的N-MOS管處於關閉狀態,IO端口的電平將完全由外部電路決定,因此,CPU可以在“輸入數據寄存器”讀到外部電路的信號,而不是它自己輸出的邏輯1。
       GPIO口的輸出模式下,有3種輸出速度可選:2MHz、10MHz和50MHz。這個速度是指GPIO口驅動電路的響應速度而不是輸出信號的速度,輸出信號的速度與程序有關(芯片內部在IO口的輸出部分安排了多個響應速度不同的輸出驅動電路,用戶可以根據自己的需要選擇合適的驅動電路)。通過選擇速度來選擇不同的輸出驅動模塊,達到最佳的噪聲控制和降低功耗的目的。高頻的驅動電路,噪聲也高,當不需要高的輸出頻率時,請選用低頻驅動電路,這樣非常有利於提高系統的EMI性能。當然如果要輸出較高的頻率的信號,但卻選用了較低頻率的驅動模塊,很可能會得到失真的輸出信號。
          在這里插入圖片描述
2.推挽式輸出GPIO_OUT_PP ——IO輸出0-接GND, IO輸出1 -接VCC,讀輸入值是未知的
在輸出模式中,推挽模式時雙 MOS 管以推挽方式工作,輸出數據寄存器GPIOx_ODR 可控制 I/O 輸出高低電平。
 
3.推挽式復用功能GPIO_AF_PP ——片內外設功能(I2C的SCL,SDA)
復用功能模式中,輸出使能,輸出速度可配置,可工作在推挽模式,但是輸出信號源於其它外設,輸出數據寄存器 GPIOx_ODR 無效;輸入可用,通過輸入數據寄存器可獲取 I/O 實際狀態,但一 般直接用外設的寄存器來獲取該 數據信號。 

 

 

4.開漏復用功能GPIO_AF_OD——片內外設功能(TX1,MOSI,MISO.SCK.SS)

復用功能模式中,輸出使能,輸出速度可配置,可工作在開漏模式, 但是輸出信號源於其它外設,輸出數據寄存器 GPIOx_ODR 無效;輸入可用,通 過輸入數據寄存器可獲取 I/O 實際狀態,但 般直接用外設的寄存器來獲取該 數據信號。 

 

GPIO整理后可分為三類:

1. 輸入模式(模擬/浮空/上拉/下拉):在輸入模式時,施密特觸發器打開,輸出被禁止,可通過輸入數據寄存器 GPIOx_IDR讀取 I/O 狀態。其中輸入模式,可設置為上拉、下拉、浮空和模擬輸入四種。上拉和下拉輸入很好理解,默認的電平由上拉或者下拉決定。浮空輸入的電平是不確定的,完全由外部的輸入決定,一般接按鍵的時候用的是浮空輸入。模擬輸入則用於 ADC 采集。

2. 輸出模式(推挽/開漏):在輸出模式中,推挽模式時雙 MOS 管以輪流方式工作,輸出數據寄存器GPIOx_ODR可控制 I/O 輸出高低電平。開漏模式時,只有 N-MOS 管工作,輸出數據寄存器可控制I/O輸出高阻態或低電平。輸出速度可配置,有 2MHz\10MHz\50MHz 的選項。此處的輸出速度即 I/O 支持的高低電平狀態最高切換頻率,支持的頻率越高,功耗越大,如果功耗要求不嚴格,把速度設置成最大即可。
在輸出模式時施密特觸發器是打開的,即輸入可用,通過輸入數據寄存器 GPIOx_IDR可讀取 I/O 的實際狀態。

3.復用功能(推挽/開漏):復用功能模式中,輸出使能,輸出速度可配置,可工作在開漏及推挽模式,但是輸出信號源於其它外設,輸出數據寄存器 GPIOx_ODR 無效;輸入可用,通過輸入數據寄存器可獲取 I/O 實際狀態,但一般直接用外設的寄存器來獲取該數據信號。

 

應用場合

 ①上拉輸入、下拉輸入可以用來檢測外部信號,例如按鍵等。

 ②浮空輸入模式,由於輸入阻抗較大,一般把這種模式用於標准通信協議的I2C、USART的接收端。

 ③普通推挽輸出模式一般應用在輸出電平為0和3.3V的場合<。而普通開漏輸出模式一般應用在電平不匹配的場合,如需要輸出5V的高電平,就需要在外部一個上拉電阻。電源為5V,把GPIO設置為開漏模式,當輸出高阻態時,由上拉電阻和電源向外輸出5V電平。

④對於相應的復用模式,復用輸出來源片上外設,則是根據GPIO的復用功能來選擇,如GPIO的引腳用作串口的輸出(USART/SPI/CAN),則使用復用推挽輸出模式。如果用在I2C、SMBUS這些需要線與功能的復用場合,就使用復用開漏模式

 ⑤在使用任何一種開漏模式時,都需要接上拉電阻。

 
每個I/O端口位可以自由編程,然而I/0端口寄存器必須按32位字被訪問(不允許半字或字節訪問)。GPIOx_BSRR和GPIOx_BRR寄存器允許對任何GPIO寄存器的讀/更改的獨立訪問;這樣,在讀和更改訪問之間產生IRQ時不會發生危險。下圖給出了一個I/O端口位的基本結構。
 
通常有5種方式使用某個引腳功能,它們的配置方式如下:
      1、作為普通GPIO輸入:根據需要配置該引腳為浮空輸入、帶弱上拉輸入或帶弱下拉輸入,同時不要使能該引腳對應的所有復用功能模塊。
      2、作為普通GPIO輸出:根據需要配置該引腳為推挽輸出或開漏輸出,同時不要使能該引腳對應的所有復用功能模塊。
      3、作為普通模擬輸入:配置該引腳為模擬輸入模式,同時不要使能該引腳對應的所有復用功能模塊。
      4、作為內置外設的輸入:根據需要配置該引腳為浮空輸入、帶弱上拉輸入或帶弱下拉輸入,同時使能該引腳對應的某個復用功能模塊。
      5、作為內置外設的輸出:根據需要配置該引腳為復用推挽輸出或復用開漏輸出,同時使能該引腳對應的所有復用功能模塊。
 
 
 
三.GPIO的常用函數
1.初始化函數
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);        //初始化(端口引腳,工作模式,傳輸速度)
//初始化PB5為輸出口.並使能這個端口的時鍾            
//LED IO初始化
void LED_Init(void)
{
 
 GPIO_InitTypeDef  GPIO_InitStructure;
     
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);  //使能PB端口時鍾
    
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;              //LED0-->PB.5 端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;       //推挽輸出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;      //IO口速度為50MHz
 GPIO_Init(GPIOB, &GPIO_InitStructure);                 //根據設定參數初始化GPIOB.5
 GPIO_SetBits(GPIOB,GPIO_Pin_5);                        //PB.5 輸出高

}
 

 

 
 
2.讀取輸入電平函數
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);       //讀取某個位的輸入電平(GPIOx,GPIO_Pin)
GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1);      //讀取PA1的輸入電平
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);                                         //讀取某個端口16位的輸入數據(GPIOx)
GPIO_ReadInputData(GPIOA);                    //讀取PA端口16位的輸入數據
3.讀取輸出電平函數
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);     //讀取某個位的輸出電平(GPIOx,GPIO_Pin)
GPIO_ReadOutputDataBit( GPIOA, GPIO_Pin_1);     //讀取PA1的輸出電平
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);                                        //讀取某個端口16位的輸出數據(GPIOx)
GPIO_ReadOutputData(GPIOA);                    //讀取PA端口16位的輸出數據

 

4.設置輸出電平函數
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);                               //置位(GPIOx,GPIO_Pin)
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);                           //復位(GPIOx,GPIO_Pin)
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);    //對某個位寫(GPIOx,GPIO_Pin,0或1)
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);                                       //對某個端口16位寫(GPIOx,0或1)
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM