welcom ! Handel home

2014年6月17日 星期二

ST32 M3 Whow to Woring GPIO demo code

  STM32 GPIO應用筆記 


1           STM32
的輸入輸出管腳有下面8種可能的配置:(4輸入+2輸出+2複用輸出)

浮空輸入_IN_FLOATING 

帶上拉輸入_IPU   

帶下拉輸入_IPD            

模擬輸入_AIN
開漏輸出_OUT_OD      

推挽輸出_OUT_PP 

複用功能的推挽輸出_AF_PP  

複用功能的開漏輸出_AF_OD

1.1         I/O
口的輸出模式下,有3種輸出速度可選(2MHz10MHz50MHz),這個速度是指I/O口驅動電路的回應速度而不是輸出信號的速度,輸出信號的速度與程式有關(晶片內部在I/O口的輸出部分安排了多個回應速度不同的輸出驅動電路,使用者可以根據自己的需要選擇合適的驅動電路)。通過選擇速度來選擇不同的輸出驅動模組,達到最佳的雜訊控制和降低功耗的目的。高頻的驅動電路,雜訊也高,當不需要高的輸出頻率時,請選用低頻驅動電路,這樣非常有利於提高系統的EMI性能。當然如果要輸出較高頻率的信號,但卻選用了較低頻率的驅動模組,很可能會得到失真的輸出信號。

關鍵是GPIO的引腳速度跟應用匹配(推薦10倍以上?)。比如:

1.1.1      
對於串口,假如最大串列傳輸速率只需115.2k,那麼用2MGPIO的引腳速度就夠了,既省電也雜訊小。

1.1.2      
對於I2C介面,假如使用400k串列傳輸速率,若想把餘量留大些,那麼用2MGPIO的引腳速度或許不夠,這時可以選用10MGPIO引腳速度。

1.1.3      
對於SPI介面,假如使用18M9M串列傳輸速率,用10MGPIO的引腳速度顯然不夠了,需要選用50MGPIO的引腳速度。

1.2         GPIO
口設為輸入時,輸出驅動電路與埠是斷開,所以輸出速度配置無意義。

1.3         
在復位期間和剛復位後,複用功能未開啟,I/O埠被配置成浮空輸入模式。

1.4         
所有埠都有外部中斷能力。為了使用外部中斷線,埠必須配置成輸入模式。

1.5         GPIO
口的配置具有上鎖功能,當配置好GPIO口後,可以通過程式鎖住配置組合,直到下次晶片重定才能解鎖。



2           
STM32中如何配置片內外設使用的IO

首先,一個外設經過 配置輸入的時鐘和 初始化後即被啟動(開啟)如果使用該外設的輸入輸出管腳,則需要配置相應的GPIO埠(否則該外設對應的輸入輸出管腳可以做普通GPIO管腳使用);再對外設進行詳細配置。

對應到外設的輸入輸出功能有下述三種情況:
一、外設對應的管腳為輸出:需要根據週邊電路的配置選擇對應的管腳為複用功能的推挽輸出或複用功能的開漏輸出。
二、外設對應的管腳為輸入:則根據週邊電路的配置可以選擇浮空輸入、帶上拉輸入或帶下拉輸入。
三、ADC對應的管腳:配置管腳為類比輸入。 

如果把埠配置成複用輸出功能,則引腳和輸出寄存器斷開,並和片上外設的輸出信號連接。將管腳配置成複用輸出功能後,如果外設沒有被啟動,那麼它的輸出將不確定。 



3           
通用IO埠(GPIO)初始化:

3.1            GPIO
初始化

3.1.1       RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | B | C, ENABLE)
:使能APB2匯流排外設時鐘

3.1.2       RCC_ APB2PeriphResetCmd (RCC_APB2Periph_GPIOA | B | C, DISABLE)
:釋放GPIO復位

3.2            
配置各個PIN埠(類比輸入_AIN、輸入浮空_IN_FLOATING、輸入上拉_IPU、輸入下拉_IPD、開漏輸出_OUT_OD、推挽式輸出_OUT_PP、推挽式複用輸出_AF_PP、開漏複用輸出_AF_OD

3.3            GPIO
初始化完成






下面我就在做個抛磚引玉,根據ST手冊上的內容,簡單地綜述一下GPIO的功能:
一、共有8種模式,可以通過程式設計選擇:
  1.
浮空輸入
  2.
帶上拉輸入
  3.
帶下拉輸入
  4.
模擬輸入
  5.
開漏輸出——(此模式可實現hotpower說的真雙向IO)
  6.
推挽輸出
  7.
複用功能的推挽輸出
  8.
複用功能的開漏輸出
模式7和模式8需根據具體的複用功能決定。

二、專門的寄存器(GPIOx_BSRRGPIOx_BRR)實現對GPIO口的原子操作,即回避了設置或清除I/O埠時的-修改-操作,使得設置或清除I/O埠的操作不會被中斷處理打斷而造成誤動作。

三、每個GPIO口都可以作為外部中斷的輸入,便於系統靈活設計。

四、I/O口的輸出模式下,有3種輸出速度可選(2MHz10MHz50MHz),這有利於雜訊控制。

五、所有I/O口相容CMOSTTL,多數I/O口相容5V電平。

六、大電流驅動能力:GPIO口在高低電平分別為0.4VVDD-0.4V時,可以提供或吸收8mA電流;如果把輸入輸出電平分別放寬到1.3VVDD-1.3V時,可以提供或吸收20mA電流。

七、具有獨立的喚醒I/O口。

八、很多I/O口的複用功能可以重新映射。

九、GPIO口的配置具有上鎖功能,當配置好GPIO口後,可以通過程式鎖住配置組合,直到下次晶片重定才能解鎖。此功能非常有利於在程式跑飛的情況下保護系統中其他的設備,不會因為某些I/O口的配置被改變而損壞——如一個輸入口變成輸出口並輸出電流。

STM32
第一個例子

//**********************************************************************
//
作者:YYYtech
//
時間:2007/12/14
//***********************************************************************
/***********************************************************************
main
檔,GPIO操作,完成最簡單的IO操作實驗,就是控制LED
4
LED分別對應PC6789引腳。4LED流水顯示
**************************************************************************/
#include "stm32f10x_lib.h"


GPIO_InitTypeDef GPIO_InitStructure;

void LED_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);

}

void LED_TurnOn(u8 led)
{
  
}

void Delay(vu32 nCount)
{
for(; nCount != 0; nCount--);
}

main()
{

//RCC_Configuration();
LED_Init();

while(1)
{
   GPIO_SetBits(GPIOC, GPIO_Pin_9);
   Delay(0x8ffff);
   GPIO_ResetBits(GPIOC, GPIO_Pin_9);
   Delay(0x8ffff);
   GPIO_SetBits(GPIOC, GPIO_Pin_10);
   Delay(0x8ffff);
   GPIO_ResetBits(GPIOC, GPIO_Pin_10);
   Delay(0x8ffff);
   GPIO_SetBits(GPIOC, GPIO_Pin_11);
   Delay(0x8ffff);
   GPIO_ResetBits(GPIOC, GPIO_Pin_11);
   Delay(0x8ffff);
   GPIO_SetBits(GPIOC, GPIO_Pin_12);
   Delay(0x8ffff);
   GPIO_ResetBits(GPIOC, GPIO_Pin_12);
   Delay(0x8ffff);
}
}
注意:在這裡用到了RCCGPIO的庫函數,所以必須把這兩個函數加入工程。
  
關於固件庫函數在資料夾:C:\Keil\ARM\RV31\LIB\ST\STM32F10x 
為了不在操作過程中避免改變KEIL資料夾下的庫函數,可以固件函式程式庫放到其他資料夾下,如:E:\jy\work\STM\WxlStm32\LAB\library
其中stm32f10x_lib.c檔是整個庫的一些定義,是必須要的。
加入後的工程為:

GPIO
庫函數簡單說明:
函數名稱 功能描述
GPIO_DeInit
重新初始化週邊設備GPIOx相關寄存器到它的默認復位值
GPIO_AFIODeInit
初始化交錯功能(remap, event control EXTI 配置) 寄存器
GPIO_Init
根據GPIO_初始化結構指定的元素初始化週邊設備GPIOx
GPIO_StructInit
填充GPIO_初始化結構(GPIO_InitStruct)內的元素為重定值
GPIO_ReadInputDataBit
讀指定埠引腳輸入資料
GPIO_ReadInputData
讀指定埠輸入資料
GPIO_ReadOtputDataBit
讀指定埠引腳輸出資料
GPIO_ReadOtputData
讀指定埠輸出資料
GPIO_SetBits
1指定的埠引腳
GPIO_ResetBits
0指定的埠引腳
GPIO_WriteBit
設置或清除選擇的資料埠引腳
GPIO_Write
寫指定資料到GPIOx埠寄存器
GPIO_ANAPinConfig
允許或禁止 GPIO 4 類比輸入模式
GPIO_PinLockConfig
鎖定GPIO引腳寄存器
GPIO_EventOutputConfig
選擇GPIO引腳作為事件輸出
GPIO_EventOutputCmd
允許或禁止事件輸出
GPIO_PinRemapConfig
改變指定引腳的影射
GPIO_EMIConfig
允許或禁止GPIO 8 9 EMI 模式
拓展實驗:
在上面LED燈流水顯示的基礎之上加上按鍵程式,首先來看看按鍵的原理圖:

當然這個原理圖也是相當之簡單的,不用讀解釋了,唯一注意的是OK鍵與其他三個鍵的區別是按下為高電平,其餘三個按下為低電平。
加入後的完整清單如下:
//**********************************************************************
//
作者:JingYong
//
時間:2008/4/24
//***********************************************************************
/***********************************************************************
GPIO
操作,完成最簡單的IO操作實驗,用按鍵控制LED燈閃爍
**************************************************************************/
#include "stm32f10x_lib.h"

GPIO_InitTypeDef GPIO_InitStructure;
//
鍵盤定義
#define    KEY_OK     GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) 
#define    KEY_DOWN    GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1)
#define    KEY_UP     GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_2)
#define    KEY_ESC    GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_3)
//LED
初始化
void LED_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
//
按鍵初始化
void KEY_Init (void)
{
    GPIO_InitTypeDef gpio_init;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    gpio_init.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
    gpio_init.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &gpio_init);
}
//
延遲函數
void Delay(vu32 nCount)
{
for(; nCount != 0; nCount--);
}
//
主函數
main()
{
//RCC_Configuration();
LED_Init();
KEY_Init ();

while(1)
{
   if(!KEY_ESC)
   {
    while(!KEY_ESC) ;
    GPIO_SetBits(GPIOC, GPIO_Pin_9);
    Delay(0x8ffff);
    GPIO_ResetBits(GPIOC, GPIO_Pin_9);
    Delay(0x8ffff);
   }
   else if(!KEY_UP)
   {
    while(!KEY_UP) ;
    GPIO_SetBits(GPIOC, GPIO_Pin_10);
    Delay(0x8ffff);
    GPIO_ResetBits(GPIOC, GPIO_Pin_10);
    Delay(0x8ffff);
   }
   else if(!KEY_DOWN)
   {
    while(!KEY_DOWN) ;
    GPIO_SetBits(GPIOC, GPIO_Pin_11);
    Delay(0x8ffff);
    GPIO_ResetBits(GPIOC, GPIO_Pin_11);
    Delay(0x8ffff);
   }
   else if(KEY_OK)
   {
    while(KEY_OK) ;
    GPIO_SetBits(GPIOC, GPIO_Pin_12);
    Delay(0x8ffff);
    GPIO_ResetBits(GPIOC, GPIO_Pin_12);
    Delay(0x8ffff);
   }
}
}
該例子是按下不同的按鍵,閃爍對應的LED燈。
                                              STM32
GPIO口的輸出:開漏輸出和推挽輸出 收藏 
推挽輸出與開漏輸出的區別:

>>
推挽輸出:可以輸出高,低電平,連接數位器件

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

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////         
三極管的開漏輸出有什麼特性,和推挽是不是一回事,
問題:
   
很多晶片的供電電壓不一樣,有3.3v5.0v,需要把幾種IC的不同口連接在一起,是不是直接連接就可以了?實際上系統是應用在I2C上面。
簡答:
1
、部分3.3V器件有5V相容性,可以利用這種容性直接連接
2
、應用電壓轉換器件,如TPS76733就是5V輸入,轉換成3.3V1A輸出。
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

開漏電路特點及應用

   
在電路設計時我們常常遇到開漏(open drain)和開集(open collector)的概念。所謂開漏電路概念中提到的就是指MOSFET的漏極。同理,開集電路中的就是指三極管的集電極。開漏電路就是指以MOSFET的漏極為輸出的電路。一般的用法是會在漏極外部的電路添加上拉電阻。完整的開漏電路應該由開漏器件和開漏上拉電阻組成。

組成開漏形式的電路有以下幾個特點:
1.
利用 外部電路的驅動能力,減少IC內部的驅動。當IC內部MOSFET導通時,驅動電流是從外部的VCC流經R pull-up MOSFETGNDIC內部僅需很下的柵極驅動電流。如圖1
2.
可以將多個開漏輸出的Pin,連接到一條線上。形成與邏輯關係。如圖1,當PIN_APIN_BPIN_C任意一個變低後,開漏線上的邏輯就為0了。這也是I2CSMBus等匯流排判斷匯流排佔用狀態的原理。
3.
可以利用改變上拉電源的電壓,改變傳輸電平。如圖2, IC的邏輯電平由電源Vcc1決定,而輸出高電平則由Vcc2決定。這樣我們就可以用低電平邏輯控制輸出高電平邏輯了。
4.
開漏Pin不連接外部的上拉電阻,則只能輸出低電平(因此對於經典的51單片機的P0口而言,要想做輸入輸出功能必須加外部上拉電阻,否則無法輸出高電平邏輯)
5.
標準的開漏腳一般只有輸出的能力。添加其它的判斷電路,才能具備雙向輸入、輸出的能力。

應用中需注意:
1.   
開漏和開集的原理類似,在許多應用中我們利用開集電路代替開漏電路。例如,某輸入Pin要求由開漏電路驅動。則我們常見的驅動方式是利用一個三極管組成開集電路來驅動它,即方便又節省成本。如圖3
2.
上拉電阻R pull-up 阻值 決定了 邏輯電平轉換的沿的速度 。阻值越大,速度越低功耗越小。反之亦然。

   Push-Pull
輸出就是一般所說的推挽輸出,在CMOS電路裡面應該較CMOS輸出更合適,應為在CMOS裡面的pushpull輸出能力不可能做得雙極那麼大。輸出能力看IC內部輸出極NP管的面積。和開漏輸出相比,pushpull的高低電平由IC的電源低定,不能簡單的做邏輯操作等。 pushpull是現在CMOS電路裡面用得最多的輸出級設計方式。
at91rm9200 GPIO
類比I2C介面時注意!!

.什麼是OCOD

集電極開路門(集電極開路 OC 或源極開路OD)
open-drain
是漏極開路輸出的意思,相當於集電極開路(open-collector)輸出,即ttl中的集電極開路(oc)輸出。一般用於線或、線與,也有的用於電流驅動。
open-drain
是對mos管而言,open-collector是對雙極型管而言,在用法上沒啥區別。
開漏形式的電路有以下幾個特點:
1.
利用外部電路的驅動能力,減少IC內部的驅動。 或驅動比晶片電源電壓高的負載.
2.
可以將多個開漏輸出的Pin,連接到一條線上。通過一隻上拉電阻,在不增加任何器件的情況下,形成與邏輯關係。這也是I2CSMBus等匯流排判斷匯流排佔用狀態的原理。如果作為圖騰輸出必須接上拉電阻。接容性負載時,下降延是晶片內的電晶體,是有源驅動,速度較快;上升延是無源的外接電阻,速度慢。如果要求速度高電阻選擇要小,功耗會大。所以負載電阻的選擇要兼顧功耗和速度。
3.
可以利用改變上拉電源的電壓,改變傳輸電平。例如加上上拉電阻就可以提供TTL/CMOS電平輸出等。
4.
開漏Pin不連接外部的上拉電阻,則只能輸出低電平。一般來說,開漏是用來連接不同電平的器件,匹配電平用的。
5.
正常的CMOS輸出級是上、下兩個管子,把上面的管子去掉就是OPEN-DRAIN了。這種輸出的主要目的有兩個:電平轉換和線與。

6.
由於漏級開路,所以後級電路必須接一上拉電阻,上拉電阻的電源電壓就可以決定輸出電平。這樣你就可以進行任意電平的轉換了。
7.
線與功能主要用於有多個電路對同一信號進行拉低操作的場合,如果本電路不想拉低,就輸出高電平,因為OPEN-DRAIN上面的管子被拿掉,高電平是靠外接的上拉電阻實現的。(而正常的CMOS輸出級,如果出現一個輸出為高另外一個為低時,等於電源短路。)

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

.什麼是線或邏輯與線與邏輯?

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

注:個人理解:線與,接上拉電阻至電源。(~A)&(~B)=~(A+B),由公式較容易理解線與此概念的由來

如果用下拉電阻和 PNP PMOS 管就可以構成與非 NAND 邏輯, 或用負邏輯關係轉換與/或邏輯.

注:線或,接下拉電阻至地。(~A)+(~B)=~(AB);
這些電晶體常常是一些邏輯電路的集電極開路 OC 或源極開路 OD 輸出端. 這種邏輯通常稱為線與/線或邏輯, 當你看到一些晶片的 OC OD 輸出端連在一起, 而有一個上拉電阻時, 這就是線或/線與了, 但有時上拉電阻做在晶片的輸入端內.
順便提示如果不是 OC OD 晶片的輸出端是不可以連在一起的, 匯流排 BUS 上的雙向輸出端連在一起是有管理的, 同時只能有一個作輸出, 而其他是高阻態只能輸入.

.什麼是推挽結構
一般是指兩個三極管分別受兩互補信號的控制,總是在一個三極管導通的時候另一個截止.要實現線與需要用OC(open collector)門電路 .如果輸出級的有兩個三極管,始終處於一個導通、一個截止的狀態,也就是兩個三級管推挽相連,這樣的電路結構稱為推拉式電路或圖騰柱(Totem- pole)輸出電路(可惜,圖無法貼上)。當輸出低電平時,也就是下級負載門輸入低電平時,輸出端的電流將是下級門灌入T4;當輸出高電平時,也就是下級負載門輸入高電平時,輸出端的電流將是下級門從本級電源經 T3D1 拉出。這樣一來,輸出高低電平時,T3 一路和 T4 一路將交替工作,從而減低了功耗,提高了每個管的承受能力。又由於不論走哪一路,管子導通電阻都很小,使RC常數很小,轉變速度很快。因此,推拉式輸出級既提高電路的負載能力,又提高開關速度。供你參考。
推挽電路是兩個參數相同的三極管或MOSFET,以推挽方式存在於電路中,各負責正負半周的波形放大任務,電路工作時,兩隻對稱的功率開關管每次只有一個導通,所以導通損耗小效率高。

輸出既可以向負載灌電流,也可以從負載抽取電流
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/feiniao_lql/archive/2010/06/13/5668585.aspx




沒有留言: