新聞中心

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

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

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

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

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

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

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

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

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

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

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

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

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

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

引腳復(fù)用功能;
內(nèi)部上拉/下拉電阻或總線保持功能;
滯后模式;
引腳控制ADC輸入的模擬模式或數(shù)字模式;
引腳控制I2C功能的I2C模式。
每個(gè)引腳對應(yīng)一個(gè)IOCON寄存,所以對于LPC1114來說,至少應(yīng)該有42個(gè)IOCON寄存器(其實(shí)共有46個(gè),多出的4個(gè)用于其它功能設(shè)置)。一般來說,在使用任何引腳之前都應(yīng)該先配置一下它所對應(yīng)的IOCON寄存器,除非用的是引腳的默認(rèn)功能。下面給出LPC1114中所有引腳的IOCON寄存器情況,如下表。
從表中可以看出,IOCON寄存器的基址為0x40044000,位于內(nèi)存地圖中的ABP模塊內(nèi)。它所對應(yīng)的結(jié)構(gòu)體定義如下:
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;

上述結(jié)構(gòu)體定義在頭文件LPC11xx.h中。

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

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

下面對引腳配置做幾點(diǎn)說明:

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

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

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

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

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

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

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

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

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

最后來看幾個(gè)例子:

一、要求把端口0的第0腳配置為GPIO口,方向?yàn)檩敵?,帶上拉,輸出值?。

執(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);




關(guān)鍵詞: LPC1114輸入輸出端口GPI

評論


技術(shù)專區(qū)

關(guān)閉