STM32之GPIO底層原理與編程實踐

1、什麼是GPIO

  GPIO全稱爲General Purpose Input Output,中文理解爲通用輸入輸出端口。它指的是編程可控制的引腳,便可以控制引腳是做爲輸入來用,仍是輸出功能,又或者是交給片上外設使用(複用)。編程

 

2、GPIO結構框圖

  理解GPIO硬件電路的實現,有助於編程的理解。下圖是官方手冊給出的GPIO框圖:ui

 

  此框圖中只有最右端的I/O pin是板上外露可見的,其餘部分均在芯片內部。該框圖結構被分爲兩個部分,其一是輸出結構,主要由引腳(I/O pin)、保護二極管(protection diode)、雙MOS管(P-MOS+N-MOS)、輸出控制(output control)、輸出數據寄存器(output data register)、位置位/復位寄存器(bit set/reset register)組成 ;其二是輸入結構,由引腳、保護二極管、雙開關(on/off)、TTL肖特基觸發器(TTL Schmitt trigger)、輸入數據寄存器(input data register)組成。spa

  1.保護二極管

    兩個二極管構成了雙向限幅電路。當外部輸入電壓大於VDD時,上方二極管導通(全文皆忽略二極管和MOS管導通壓降),使得電壓限制在VDD左右;當外部輸入電壓低於VSS,下方二極管導通,電壓限制在VSS左右。然而這樣的保護並不能使引腳直接驅動大功率器件,例如電機,就須要外加驅動電路。3d

  2.雙開關

    這個雙開關電路與上拉、下拉和浮空模式有關,當處於上拉模式時上方開關閉合,下方斷開,除非引腳的外部輸入爲低電平,不然輸入到肖特基觸發器的電平都是高電平;當處於下拉模式時上方開關斷開,下方閉合,除非引腳的外部輸入爲高電平,不然輸入到肖特基觸發器的電平都是低電平;當處於浮空模式時開關所有斷開,電平默認爲高阻態,輸入的電平徹底取決於外部輸入。上下拉多用於按鍵檢測,而浮空則經常使用於ADC檢測。code

  3.肖特基觸發器

    該觸發器主要是將模擬電壓轉爲0/1數字信號,上圖中模擬輸入(Analog input)就取自觸發器以前,而輸入數據寄存器則取自觸發器以後的數字信號。blog

  4.輸入數據寄存器

    這個寄存器用來存儲各個引腳電平狀態,可經過讀取該寄存器內容,來獲取任意引腳狀態。input

  5.位置位/復位寄存器

    經過讀寫該寄存器,能夠間接地更改輸出數據寄存器的值。it

  6.輸出數據寄存器

    能夠直接讀寫該寄存器,來更改各個引腳的輸出狀態,當寄存器值保持不變時,每一個引腳的電平也就不發生變化。io

  7.雙MOS管

    雙MOS管組成一個推輓輸出(push-pull)電路,當輸出寄存器中值爲1時,通過反相器,兩管的共柵極輸入低電平,則PMOS導通,NMOS截止,引腳輸出高電平;當輸出寄存器中值爲0時,通過反相器,兩管的共柵極輸入高電平,則NMOS導通,PMOS截止,引腳輸出低電平。當PMOS被禁用時,電路變爲開漏輸出,引腳仍可輸出低電平,但沒法正常輸出高電平,取而代之的是高阻態。若是此時想要輸出高電平,則必須接上拉電阻。開漏輸出僅在一些特殊場合下使用,更多的是推輓輸出。class

 

3、GPIO寄存器

  1.APB2外設時鐘使能寄存器(RCC_APB2ENR)

    RCC_APB2ENR並不屬於GPIO的寄存器組,可是它控制着GPIO的引腳時鐘使能,芯片上電後,全部外設時鐘默認是關閉的,因此在使用GPIO前要先打開端口時鐘使能。該寄存器內容以下,咱們只關心IOPxEN位,置1則開啓時鐘。

    

       

 

  2.端口配置低位寄存器(GPIOx_CRL)

    該寄存器可配置低8個GPIO引腳的工做模式:模擬輸入、浮空輸入、上拉\下拉輸入、通用推輓輸出、通用開漏輸出、複用推輓輸出、複用開漏輸出。複用輸入模式沒有單獨的配置,只要將引腳配置爲浮空/上拉/下拉輸入模式,由片上外設驅動便可。CRL還能夠在輸出模式下配置工做頻率,頻率越大,功耗越高。注意每一個引腳模式配置佔4bit。對於上拉\下拉輸入來講,是上拉仍是下拉取決於ODR寄存器配置的值。

    

 

  3.端口配置高位寄存器(GPIOx_CRH)

    該寄存器同GPIOx_CRL,只是它控制的是高8個GPIO引腳的工做模式。

    

 

  4.輸入數據寄存器(GPIOx_IDR)

    該寄存器存儲了當前引腳的狀態,不管GPIO在哪一種工做模式下,均可以讀取該寄存器,但在模擬輸入模式下,寄存器的值一直爲0。

    

 

     

  5.輸出數據寄存器(GPIOx_ODR)

    在通用輸出模式下,該寄存器可用來控制電平高低;在複用推輓輸出模式下,可讀取ODR獲取引腳狀態(在複用開漏輸出模式下,可讀取IDR獲取引腳狀態)。在上拉或下拉輸入模式下,ODR可決定是上拉仍是下拉。

    

 

 

   

  6.位置位/復位寄存器(GPIOx_BSRR)

    經過該寄存器,能夠單獨控制某個引腳的電平變化。由於向這個寄存器寫0的結果是無操做,寫1是置位或者復位,因此訪問該寄存器能夠直接用=號;而ODR寄存器寫0則表示給低電平,寫1表示給高電平,爲了避免影響其餘引腳,寫入必須用&=和|=號。另外還有個寄存器叫GPIOx_BRR,同該寄存器差很少,只不過BRR只能復位,高16位是保留的。

    

 

 

 

4、GPIO編程

  GPIO最經常使用的就是通用推輓輸出和上拉/下拉輸入這兩種模式。一下程序實現功能爲:

    PA0爲按鍵輸入,按下爲低電平。PC13是led控制引腳,低電平點亮LED。當按下按鍵時,LED亮;鬆開按鍵時,LED滅。

  程序代碼以下,根據GPIO原理,編程順序通常是:先開啓時鐘使能,配置引腳工做模式,最後給引腳電平信號。

  

int main(void)
{
    
    uint32_t key_value;
    
    //開啓GPIO外設時鐘使能
    //PORTA,第三位置1
    RCC->APB2ENR |= (1<<2);
    //PORTC,第五位置1
    RCC->APB2ENR |= (1<<4);
    
    //GPIO輸入輸出模式配置
    //清零PA0控制位
    GPIOA->CRL &= ~((uint32_t)(0x0F)<<(4*0));
    //設置PA0爲上拉輸入
    GPIOA->CRL |=  (uint32_t)(0x08)<<(4*0);
    GPIOA->ODR |=  (uint32_t)(0x01)<<0;    
    //清零PC13控制位
    GPIOC->CRH &= ~((uint32_t)(0x0F)<<(4*5));
    //設置PC13爲推免輸出
    GPIOC->CRH |=  (uint32_t)(0x01)<<(4*5);
    
    
    while(1){
            //獲取PA0電平狀態,key_value==1表示按鍵沒有按下
            key_value = (GPIOA->IDR & (uint32_t)(0x01)) == (uint32_t)(0x01);
            //改變PC13電平
            if (key_value==0)
                //PC13低電平輸出
                GPIOC->ODR &= ~((uint32_t)(0x01)<<13);                
            else
                //PC13高電平輸出
                GPIOC->ODR |= (uint32_t)(0x01)<<13;
    }
}
相關文章
相關標籤/搜索