STM32學習筆記之GPIO口的使用

一、GPIO口簡介

1、   GPIO口輸入輸出模式

1.1 一般來說STM32的輸入輸出管腳有以下8種配置方式:

輸入

① 浮空輸入_IN_FLOATING  ——浮空輸入,可以做KEY識別

② 帶上拉輸入_IPU          ——IO內部上拉電阻輸入  

③ 帶下拉輸入_IPD              ——IO內部下拉電阻輸入

④ 模擬輸入_AIN            ——應用ADC模擬輸入,或者低功耗下省電

輸出
⑤ 開漏輸出_OUT_OD        ——IO輸出0接GND,IO輸出1,懸空,需要外接
上拉電阻,才能實現輸出高電平。當輸出爲1時,IO口的狀態由上拉電阻拉高電平,但由於是開漏輸出模式,這樣IO口也就可以由外部電路改變爲低電平或不變。可以讀IO輸入電平變化,實現C51的IO雙向功能。

⑥ 推輓輸出_OUT_PP       ——IO輸出0-接GND, IO輸出1 -接VCC,讀輸入值是未知的。

複用輸出

⑦ 複用功能的推輓輸出_AF_PP   ——片內外設功能(I2C的SCL,SDA)

⑧ 複用功能的開漏輸出_AF_OD  ——片內外設功能(TX1,MOSI,MISO,SCK,SS)

2、輸入輸出模式詳解

一般我們平時用的最多的也就是推輓輸出、開漏輸出、上拉輸入,介紹如下:

2.1推輓輸出:

QQ截圖20130509185220.jpg 


可以輸出高,低電平,連接數字器件; 推輓結構一般是指兩個三極管分別受兩互補信號的控制,總是在一個三極管導通的時候另一個截止。高低電平由IC的電源低定。

推輓電路是兩個參數相同的三極管或MOSFET,以推輓方式存在於電路中,各負責正負半周的波形放大任務,電路工作時,兩隻對稱的功率開關管每次只有一個導通,所以導通損耗小、效率高。輸出既可以向負載灌電流,也可以從負載抽取電流。推拉式輸出級既提高電路的負載能力,又提高開關速度。


2.2開漏輸出:

QQ截圖20130509185235.jpg 


輸出端相當於三極管的集電極。 要得到高電平狀態需要上拉電阻才行。 適合於做電流型的驅動,其吸收電流的能力相對強(一般20mA以內)

開漏形式的電路有以下幾個特點:

1、 利用外部電路的驅動能力,減少IC內部的驅動。當IC內部MOSFET導通時,驅動電流是從外部的VCC流經R pull-up ,MOSFET到GND。IC內部僅需很小的柵極驅動電流。

2、 一般來說,開漏是用來連接不同電平的器件,匹配電平用的,因爲開漏引腳不連接外部的上拉電阻時,只能輸出低電平,如果需要同時具備輸出高電平的功能,則需要接上拉電阻,很好的一個優點是通過改變上拉電源的電壓,便可以改變傳輸電平。比如加上上拉電阻就可以提供TTL/CMOS電平輸出等。(上拉電阻的阻值決定了邏輯電平轉換的沿的速度 。阻值越大,速度越低功耗越小,所以負載電阻的選擇要兼顧功耗和速度。)

3、 OPEN-DRAIN提供了靈活的輸出方式,但是也有其弱點,就是帶來上升沿的延時。因爲上升沿是通過外接上拉無源電阻對負載充電,所以當電阻選擇小時延時就小,但功耗大;反之延時大功耗小。所以如果對延時有要求,則建議用下降沿輸出。

4、可以將多個開漏輸出的Pin,連接到一條線上。通過一隻上拉電阻,在不增加任何器件的情況下,形成“與邏輯”關係。這也是I2C,SMBus等總線判斷總線佔用狀態的原理。


補充:什麼是“線與”?:

在一個結點(線)上, 連接一個上拉電阻到電源 VCC 或 VDD 和 n 個 NPN 或 NMOS 晶體管的集電極 C 或漏極 D, 這些晶體管的發射極 E 或源極 S 都接到地線上, 只要有一個晶體管飽和, 這個結點(線)就被拉到地線電平上。 因爲這些晶體管的基極注入電流(NPN)或柵極加上高電平(NMOS), 晶體管就會飽和, 所以這些基極或柵極對這個結點(線)的關係是或非 NOR 邏輯。 如果這個結點後面加一個反相器, 就是或 OR 邏輯。

其實可以簡單的理解爲:在所有引腳連在一起時,外接一上拉電阻,如果有一個引腳輸出爲邏輯0,相當於接地,與之並聯的迴路“相當於被一根導線短路”,所以外電路邏輯電平便爲0,只有都爲高電平時,與的結果才爲邏輯1。


關於推輓輸出和開漏輸出,最後概括一下:

無標題.png 


該圖中左邊的便是推輓輸出模式,其中比較器輸出高電平時下面的PNP三極管截止,而上面NPN三極管導通,輸出電平VS+;當比較器輸出低電平時則恰恰相反,PNP三極管導通,輸出和地相連,爲低電平。右邊的則可以理解爲開漏輸出形式,需要接上拉。


2.3浮空輸入 :對於浮空輸入,一直沒找到很權威的解釋,只好從以下圖中去理解了。


gpio.jpg 



2.4  上拉輸入/下拉輸入/模擬輸入:這幾個概念很好理解,從字面便能輕易讀懂。

2.5  複用開漏輸出、複用推輓輸出:可以理解爲GPIO口被用作第二功能時的配置情況(即並非作爲通用IO口使用)

二、GPIO口配置

1、根據具體應用配置爲輸入或輸出

① 作爲普通GPIO輸入:

根據需要配置該引腳爲浮空輸入、帶弱上拉輸入或帶弱下拉輸入,同時不要使能該引腳對應的所有複用功能模塊。

② 作爲普通GPIO輸出:

根據需要配置該引腳爲推輓輸出或開漏輸出,同時不要使能該引腳對應的所有複用功能模塊。

③ 作爲普通模擬輸入:

配置該引腳爲模擬輸入模式,同時不要使能該引腳對應的所有複用功能模塊。

④ 作爲內置外設的輸入:

根據需要配置該引腳爲浮空輸入、帶弱上拉輸入或帶弱下拉輸入,同時使能該引腳對應的某個複用功能模塊。

⑤ 作爲內置外設的輸出:

根據需要配置該引腳爲複用推輓輸出或複用開漏輸出,同時使能該引腳對應的所有複用功能模塊。


2、輸出模式下,配置速度

I/O口輸出模式下,有3種輸出速度可選(2MHz、10MHz和50MHz),這個速度是指I/O口驅動電路的響應速度而不是輸出信號的速度,輸出信號的速度與程序有關(芯片內部在I/O口的輸出部分安排了多個響應速度不同的輸出驅動電路,用戶可以根據自己的需要選擇合適的驅動電路)。通過選擇速度來選擇不同的輸出驅動模塊,達到最佳的噪聲控制和降低功耗的目的。高頻的驅動電路,噪聲也高,當不需要高的輸出頻率時,請選用低頻驅動電路,這樣非常有利於提高系統的EMI性能。當然如果要輸出較高頻率的信號,但卻選用了較低頻率的驅動模塊,很可能會得到失真的輸出信號。關鍵是GPIO的引腳速度跟應用匹配。

2.1     對於串口,假如最大波特率只需115.2k,那麼用2M的GPIO的引腳速就夠

了,既省電也噪聲小。

2.2    對於I2C接口,假如使用400k波特率,若想把餘量留大些,那麼用2M的

GPIO的引腳速度或許不夠,這時可以選用10M的GPIO引腳速度。

2.3    對於SPI接口,假如使用18M或9M波特率,用10M的GPIO的引腳速度顯然不夠了,需要選用50M的GPIO的引腳速度。

3、GPIO口初始化

①使能GPIO口的時鐘 ②配置模式設置(8種模式)

    STM32的GPIO的時鐘統一掛接在APB2上,具體的使能寄存器爲RCC_APB2ENR該寄存器的第2位到第8位分別控制GPIOx(x=A,B,C,D,E,F,G)端口的時鐘使能。

如打開PORTA時鐘  RCC->APB2ENR|=1<<2;    //使能PORTA時鐘

如果把端口配置成複用輸出功能,則還需開始複用端口時鐘,並進行相應配置。  


4、GPIO配置寄存器

GPIO口配置是通過配置寄存器來進行的,每個GPIO 端口有:

兩個32位配置寄存器(GPIOx_CRL,GPIOx_CRH)分別控制每個端口的高八位和低八位。如果IO口是0-7號的話,則寫CRL寄存器;如果IO口是8-15號的話,則寫CRH寄存器。

兩個32位數據寄存器(GPIOx_IDR,GPIOx_ODR)一個是隻讀作輸入數據寄存器,一個是隻寫作輸出寄存器。

一個32位置位/復位寄存器(GPIOx_BSRR)。

一個16位復位寄存器(GPIOx_BRR)。

一個32位鎖定寄存器(GPIOx_LCKR)。

常用的IO端口寄存器只有四個:CRH,CRL,IDR,ODR。

數據手冊中列出的每個I/O端口的特定硬件特徵。 GPIO端口的每個位可以由軟件分別配置成多種模式。每個I/O端口位可以自由編程,然而I/0端口寄存器必須按32位字被訪問(不允許半字或字節訪問)。 另外,STM32的每個端口使用前都要將其時鐘使能,STM32的GPIO的時鐘統一掛接在APB2上,具體的使能寄存器爲RCC_APB2ENR,該寄存器的第2位到第8位分別控制GPIOx(x=A,B,C,D,E,F,G)端口的時鐘使能,當外設時鐘沒有啓用時,程序不能讀出外設寄存器的數值,如打開PORTA時鐘:  RCC->APB2ENR|=1<<2;    //使能PORTA時鐘


總結一下GPIO功能:

1、通用I/O(GPIO):最基本的功能,可以驅動LED、可以產生PWM、可以驅動蜂鳴器等等;

2、單獨的位設置或位清除:方便軟體作業,程序簡單。端口配置好以後只需GPIO_SetBits(GPIOx, GPIO_Pin_x)就可以實現對GPIOx的pinx位爲高電平;

3、所有端口都有外部中斷能力:端口必須配置成輸入模式,所有端口都有外部中斷能力;

4、複用功能(AF):複用功能的端口兼有IO功能等。復位期間和剛復位後,複用功能未開啓,I/O 端口被配置成浮空輸入模式。

5、 軟件重新映射I/O複用功能:爲了使不同器件封裝的外設I/O 功能的數量達到最優,可以把一些複用功能重新映射到其他一些腳上。這可以通過軟件配置相應的寄存器來完成。這時,複用功能就不再映射到它們的原始引腳上了。

6、 GPIO鎖定機制:當在一個端口位上執行了所定(LOCK)程序,在下一次復位之前,將不能再更改端口位的配置。


5、GPIO寄存器詳解

參見《STM32F10X中文手冊》

GPIO基本設置

GPIOMode_TypeDefGPIO mode    定義及偏移地址

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    //推輓複用

GPIO輸入輸出速度選擇:

typedef enum

{

GPIO_Speed_10MHz =1,

GPIO_Speed_2MHz,

GPIO_Speed_50MHz

}

GPIOSpeed_TypeDef;

#defineIS_GPIO_SPEED(SPEED) ((SPEED == GPIO_Speed_10MHz) ||

(SPEED ==GPIO_Speed_2MHz) || (SPEED == GPIO_Speed_50MHz))



6、GPIO輸出的試驗

這裏利用ST固件庫,就不需要自己對照配置寄存器寫代碼,直接利用庫函數,非常方便。


main.c

  1. /*****************************************************************************
  2.   *   main.c
  3.   *   http://www.veryarm.cn
  4.   *   V1.0.0
  5.   *   04-27-2013
  6.   *
  7.   *   http://veryarm.taobao.com
  8. ******************************************************************************
  9.   *
  10.   *
  11.   *
  12. *****************************************************************************/

  13. /* Includes ------------------------------------------------------------------*/
  14. #include "stm32f10x.h"
  15. #include "led.h"

  16. /* Private define------------------------------------------------------------*/

  17. /* Declare Private functions-------------------------------------------------*/                                       
  18. void Delay(u32 d_time);

  19. /* Main functions------------------------------------------------------------*/                                                                       
  20. int main(void)
  21. {
  22.          LED_Init();        
  23.          while(1)
  24.          {
  25.                   GPIO_SetBits(GPIOF,GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9);
  26.                   Delay(3000000);
  27.                   GPIO_ResetBits(GPIOF,GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9);
  28.                   Delay(3000000);
  29.          }
  30. }

  31. /* Define Private functions-------------------------------------------------*/
  32. void Delay(u32 d_time)
  33. {
  34.          for(;d_time>0;d_time--);
  35. }

  36. /************************ (C) COPYRIGHTwww.veryarm.cn *********END OF FILE****/
複製代碼
led.h
  1. #ifndef __LED_H
  2. #define __LED_H  
  3. #include"sys.h"

  4. void  LED_Init(void);
  5.                                                        
  6. #endif
複製代碼
led.c
  1. #include"led.h"
  2.            
  3. //LED IO初始化
  4. void LED_Init(void)
  5. {
  6.        GPIO_InitTypeDef GPIO_InitStructure;
  7.        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF,ENABLE);
  8.       
  9.        GPIO_InitStructure.GPIO_Pin =GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;
  10.        GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP;
  11.        GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;
  12.        GPIO_Init(GPIOF, &GPIO_InitStructure);
  13.        GPIO_ResetBits(GPIOF,GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9);
  14. }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章