IO 口是處理器系統(tǒng)對(duì)外溝通的最基本部件,從基本的鍵盤、LED 到復(fù)雜的外設(shè)芯片等,都是通過IO 口的輸入、輸出操作來進(jìn)行讀取或控制的。
MSP430系列中,不同單片機(jī)的IO 口數(shù)量不同。體積最小的MSP430F20xx系列只有10 個(gè)IO,適合在超小型設(shè)備中應(yīng)用;功能最豐富的MSP430FG46xx系列多達(dá)80 個(gè)IO 口,足夠應(yīng)付外部設(shè)備繁多的復(fù)雜應(yīng)用。在MSP430FE425 單片機(jī)中,共有14 個(gè)IO 口,屬于IO 口較少的系列。但由于需要大量引腳的設(shè)備,如LCD、多通道模擬量輸入等都有專用引腳,不占用IO 口。因此在大部分設(shè)計(jì)中IO 數(shù)量還是夠用的。
l IO 口寄存器
和大部分單片機(jī)類似,MSP430 單片機(jī)也將8 個(gè)IO 口編為一組。例如P1.0~P1.7都屬于P1 口。每組IO 口都有4 個(gè)控制寄存器,其中P1 和P2 口還額外具有3 個(gè)中斷寄存器。
表2.1.1 IO 口寄存器列表。
寄存器名 寄存器功能 讀寫類型 復(fù)位初始值
PxIN Px 口輸入寄存器 只讀 無
PxOUT Px 口輸出寄存器 可讀可寫 保持不變
PxDIR Px 口方向寄存器 可讀可寫 0(全部輸入)
PxSEL Px 口第二功能選擇 可讀可寫 0(全部為IO 口)
PxIE Px口中斷允許 可讀可寫 0(全部不允許中斷)
PxIES Px口中斷沿選擇 可讀可寫 保持不變
PxIFG Px口中斷標(biāo)志位 可讀可寫 0(全部未發(fā)生中斷)
這是本書第一次出現(xiàn)寄存器列表,有必要說明一下MSP430單片機(jī)的寄存器以及標(biāo)志位全部是大寫的。若出現(xiàn)的小寫的“x”,表示該設(shè)備不止一個(gè),因此寄存器也不止一個(gè)。為了縮短列表長(zhǎng)度,不用全部列出,用字母x 表示序號(hào)。例如對(duì)于表中的PxOUT,當(dāng)x取1、2、3 時(shí),就變成了P1OUT、P2OUT、P3OUT。
n PxDIR寄存器用于設(shè)置每一位IO口方向: 0=輸入 1=輸出MSP430 單片機(jī)的IO 口屬于雙向IO 口,因此在使用IO 口時(shí)首先要用方向選擇寄存器來設(shè)置每個(gè)IO 口的方向。例如P1.5、P1.6、P1.7 接有按鍵,P1.1、P1.3、P1.4接有LED,那么P1.5、P1.6、P1.7 要設(shè)為輸入,P1.1、P1.3、P1.4 要設(shè)為輸出:
P1DIR|=BIT1+BIT3+BIT4; // P1.1、P1.3、P1.4設(shè)為輸出
P1DIR &=~ (BIT5+BIT6+BIT7); // P1.5、P1.6、P1.7設(shè)為輸入(可省略)
由于PxDIR 寄存器在復(fù)位過程中會(huì)被清0,沒有被設(shè)置的IO 口方向均為輸入狀態(tài),因此第二句可以被省略。
對(duì)于所有已經(jīng)設(shè)成輸出狀態(tài)的IO口,可以通過PxOUT寄存器設(shè)置其輸出電平;對(duì)于所有已經(jīng)被設(shè)成輸入狀態(tài)的IO 口,可以通過PxIN 寄存器讀回其輸入電平。例如讀回P1.5口上的開關(guān)狀態(tài),并判斷若處于按下狀態(tài)(低電平)則從P1.1 口輸出高電平點(diǎn)亮LED:
if((P1IN & BIT5)==0) P1OUT|=BIT1; //若P1.5為低電平則P1.1輸出高電平
n PxSEL寄存器用于設(shè)置每一位IO的功能: 0=普通IO口 1=第二功能
在MSP430單片機(jī)中,很多內(nèi)部功能模塊也需要和外界進(jìn)行數(shù)據(jù)交流,為了不增加芯片引腳數(shù)量,大部分都和IO 口復(fù)用管腳。因此大多數(shù)IO 引腳都具有第二功能。通過寄存器PxSEL 可以指定某些IO 引腳作為第二功能使用。例如從附錄中管腳排布圖中查到MSP430x42x 系列單片機(jī)的P2.4、P2.5 口和串口的TXD、RXD 公用引腳。若需要將這兩個(gè)引腳配置為串口收發(fā)腳,則須將P2SEL的4、5位置高:
P2SEL |= BIT4 + BIT5; // P2.4,5 設(shè)為串口收發(fā)引腳
l IO 口中斷
在MSP430 所有的單片機(jī)中,P1 口、P2 口總共16 個(gè)IO 口均能作引發(fā)中斷。在MSP430x42x系列中,14 個(gè)IO 均屬于P1 或P2 口,因此每個(gè)IO 都能作為中斷源使用。通過下列2 個(gè)寄存器配置IO 口作為中斷使用:
n PxIE寄存器用于設(shè)置每一位IO的中斷允許: 0=不允許 1=允許
n PxIES寄存器用于選擇每一位IO的中斷觸發(fā)沿: 0=上升沿 1=下降沿
在使用IO 口中斷之前,需要先將IO 口設(shè)為輸入狀態(tài),并允許該位IO 的中斷,再通過PxIES寄存器選擇觸發(fā)方式為上升沿觸發(fā)或者下降沿觸發(fā)。例如將P1.5、P1.6、P1.7 口設(shè)為中斷源,下降沿觸發(fā):
P1DIR &=~(BIT5 + BIT6 + BIT7); // P1.5、P1.6、P1.7設(shè)為輸入(可省略)
P1IES |= BIT5 + BIT6 + BIT7; // P1.5、P1.6、P1.7設(shè)為下降沿中斷
P1IE |= BIT5 + BIT6 + BIT7; // 允許P1.5、P1.6、P1.7中斷
EINT(); // 總中斷允許
n PxIFG寄存器是IO中斷標(biāo)志寄存器:0=中斷條件不成立 1=中斷條件曾經(jīng)成立過無論中斷是否被允許,也不論是否正在執(zhí)行中斷服務(wù)程序,只要對(duì)應(yīng)IO 滿足了中斷條件(例如一個(gè)下降沿的到來),PxIFG 中的相應(yīng)位都會(huì)立即置1 并保持,只能通過軟件人工清除。這種機(jī)制的目的在于最大可能的保證不會(huì)漏掉每一次中斷。在MSP430系列單片機(jī)中,P1 口的8個(gè)中斷和P2 口8個(gè)中斷各公用了一個(gè)中斷入口,因此該寄存器另一重要作用在于中斷服務(wù)程序中用于判斷哪一位IO 產(chǎn)生的中斷。下面的中斷服務(wù)程序示范P1.5、P1.6、P1.7 發(fā)生中斷后執(zhí)行不同的代碼:
#pragma vector = PORT1_VECTOR //P1口中斷源
__interrupt void P1_ISR(void) //聲明一個(gè)中斷服務(wù)程序,名為P1_ISR()
{
if(P1IFG & BIT5) //判斷P1中斷標(biāo)志第5位(P1.5)
{
... ... //在這里寫P1.5中斷處理程序
}
if(P1IFG & BIT6) //判斷P1中斷標(biāo)志第6位(P1.6)
{
... ... //在這里寫P1.6中斷處理程序
}
if(P1IFG & BIT7) //判斷P1中斷標(biāo)志第7位(P1.7)
{
... ... //在這里寫P1.7中斷處理程序
}
P1IFG=0; //清除P1所有中斷標(biāo)志位
}
注意在退出中斷前一定要人工清除中斷標(biāo)志,否則該中斷會(huì)不停發(fā)生。類似的原理,即使IO 口沒有出現(xiàn)中斷條件,人工向?qū)慞xIFG 寄存器相應(yīng)位寫“1”,也會(huì)引發(fā)中斷。更改中斷沿選擇寄存器也相當(dāng)于跳變,也會(huì)引發(fā)中斷。所以更改PxIES寄存器應(yīng)該在關(guān)閉中斷后進(jìn)行,并在打開中斷之前及時(shí)清除中斷標(biāo)志。MSP430單片機(jī)大量的IO 中斷非常適合做鍵盤輸入用,但要注意鍵盤存在機(jī)械結(jié)構(gòu),在閉合或松開的過程中,機(jī)械結(jié)構(gòu)的碰撞和反彈會(huì)造成信號(hào)上數(shù)毫秒的“毛刺”。