STC15系列單片機(jī)還提供另一種高速串行通信接口 —— SPI接口。SPI是一種全雙工、高速、同步的通信總線,有兩種操作模式:主模式和從模式。在主模式中支持高達(dá)3 Mbps的速率(工作頻率為12MHz時(shí),如果CPU主頻采用20MHz到36MHz,則可更高,從模式時(shí)速度無(wú)法太快,SYSclk/4以內(nèi)較好),還具有傳輸完成標(biāo)志和寫(xiě)沖突標(biāo)志保護(hù)。
一、 與SPI功能模塊相關(guān)的特殊功能寄存器
1.1SPI控制寄存器SPCTL
SPCTL : SPI控制寄存器
SSIG:SS引腳忽略控制位。
SSIG=1,MSTR(位4)確定器件為主機(jī)還是從機(jī)
SSIG=0,SS腳用于確定器件為主機(jī)還是從機(jī).SS腳可作為I/O口使用(見(jiàn)SPI主從選擇表)
SPEN:SPI使能位。
SPEN=1,SPI使能;
SPEN=0,SPI被禁止,所有SPI引腳都作為I/O口使用。
DORD:設(shè)定SPI數(shù)據(jù)發(fā)送和接收的位順序
DORD=1, 數(shù)據(jù)字的LSB(最低位)最先發(fā)送;
DORD=0, 數(shù)據(jù)字的MSB(最高位)最先發(fā)送。
MSTR:主/從模式選擇位(見(jiàn)SPI主從選擇表)。
CPOL:SPI時(shí)鐘極性
CPOL=1,SCLK空閑時(shí)為高電平。SCLK的前時(shí)鐘沿為下降沿而后沿為上升沿。
CPOL=0,SCLK空閑時(shí)為低電平。SCLK的前時(shí)鐘沿為上升沿而后沿為下降沿。
CPHA:SPI時(shí)鐘相位選擇。
CPHA=1, 數(shù)據(jù)在SCLK的前時(shí)鐘沿驅(qū)動(dòng),并在后時(shí)鐘沿采樣
CPHA=0, 數(shù)據(jù)在SS為低(SSIG=0)時(shí)被驅(qū)動(dòng),在SCLK的后時(shí)鐘沿被改變,并在前時(shí)鐘沿被采樣。(注:SSIG = 1時(shí)的操作未定義)
SPR1、SPR0:SPI時(shí)鐘頻率選擇控制位:
表中,CPU_CLK是CPU時(shí)鐘。
1.2 SPI狀態(tài)寄存器SPSTAT
SPSTAT: SPI狀態(tài)寄存器
SPIF:SPI傳輸完成標(biāo)志。
當(dāng)一次串行傳輸完成時(shí),SPIF置位 SPI中斷被打開(kāi)(即ESPI (IE2.1) 和EA(IE.7) 都置位),則產(chǎn)生中斷。SPI處于主模式且SSIG=0時(shí),如果SS為輸入并被驅(qū)動(dòng)為低電平,SPIF也將置位 "模式改變"。SPIF標(biāo)志通過(guò)軟件向其寫(xiě)入"1"清零。
WCOL:SPI寫(xiě)沖突標(biāo)志。
在數(shù)據(jù)傳輸?shù)倪^(guò)程中如果對(duì)SPI 數(shù)據(jù)寄存器SPDAT執(zhí)行寫(xiě)操作,WCOL將置位。WCOL標(biāo)志通過(guò)軟件向其寫(xiě)入"1"清零。
1.3 SPI數(shù)據(jù)寄存器SPDAT
SPDAT: SPI數(shù)據(jù)寄存器
SPDAT.7 - SPDAT.0: 傳輸?shù)臄?shù)據(jù)位Bit7~Bit0。
1.4 中斷允許寄存器2
ESPI : SPI中斷允許位
ESPI=1,允許SPI中斷,
ESPI=0,禁止SPI中斷。
二、SPI接口的結(jié)構(gòu)
STC15系列單片機(jī)的SPI功能方框圖如下圖所示。
SPI的核心是一個(gè)8位移位寄存器和數(shù)據(jù)緩沖器,數(shù)據(jù)可以同時(shí)發(fā)送和接收。在SPI數(shù)據(jù)的傳輸過(guò)程中,發(fā)送和接收的數(shù)據(jù)都存儲(chǔ)在數(shù)據(jù)緩沖器中。對(duì)于主模式,若要發(fā)送一字節(jié)數(shù)據(jù),只需將這個(gè)數(shù)據(jù)寫(xiě)到SPDAT寄存器中。主模式下SS信號(hào)不是必需的;但是在從模式下,必須在SS信號(hào)變?yōu)橛行Р⒔邮盏胶线m的時(shí)鐘信號(hào)后,方可進(jìn)行數(shù)據(jù)傳輸。在從模式下,如果一個(gè)字節(jié)傳輸完成后,SS信號(hào)變?yōu)楦唠娖?,這個(gè)字節(jié)立即被硬件邏輯標(biāo)志為接收完成,SPI接口準(zhǔn)備接收下一個(gè)數(shù)據(jù)。
三、SPI接口的數(shù)據(jù)通信
SPI接口 有4個(gè)管腳 SCLK, MISO, MOSI和SS,可在3組管腳之間進(jìn)行切換 SCLK/P1.5,MISO/P1.4, MOSI/P1.3和SS/P1.2 ];SCLK_2/P2.1, MISO_2/P2.2, MOSI_2/P2.3和SS_2/P2.4][SCLK_3/P4.3, MISO_3/P4.1, MOSI_3/P4.0和SS_3/P5.4]。MOSI ( Master Out Slave In,主出從入):主器件的輸出和從器件的輸入,用于主器件到從器件的串行數(shù)據(jù)傳輸。當(dāng)SPI作為主器件時(shí),該信號(hào)是輸出;當(dāng)SPI作為從器件時(shí),該信號(hào)是輸入。數(shù)據(jù)傳輸時(shí)最高位在先,低位在后 根據(jù)SPI規(guī)范,多個(gè)從機(jī)可以共享一根MOSI信號(hào)線。在時(shí)鐘邊界的前半周期,主機(jī)將數(shù)據(jù)放在MOSI信號(hào)線上,從機(jī)在該邊界處獲取該數(shù)據(jù)。MISO ( Master In Slave Out,主入從出):從器件的輸出和主器件的輸入,用于實(shí)現(xiàn)從器件到主器件的數(shù)據(jù)傳輸。當(dāng)SPI作為主器件時(shí),該信號(hào)是輸入;當(dāng)SPI作為從器件時(shí),該信號(hào)是輸出。數(shù)據(jù)傳輸時(shí)最高位在先,低位在后 SPI規(guī)范中,一個(gè)主機(jī)可連接多個(gè)從機(jī),因此,主機(jī)的MISO信號(hào)線會(huì)連接到多個(gè)從機(jī)上,或者說(shuō),多個(gè)從機(jī)共享一根MISO信號(hào)線。當(dāng)主機(jī)與一個(gè)從機(jī)通信時(shí),其他從機(jī)應(yīng)將其MISO引腳驅(qū)動(dòng)置為高阻狀態(tài)。SCLK ( SPI Clock,串行時(shí)鐘信號(hào)):串行時(shí)鐘信號(hào)是主器件的輸出和從器件的輸入,用于同步主器件和從器件之間在MOSI和MISO線上的串行數(shù)據(jù)傳輸。當(dāng)主器件啟動(dòng)一次數(shù)據(jù)傳輸時(shí),自動(dòng)產(chǎn)生8個(gè)SCLK時(shí)鐘周期信號(hào)給從機(jī)。在SCLK的每個(gè)跳變處(上升沿或下降沿)移出一位數(shù)據(jù)。所以,一次數(shù)據(jù)傳輸可以傳輸一個(gè)字節(jié)的數(shù)據(jù)。SS( Slave Select,從機(jī)選擇信號(hào)):這是一個(gè)輸入信號(hào),主器件用它來(lái)選擇處于從模式的SPI模塊。主模式和從模式下SS的使用方法不同。在主模式下,SPI接口只能有一個(gè)主機(jī),不存在主機(jī)選擇問(wèn)題,該模式下SS不是必需的。主模式下通常將主機(jī)的SS管腳通過(guò)10KΩ的電阻上拉高電平。每一個(gè)從機(jī)的SS接主機(jī)的I/O口,由主機(jī)控制電平高低,以便主機(jī)選擇從機(jī)。
在從模式下,不管發(fā)送還是接收,SS信號(hào)必須有效。因此在一次數(shù)據(jù)傳輸開(kāi)始之前必須將SS為低電平。SPI主機(jī)可以使用I/O口選擇一個(gè)SPI器件作為當(dāng)前的從機(jī)。
SPI從器件通過(guò)其SS腳確定是否被選擇。如果滿足下面的條件之一,SS就被忽略:如果SPI系統(tǒng)被禁止,即SPEN(SPCTL.6)= 0(復(fù)位值)
如果SPI配置為主機(jī),即MSTR(SPCTL.4)=1,并且P1.2/SS配置為輸出( P1M0.2和P1M1.2)如果SS腳被忽略,即SSIG(SPCTL.7)= 1,該腳配置用于I/O口功能。
注:即使SPI被配置為主機(jī)(MSTR = 1),它仍然可以通過(guò)拉低SS腳配置為從機(jī)(如果P1.2/SS配置為輸入且SSIG=0)。要使能該特性,應(yīng)當(dāng)置位SPIF(SPSTAT.7)。
四、SPI測(cè)試代碼
這里采用的是查詢法。
#define u16 unsigned int
#define u8 unsigned char
// 控制寄存器 SPCTL
#define SSIG 1 // 1: 忽略SS腳,由MSTR位決定主機(jī)還是從機(jī) 0: SS腳用于決定主從機(jī)。
#define SPEN 1 // 1: 允許SPI,0:禁止SPI,所有SPI管腳均為普通IO
#define DORD 0 // 1:LSB先發(fā),0:MSB先發(fā)
#define MSTR 1 // 1:設(shè)為主機(jī) 0:設(shè)為從機(jī)
#define CPOL 1 // 1: 空閑時(shí)SCLK為高電平,0:空閑時(shí)SCLK為低電平
#define CPHA 1 // 數(shù)據(jù)在SCLK的前時(shí)鐘沿驅(qū)動(dòng),并在后時(shí)鐘沿采樣
#define SPEED_4 0 // fosc/4
#define SPEED_8 1 // fosc/8
#define SPEED_16 2 // fosc/16
#define SPEED_32 3 // fosc/32
// 狀態(tài)寄存器 SPSTAT
#define SPIF 0x80 //SPI傳輸完成標(biāo)志。寫(xiě)入1清0。
#define WCOL 0x40 //SPI寫(xiě)沖突標(biāo)志。寫(xiě)入1清0。
void Spi_Init(void)
{
SPDAT = 0; //初始化SPDAT
SPSTAT = SPIF | WCOL; //清除SPI狀態(tài)標(biāo)志
SPCTL = (SSIG < < 7) + (SPEN < < 6) + (MSTR < < 4) + (CPOL < < 3) + (CPHA < < 2) + SPEED_4;
}
void Spi_Send(u8 dat)
{
SPSTAT = SPIF + WCOL; //清0 SPIF和WCOL標(biāo)志
SPDAT = dat; //發(fā)送一個(gè)字節(jié)
while (!(SPSTAT & SPIF)); //等待SPI數(shù)據(jù)傳輸完成
SPSTAT = SPIF + WCOL; //清0 SPIF和WCOL標(biāo)志
}
評(píng)論