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