LPC1114通用輸入/輸出端口(GPIO)續(xù)
首先看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的下列功能特性:
{
__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ù)手冊。
下面對引腳配置做幾點(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);
評論