新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > LPC1114通用輸入/輸出端口(GPIO)續(xù)

LPC1114通用輸入/輸出端口(GPIO)續(xù)

作者: 時間:2016-11-13 來源:網絡 收藏
前面討論了GPIO數(shù)據寄存器和屏蔽結構的用法,這里再接著討論一下涉及到GPIO的其它寄存器用法。從GPIO定義的結構體中可以看出,除了前面討論的DATA寄存器以外,還剩余有8個寄存器,偏移地址從0x8000到0x801C,它們都在GPIO設置中起著重要的作用,下面就一一進行討論。

首先看DIR寄存器,其偏移地址為0x8000,屬性為可讀可寫,它負責GPIO引腳的方向,即引腳是用做輸入還是輸出,由該寄存器的設置來決定。雖然DIR寄存器也是32位結構,但由于LPC1114每組只有12個引腳,所以只用了其中的低12位。當位為0 時做輸入,為1時做輸出,12位與12個引腳一一對應,每位設置對應一個引腳。在默認狀態(tài)下DIR的值為全0,所以在默認狀態(tài)下所有的引腳為輸入狀態(tài)。要改變引腳狀態(tài),可通過寫DIR寄存器對應的位來實現(xiàn)。例如,要把端口0的第1、3、5腳設為輸入,其它全為輸出,執(zhí)行語句“LPC_GPIO0->DIR = 0xFD5;”就可以了。

本文引用地址:http://m.butianyuan.cn/article/201611/316323.htm

接下來看IS寄存器,其偏移地址為0x8004,屬性為可讀可寫,它負責GPIO引腳外部中斷的觸發(fā)方式,即引腳響應中斷是電平觸發(fā)還是邊沿觸發(fā),由該寄存器的設置來決定。IS寄存器也只用了32位中的低12位,當位為0 時選擇邊沿觸發(fā),為1時選擇電平觸發(fā),12位與12個引腳一一對應,每位設置對應一個引腳。在默認狀態(tài)下IS的值為全0,所以在默認狀態(tài)下所有的引腳在外部中斷時是邊沿觸發(fā)方式。要改變引腳中斷的觸發(fā)方式,可通過寫IS寄存器對應的位來實現(xiàn)。例如,要把端口1的第11腳設為電平觸發(fā),執(zhí)行語句“LPC_GPIO1->IS |= 0x800;”就可以了。另外,在選擇觸發(fā)方式時要注意,若選擇了電平觸發(fā),必須要考慮是否會在觸發(fā)電平保持期間引發(fā)多次外部中斷響應。一般情況下,選擇邊沿觸發(fā)方式就不會存在這個問題。

接著看IEV寄存器,其偏移地址為0x800C,屬性為可讀可寫,它負責配合上面的IS寄存器來確定具體的觸發(fā)方式。即:若IS配置為邊沿觸發(fā)方式,則IEV負責選擇是上跳沿還是下跳沿;若IS配置為電平觸發(fā)方式,則IVE負責選擇是高電平觸發(fā)還是低電平觸發(fā)。IVE寄存器也只用了32位中的低12位,當位為0 時選擇下跳沿觸發(fā)或低電平觸發(fā)方式,為1時選擇上跳沿觸發(fā)或高電平觸發(fā)方式,12位與12個引腳一一對應,每位設置對應一個引腳。在默認狀態(tài)下IEV的值為全0,所以在默認狀態(tài)下所有的引腳在外部中斷時是下跳沿觸發(fā)或低電平觸發(fā)方式。要改變引腳中斷的具體觸發(fā)方式,可通過寫IEV寄存器對應的位來實現(xiàn)。例如,要把端口2的第5腳設為高電平觸發(fā),執(zhí)行兩句語句“LPC_GPIO1->IS |= 0x020;LPC_GPIO1->IVE |=0x020;”就可以了。另外要強調一點,IEV寄存器必須和IS寄存器配合使用。一般來說,應先配置IS,再配置IVE。

接下來是IBE寄存器,其偏移地址為0x8008,屬性為可讀可寫,它負責GPIO在外部中斷時,用來選擇是否使用雙邊沿觸發(fā)方式。在某些特殊應用的地方(比如需要同時捕獲脈沖的上跳沿和下跳沿時),需要在程序中頻繁轉換觸發(fā)方式,而在LPC1114中由于有IBE寄存器,所以操作就簡單多了,只要通過設置IBE寄存器來使能對應引腳的雙沿觸發(fā)方式就可以了。IBE寄存器也只用了32位中的低12位,當位為0 時關閉雙沿觸發(fā),此時的觸發(fā)方式由IEV寄存器決定。為1時開啟雙沿觸發(fā),12位與12個引腳一一對應,每位設置對應一個引腳。在默認狀態(tài)下IBE的值為全0,所以在默認狀態(tài)下所有的引腳在外部中斷時雙沿觸發(fā)方式處于關閉狀態(tài)。要使能雙邊沿觸發(fā)方式,可通過寫IBE寄存器對應的位來實現(xiàn)。例如,要把端口3的第1腳設為雙沿觸發(fā)方式,執(zhí)行兩句語句“LPC_GPIO2->IS &= ~0x002;LPC_GPIO2->IBE |=0x002;”就可以了。另外有一點需要強調一下,如果某引腳被IBE設置為雙邊沿觸發(fā),則其對應的IEV設置就不起作用了。還有就是IBE寄存器也必須和IS寄存器配合使用,一般來說,應先配置IS,再配置IBE。

下一個是IE寄存器,其偏移地址為0x8010,屬性為可讀可寫,它負責使能GPIO引腳的外部中斷功能。該寄存器也只用了32位中的低12位,當位為0 時中斷功能被屏蔽(即中斷不使能),為1時中斷功能未屏蔽(即中斷使能),12位與12個引腳一一對應,每位設置對應一個引腳。在默認狀態(tài)下IE的值為全0,所以在默認狀態(tài)下所有的引腳不使用外部中斷(中斷全部被屏蔽)。要使能某引腳的外部中斷功能,可通過寫IE寄存器對應的位來實現(xiàn)。例如,要開啟端口0的第1引腳中斷功能,執(zhí)行語句“LPC_GPIO0->IE = 0x002;”就可以了。

再下一個是RIS寄存器,其偏移地址為0x8014,屬性為只讀,它負責查詢哪個GPIO引腳上有中斷請求。該寄存器也只用了32位中的低12位,當位為0 時表明對應引腳上沒有外部中斷請求發(fā)生,為1時表明對應引腳上有外部中斷請求發(fā)生,12位與12個引腳一一對應,每位設置對應一個引腳。在復位時RIS的值為全0,表明所有的引腳復位時都沒有外部中斷請求發(fā)生。如果某個引腳上RIS對應的值為1,則表明該引腳上有符合條件的中斷請求發(fā)生,此時若對應的IE位也為1(即開啟該引腳的中斷功能),就會發(fā)生該引腳的中斷響應。但如果對應的IE位不為1,則不會響應中斷。

接下來是MIS寄存器,其偏移地址為0x8018,屬性為只讀,它和上面的RIS寄存器基本是一樣的,可以用于查詢是否有中斷響應。不同點在于,RIS是只要引腳上滿足中斷觸發(fā)條件它對應的位就被置1,但它不一定被響應,因為它有可能被屏蔽了(例如對應的IE位沒有被置1),因此RIS不能判定中斷是否響應了,而只能判定有符合條件的中斷請求發(fā)生;但在MIS寄存器中,若相應的位被置1了,則說明這個中斷一定被響應了,因此可以通過程序查詢MIS寄存器的方式來判斷是否有中斷被響應,是哪個引腳上的中斷被響應。其實MIS寄存器表征的就是屏蔽之后的中斷狀態(tài),它也只用了32位中的低12位,當位為0 時表明對應引腳上沒有外部中斷響應,為1時表明對應引腳上有外部中斷響應,12位與12個引腳一一對應,每位設置對應一個引腳。

最后一個是IC寄存器,其偏移地址為0x801C,屬性為只寫,它用來清除中斷邊沿檢測邏輯。它也只用了32位中的低12位,當位為0 時不起作用,即對外部中斷無任何影響,為1時表明對應引腳上的邊沿觸發(fā)端口位被清零,12位與12個引腳一一對應,每位設置對應一個引腳。之所以要設IC寄存器,是因為在中斷響應后(僅邊沿型觸發(fā)),在RIS和MIS寄存器中相應的位不會被自動清零,因此在中斷響應后需要在IC寄存器的相應位中寫1來進行清零,以保證后續(xù)中斷的正常觸發(fā)。

以上是GPIO中各寄存器功能的基本介紹,至于詳細的使用方法,會在后面中斷一章中做詳細討論,這里先不贅述了。

接下來討論一下GPIO端口引腳的配置。從第一章中已經知道,LPC1114引腳復用的很多,除了第0端口中的3、第2端口中的2~10和第3端口中的4、5引腳外,其余的引腳都具有第二功能。甚至包括復位端RESET都復用在了GPIO0_0引腳。為了實現(xiàn)引腳上各復用功能間的切換,在處理器內部專門設立了一個引腳配置寄存器IOCON。用戶可以通過IOCON來配置每一個I/O的下列功能特性:

引腳復用功能;
內部上拉/下拉電阻或總線保持功能;
滯后模式;
引腳控制ADC輸入的模擬模式或數(shù)字模式;
引腳控制I2C功能的I2C模式。
每個引腳對應一個IOCON寄存,所以對于LPC1114來說,至少應該有42個IOCON寄存器(其實共有46個,多出的4個用于其它功能設置)。一般來說,在使用任何引腳之前都應該先配置一下它所對應的IOCON寄存器,除非用的是引腳的默認功能。下面給出LPC1114中所有引腳的IOCON寄存器情況,如下表。
從表中可以看出,IOCON寄存器的基址為0x40044000,位于內存地圖中的ABP模塊內。它所對應的結構體定義如下:
typedef struct
{
__IO uint32_t PIO2_6; /*!< Offset: 0x000 (R/W) I/O configuration for pin PIO2_6 */
uint32_t RESERVED0[1];
__IO uint32_t PIO2_0; /*!< Offset: 0x008 (R/W) I/O configuration for pin PIO2_0/DTR/SSEL1 */
__IO uint32_t RESET_PIO0_0; /*!< Offset: 0x00C (R/W) I/O configuration for pin RESET/PIO0_0 */
__IO uint32_t PIO0_1; /*!< Offset: 0x010 (R/W) I/O configuration for pin PIO0_1/CLKOUT/CT32B0_MAT2 */
__IO uint32_t PIO1_8; /*!< Offset: 0x014 (R/W) I/O configuration for pin PIO1_8/CT16B1_CAP0 */
uint32_t RESERVED1[1];
__IO uint32_t PIO0_2; /*!< Offset: 0x01C (R/W) I/O configuration for pin PIO0_2/SSEL0/CT16B0_CAP0 */

__IO uint32_t PIO2_7; /*!< Offset: 0x020 (R/W) I/O configuration for pin PIO2_7 */
__IO uint32_t PIO2_8; /*!< Offset: 0x024 (R/W) I/O configuration for pin PIO2_8 */
__IO uint32_t PIO2_1; /*!< Offset: 0x028 (R/W) I/O configuration for pin PIO2_1/nDSR/SCK1 */
__IO uint32_t PIO0_3; /*!< Offset: 0x02C (R/W) I/O configuration for pin PIO0_3 */
__IO uint32_t PIO0_4; /*!< Offset: 0x030 (R/W) I/O configuration for pin PIO0_4/SCL */
__IO uint32_t PIO0_5; /*!< Offset: 0x034 (R/W) I/O configuration for pin PIO0_5/SDA */
__IO uint32_t PIO1_9; /*!< Offset: 0x038 (R/W) I/O configuration for pin PIO1_9/CT16B1_MAT0 */
__IO uint32_t PIO3_4; /*!< Offset: 0x03C (R/W) I/O configuration for pin PIO3_4 */

__IO uint32_t PIO2_4; /*!< Offset: 0x040 (R/W) I/O configuration for pin PIO2_4 */
__IO uint32_t PIO2_5; /*!< Offset: 0x044 (R/W) I/O configuration for pin PIO2_5 */
__IO uint32_t PIO3_5; /*!< Offset: 0x048 (R/W) I/O configuration for pin PIO3_5 */
__IO uint32_t PIO0_6; /*!< Offset: 0x04C (R/W) I/O configuration for pin PIO0_6/SCK0 */
__IO uint32_t PIO0_7; /*!< Offset: 0x050 (R/W) I/O configuration for pin PIO0_7/nCTS */
__IO uint32_t PIO2_9; /*!< Offset: 0x054 (R/W) I/O configuration for pin PIO2_9 */
__IO uint32_t PIO2_10; /*!< Offset: 0x058 (R/W) I/O configuration for pin PIO2_10 */
__IO uint32_t PIO2_2; /*!< Offset: 0x05C (R/W) I/O configuration for pin PIO2_2/DCD/MISO1 */

__IO uint32_t PIO0_8; /*!< Offset: 0x060 (R/W) I/O configuration for pin PIO0_8/MISO0/CT16B0_MAT0 */
__IO uint32_t PIO0_9; /*!< Offset: 0x064 (R/W) I/O configuration for pin PIO0_9/MOSI0/CT16B0_MAT1 */
__IO uint32_t SWCLK_PIO0_10; /*!< Offset: 0x068 (R/W) I/O configuration for pin SWCLK/PIO0_10/SCK0/CT16B0_MAT2 */
__IO uint32_t PIO1_10; /*!< Offset: 0x06C (R/W) I/O configuration for pin PIO1_10/AD6/CT16B1_MAT1 */
__IO uint32_t PIO2_11; /*!< Offset: 0x070 (R/W) I/O configuration for pin PIO2_11/SCK0 */
__IO uint32_t R_PIO0_11; /*!< Offset: 0x074 (R/W) I/O configuration for pin TDI/PIO0_11/AD0/CT32B0_MAT3 */
__IO uint32_t R_PIO1_0; /*!< Offset: 0x078 (R/W) I/O configuration for pin TMS/PIO1_0/AD1/CT32B1_CAP0 */
__IO uint32_t R_PIO1_1; /*!< Offset: 0x07C (R/W) I/O configuration for pin TDO/PIO1_1/AD2/CT32B1_MAT0 */

__IO uint32_t R_PIO1_2; /*!< Offset: 0x080 (R/W) I/O configuration for pin nTRST/PIO1_2/AD3/CT32B1_MAT1 */
__IO uint32_t PIO3_0; /*!< Offset: 0x084 (R/W) I/O configuration for pin PIO3_0/nDTR */
__IO uint32_t PIO3_1; /*!< Offset: 0x088 (R/W) I/O configuration for pin PIO3_1/nDSR */
__IO uint32_t PIO2_3; /*!< Offset: 0x08C (R/W) I/O configuration for pin PIO2_3/RI/MOSI1 */
__IO uint32_t SWDIO_PIO1_3; /*!< Offset: 0x090 (R/W) I/O configuration for pin SWDIO/PIO1_3/AD4/CT32B1_MAT2 */
__IO uint32_t PIO1_4; /*!< Offset: 0x094 (R/W) I/O configuration for pin PIO1_4/AD5/CT32B1_MAT3 */
__IO uint32_t PIO1_11; /*!< Offset: 0x098 (R/W) I/O configuration for pin PIO1_11/AD7 */
__IO uint32_t PIO3_2; /*!< Offset: 0x09C (R/W) I/O configuration for pin PIO3_2/nDCD */

__IO uint32_t PIO1_5; /*!< Offset: 0x0A0 (R/W) I/O configuration for pin PIO1_5/nRTS/CT32B0_CAP0 */
__IO uint32_t PIO1_6; /*!< Offset: 0x0A4 (R/W) I/O configuration for pin PIO1_6/RXD/CT32B0_MAT0 */
__IO uint32_t PIO1_7; /*!< Offset: 0x0A8 (R/W) I/O configuration for pin PIO1_7/TXD/CT32B0_MAT1 */
__IO uint32_t PIO3_3; /*!< Offset: 0x0AC (R/W) I/O configuration for pin PIO3_3/nRI */
__IO uint32_t SCK_LOC; /*!< Offset: 0x0B0 (R/W) SCK pin location select Register */
__IO uint32_t DSR_LOC; /*!< Offset: 0x0B4 (R/W) DSR pin location select Register */
__IO uint32_t DCD_LOC; /*!< Offset: 0x0B8 (R/W) DCD pin location select Register */
__IO uint32_t RI_LOC; /*!< Offset: 0x0BC (R/W) RI pin location Register */
} LPC_IOCON_TypeDef;

上述結構體定義在頭文件LPC11xx.h中。

每一個IOCON寄存器都是32位結構,但它最多只用了其中的低11位,因為根據各引腳功能不同,設置所占用的位數(shù)是不一樣的。為了方便討論,下表給出一個IOCON寄存器的一般位域定義描述,在實際用到引腳的不同設置時,請自行查詢數(shù)據手冊。

從上表中可以看出,IOCON寄存器的低三位(0~2位)是用來選擇引腳復用功能的(FUNC),第3位和第4位是用來選擇該引腳的上拉或下拉功能的,第5位是用來選擇是否使用滯后作用的,第7位是用來選擇該引腳是用于數(shù)字模式還是模擬模式的(只有端口1的第0~4引腳、第10~11引腳和端口0的第11引腳具有A/D功能,所以其它引腳沒有此設置),第8位和位9位是用來設置引腳的I2C形式的(只有端口0的第4和第5腳具有I2C復用,所以其它引腳沒有此設置)。詳細情況如下表所示。
下表是上表中引腳復用功能(FUNC)的選擇情況。
從上表中可以看出,由于LPC1114各引腳的復用功能數(shù)量不一樣,所以對于每一個引腳FUNC位的設置要根據具體引腳來定,不能想當然一概而論。比如,不能認為FUNC為全0時引腳就是使用IO功能,因為端口1的第0~3引腳和端口0的第0、第10~11引腳在FUNC為全0時就不是IO引腳。

下面對引腳配置做幾點說明:

1.若引腳被配置為GPIO,則可用DIR寄存器來設置其方向(即輸入/輸出);若配置為非GPIO功能時,DIR設置無效。

2.若引腳被配置為GPIO,則默認為帶上拉的方式,但無論是上拉還是下拉,都是弱拉式的(片內40k電阻),若要強拉必須外接電阻。

3.滯后作用即為輸入緩沖,它只能在外部引腳電壓為2.5~3.6V時才能使用,當電壓低于2.5V時必須禁能。

4.選擇A/D轉換模式時,內部數(shù)字接收部分被斷開,以保證輸入電壓的精度,若只接收高低電平,必須設為數(shù)字模式,否則讀不到電平。

5.只有部分引腳有A/D模式和I2C模式(見FUNC表),其它引腳配置為此模式時無效,若引腳配置為A/D模式后,滯后和上/下拉配置無效。

6.所有引腳配置的IOCON在復位時,值為0xD0,表示默認時引腳為復用功能第0組,上拉電阻模式,禁能滯后特性,數(shù)字模式。

7.在使用程序配置時,要注意IOCON的第6位(保留位)必須寫1,因其復位值為1。

8.其它四個多于的特殊配置寄存器(SCK_LOC、DSR_LOC、DCD_LOC、RI_LOC)主要用來定位某引動功能的引腳,具體用法請參考手冊。

9.在配置IOCON之前必須把IOCON的時鐘(位于AHBCLKCTRL寄存器中的第16位)打開,否則配置不了,配置完成后再把時鐘關閉,以節(jié)約電能。

最后來看幾個例子:

一、要求把端口0的第0腳配置為GPIO口,方向為輸出,帶上拉,輸出值為0。

執(zhí)行:LPC_SYSCON->SYSAHBCLKCTRL |= (1<<16);
LPC_IOCON->RESET_PIO0_0 = 0xD1;
LPC_SYSCON->SYSAHBCLKCTRL &= ~(1<<16);
LPC_GPIO0->DIR |= 0x001;
LPC_GPIO0->MASKED_ACCESS[1] = 0x000;

二、要求把端口1的第1腳配置為A/D輸入口。

執(zhí)行:LPC_SYSCON->SYSAHBCLKCTRL |= (1<<16);
LPC_IOCON->R_PIO1_1= 0x42;
LPC_SYSCON->SYSAHBCLKCTRL &= ~(1<<16);
三、要求把端口1的第3腳配置為CT32B1_MAT2模式。

執(zhí)行:LPC_SYSCON->SYSAHBCLKCTRL |= (1<<16);
LPC_IOCON->SWDIO_PIO1_3= 0xD3;
LPC_SYSCON->SYSAHBCLKCTRL &= ~(1<<16);




評論


技術專區(qū)

關閉