找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 28402|回復(fù): 5
打印 上一主題 下一主題
收起左側(cè)

第5章 單片機(jī)SPI通信

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
51單片機(jī)輕松入門(mén)—基于STC15W4K系列(C語(yǔ)言版)
李友全
編著:http://www.torrancerestoration.com/bbs/dpj-37954-1.html


5章 單片機(jī)SPI通信
1 接口定義
2 SPI接口相關(guān)寄存器
3 SPI接口運(yùn)用舉例

(1)單主機(jī)-單從機(jī)通信方式(從機(jī)不用片選)

(2)STC-SPI硬接口(單主單從_從機(jī)使用片選)

(3)STC-SPI硬接口(互為主從)

(4)STC-SPI硬接口(單主多從)

1 接口定義

UART串口通信速度一般只能到達(dá)115200位/秒,SPI通信數(shù)據(jù)速率可達(dá)8MHz

(16M位/秒)以上的水平。 SPI接口共有4根信號(hào)線,分別是:設(shè)備選擇線(片選)、時(shí)鐘線、串行數(shù)據(jù)輸出 線、串行數(shù)據(jù)輸入線,如下圖所示。

① MOSI(Master Out Slave In):主器件數(shù)據(jù)輸出,從器件數(shù)據(jù)輸入,用于主器件到從
器件的數(shù)據(jù)傳輸。
② MISO(Master In Slave Out):主器件數(shù)據(jù)輸入,從器件數(shù)據(jù)輸出,用于從器件到主 器件的數(shù)據(jù)傳輸。
③ SCLK (SPI Clock) :時(shí)鐘信號(hào),只能由主器件產(chǎn)生。
④ /SS:設(shè)備選擇線(片選),由主器件控制,當(dāng)從器件片選信號(hào)輸入低電平時(shí)為選中狀 態(tài),/SS是針對(duì)從器件而言的,作為主器件,不需要使用/SS。
單片機(jī)為了和外設(shè)進(jìn)行數(shù)據(jù)交換,根據(jù)外設(shè)工作要求,單片機(jī)輸出時(shí)鐘信號(hào)有幾種不同的狀 態(tài)。

(1)時(shí)鐘極性(CPOL)定義了時(shí)鐘空閑狀態(tài)的電平。 CPOL=0:時(shí)鐘空閑狀態(tài)為低電平。 CPOL=1:時(shí)鐘空閑狀態(tài)為高電平。

(2)時(shí)鐘相位(CPHA)定義數(shù)據(jù)的采樣時(shí)刻。 CPHA=0:?jiǎn)纹瑱C(jī)在每個(gè)時(shí)鐘周期的第一個(gè)跳變沿(上升或下降) 采樣外部數(shù)據(jù),第二個(gè)

跳變沿輸出數(shù)據(jù)。
CPHA=1:在每個(gè)時(shí)鐘周期的第一個(gè)跳變沿(上升或下降) 輸出數(shù)據(jù),第二個(gè)跳變沿采樣 外部數(shù)據(jù)。

時(shí)鐘極性(CPOL)和時(shí)鐘相位(CPHA)的組合可形成四種不同的數(shù)據(jù)傳輸時(shí)序,如下圖所示。

前沿采樣后沿輸出


2 SPI接口相關(guān)寄存器
表5-1 SPCTL控制寄存器(復(fù)位值為0000 0100B)

位號(hào)

D7

D6

D5

D4

D3

D2

D1

D0

位名稱

SSIG

SPEN

DORD

MSTR

CPOL

CPHA

SPR1

SPR0

典型設(shè)置舉例:
l 2個(gè)單片機(jī)3線制主從通信(從機(jī)不用片選線),主機(jī)設(shè)置:0xF0(1111 0000), 從機(jī)設(shè)置:0xE0(1110 0000)。
l 2個(gè)單片機(jī)4線制通信(從機(jī)使用片選線),主機(jī)設(shè)置:0xF0(1111 0000), 從機(jī)設(shè)置:0x60(0110 0000)。
l 2個(gè)單片機(jī)互為主從4線制通信(從機(jī)使用片選線),主機(jī)設(shè)置:0xF0(1111 0000), 從機(jī)設(shè)置:0x60(0110 0000)。

各位詳細(xì)說(shuō)明:

SSIG :/SS引腳忽略控制位。
1:忽略/SS引腳,由D4(MSTR)位確定器件為主機(jī)還是從機(jī),MSTR=1(主機(jī)),MSTR=0(從機(jī))。
0:作從機(jī)且使用片選線時(shí)設(shè)為0,同時(shí)將D4(MSTR)位設(shè)0成為從機(jī),當(dāng)片選線/SS為低時(shí)芯片 選中,可正常通信,當(dāng)片選線/SS為高時(shí)芯片沒(méi)選中,不參與通信。
SPEN :SPI使能位。1:使能SPI。0:禁止SPI,所有SPI引腳都作為普通IO口使用。

DORD:設(shè)定數(shù)據(jù)發(fā)送和接收的順序。1:低位在前,高位在后。 0:高位在前,低位在后。 MSTR :MSTR=1(主機(jī)),MSTR=0(從機(jī))。 CPOL:時(shí)鐘極性。1:SPI空閑時(shí),時(shí)鐘線為高電平。0:SPI空閑時(shí),時(shí)鐘線為低電平。 CPHA:時(shí)鐘相位選擇。1:時(shí)鐘前沿輸出,后沿采樣。0:時(shí)鐘前沿采樣,后沿輸出。

SPR1與SPR0:主機(jī)輸出時(shí)鐘速率選擇,見(jiàn)下表。


說(shuō)明:SYS_clk表示CPU運(yùn)行時(shí)鐘,若沒(méi)進(jìn)行分頻設(shè)置(默認(rèn)值),SYS_clk就是內(nèi)部R/C時(shí)鐘

或外部晶振頻率,作為主機(jī)方式,上面4種配置方式都可以穩(wěn)定工作,但建議時(shí)鐘頻率一般不 要超過(guò)3M,這樣既可增強(qiáng)SPI傳輸穩(wěn)定性又能減小高頻信號(hào)對(duì)電路板上其它器件產(chǎn)生干擾。對(duì) 于從機(jī),時(shí)鐘速率設(shè)置無(wú)效,它完全是由主機(jī)時(shí)鐘頻率控制,從機(jī)能接受的時(shí)鐘頻率要求控 制在SYS_clk/4以內(nèi),比如主機(jī)和從機(jī)都使用內(nèi)部R/C時(shí)鐘33.1776MHZ,主機(jī)和從機(jī)最高允許

時(shí)鐘頻率率33.1776/4≈8.3MHz。


表5-3 SPSTAT狀態(tài)寄存器(復(fù)位值為00xx xxxxB)

位號(hào)

D7

D6

D5

D4

D3

D2

D1

D0

位名稱

SPIF

WOCL

-

-

-

-

-

-

SPIF:SPI傳輸完成標(biāo)志。當(dāng)一次傳輸完成時(shí),SPIF被置1,此時(shí),如果SPI中斷被打開(kāi)

(ESPI=1,EA=1),則產(chǎn)生中斷,SPIF標(biāo)志通過(guò)軟件向其寫(xiě)入1而清零,比如:SPSTAT=0xC0; 執(zhí)行后SPSTAT=0x00。
WOCL:SPI寫(xiě)沖突標(biāo)志。當(dāng)一個(gè)數(shù)據(jù)還在傳輸,又向數(shù)據(jù)寄存器SPDAT寫(xiě)入數(shù)據(jù)時(shí),WOCL被 置1,WOCL標(biāo)志通過(guò)軟件向其寫(xiě)入1而清零。
表5-4 SPDAT數(shù)據(jù)寄存器(復(fù)位值為0000 0000B)

位號(hào)

D7

D6

D5

D4

D3

D2

D1

D0

位名稱

MSB







LSB

位7~0:保存SPI通信數(shù)據(jù)字節(jié)。MSB為最高位,LSB為最低位。例如,主機(jī)發(fā)送數(shù)據(jù):
SPDAT=tmpdata; // 將tmpdata變量中的數(shù)據(jù)發(fā)送出去,執(zhí)行此命令后硬件電路自動(dòng)輸出
tmpdata變量數(shù)據(jù)并接收從機(jī)數(shù)據(jù)。

重點(diǎn)說(shuō)明:如下圖所示,SPDAT是SPI接口內(nèi)部移位寄存器配備的一個(gè)數(shù)據(jù)緩沖寄存器,其物 理地址與移位寄存器一樣,當(dāng)對(duì)SPDAT進(jìn)行讀操作時(shí),讀取的是緩沖寄存器中的內(nèi)容,當(dāng)對(duì) SPDAT進(jìn)行寫(xiě)操作時(shí),數(shù)據(jù)將被直接寫(xiě)入移位寄存器并啟動(dòng)發(fā)送過(guò)程。


3 SPI接口運(yùn)用舉例

(1)單主機(jī)-單從機(jī)通信方式(從機(jī)不用片選),硬件電路如圖所示。


程序功能說(shuō)明:
計(jì)算機(jī)向主單片機(jī)(1號(hào))發(fā)送一個(gè)字節(jié)數(shù)據(jù),主單片機(jī)的串口每次收到1個(gè)字節(jié)數(shù)據(jù)后就立 刻將這個(gè)字節(jié)通過(guò)SPI口發(fā)送到從單片機(jī)(2號(hào)),同時(shí),主單片機(jī)收到從單片機(jī)發(fā)回的一個(gè) 字節(jié),并把收到的這個(gè)字節(jié)通過(guò)串口發(fā)送到計(jì)算機(jī),可使用串口助手觀察實(shí)驗(yàn)結(jié)果。 從單片機(jī)SPI口收到數(shù)據(jù)后,把收到的數(shù)據(jù)(SPDAT中讀出的內(nèi)容)放到自己的移位寄存器中
(對(duì)SPDAT寫(xiě)入數(shù)據(jù)),當(dāng)下一次主單片機(jī)發(fā)送一個(gè)字節(jié)過(guò)來(lái)時(shí)把數(shù)據(jù)發(fā)回到主單片機(jī),R/C

時(shí)鐘頻率22.1184MHz,計(jì)算機(jī)串口波特率設(shè)置為9600、n、8、1,十六進(jìn)制發(fā)送與接收。


主單片機(jī)(1號(hào))程序代碼:


#include "STC15W4K.H"

//

注意宏定義后面沒(méi)分號(hào)

bit SPI_Receive;
//
SPI 端口收到數(shù)據(jù)標(biāo)志位
unsigned char SPI_buffer;
//
保存SPI端口收到的數(shù)據(jù)
/**************************************************************************
- 功能描述:STC15單片機(jī)串口1初始化,使用T1方式2自重載方式做波特率發(fā)生器
**************************************************************************/
void UART_init(void) // 9600bps@22.1184MHz
{
// 下面代碼設(shè)置定時(shí)器1
TMOD |= 0x20; // 0010 0000 定時(shí)器1工作于方式2(8位自動(dòng)重裝方式) TH1 = 0xFA; // 波特率:9600 /22.1184MHZ
TL1 = 0xFA; // 波特率:9600 /22.1184MHZ TR1 = 1;
// 下面代碼設(shè)置定串口
AUXR = 0x00; // 很關(guān)鍵,使用定時(shí)器1作為波特率發(fā)生器,S1ST2=0
SCON = 0x50; // 01010 0000 SM0.SM1=01(最普遍的8位通信),REN=1(允許接受)
}
void Switch_port() // 根據(jù)硬件連接切換端口
{
AUXR1&=0XF3; //1111 0011
AUXR1|=0X04; //0000 0100
}
void port_mode() // 端口模式
{
P0M1=0x00; P0M0=0x00;P1M1=0x00; P1M0=0x00;P2M1=0x00; P2M0=0x00;P3M1=0x00; P3M0=0x00; P4M1=0x00; P4M0=0x00;P5M1=0x00; P5M0=0x00;P6M1=0x00; P6M0=0x00;P7M1=0x00; P7M0=0x00;
}

void main(void)
{
unsigned char tmpdata,SPI_status;
port_mode(); // 所有IO口設(shè)為準(zhǔn)雙向弱上拉方式。 UART_init(); // 初始化串口2C9600bps@22.1184MHz],9600bps@22.1184MHz
SPCTL=0xF0; // 主機(jī) (或SPCTL=0xFC; )
Switch_port(); // 端口切換
while(1) // 主循環(huán)
{
if(RI) // 判串口是否收到數(shù)據(jù)
{
tmpdata=SBUF; // 讀取串口中收到的數(shù)據(jù) RI=0;
P35=!P35; // 串口接收數(shù)據(jù)指示燈,調(diào)試時(shí)觀察串口工作是否正常
SPDAT=tmpdata; // 將數(shù)據(jù)發(fā)送到從機(jī)SPI SPI_status=0;
while(SPI_status==0)
{
SPI_status=SPSTAT; // 等待SPIF=1即等待SPI發(fā)送完畢 SPI_status=SPI_status&0x80;
}
SPSTAT=0xC0; // 清0標(biāo)志位SPIF和WCOL SPI_buffer=SPDAT; // 保存收到的數(shù)據(jù)
SBUF=SPI_buffer; // 將接收到的數(shù)據(jù)從串口發(fā)送到計(jì)算機(jī)
while(TI==0); // 等待發(fā)送完畢
TI=0; // 清零串口發(fā)送中斷標(biāo)志
}
}
}

從單片機(jī)(2號(hào))程序代碼:


#include "STC15W4K.H"
//
注意宏定義后面沒(méi)分號(hào)
bit SPI_Receive;
//
SPI 端口收到數(shù)據(jù)標(biāo)志位
unsigned char SPI_buffer;
//
保存SPI端口收到的數(shù)據(jù)
void port_mode() {}
//
端口模式,與主單片機(jī)相同
void main(void)



{



port_mode();
//
所有IO口設(shè)為準(zhǔn)雙向弱上拉方式。
SPCTL=0xE0;
//
從機(jī) (或SPCTL=0xEC; )
IE2=IE2|0x02;
//
ESPI(IE2.1)=1,允許SPIF產(chǎn)生中斷
EA=1;
//
開(kāi)總中斷
SPI_Receive=0;
//
清標(biāo)志字
while(1)
//
主循環(huán)
{



if (SPI_Receive)


// 判收是否收到主機(jī)SPI發(fā)來(lái)的數(shù)據(jù)
{



SPI_Receive=0;


// 清0主單片機(jī)SPI端口收到數(shù)據(jù)標(biāo)志位
SPDAT=SPI_buffer; // 將收到數(shù)據(jù)送SPDAT,準(zhǔn)備下一次通訊時(shí)發(fā)回
}
}
}
void SPI(void) interrupt 9
{
SPSTAT=0xC0; // 清0標(biāo)志位SPIF和WCOL SPI_buffer=SPDAT; // 保存收到的數(shù)據(jù) SPI_Receive=1; // 設(shè)置SPI端口收到數(shù)據(jù)標(biāo)志
}
(2)STC-SPI硬接口(單主單從_從機(jī)使用片選)


我們使用片選的目的是要實(shí)現(xiàn)多機(jī)選擇,如果只有一個(gè)從機(jī)就沒(méi)有必要多使用一條片選線
了,因此程序中在SPI傳輸前打開(kāi)片選(拉低從機(jī)SS),SPI傳輸完成后關(guān)閉片選(拉高 從機(jī)SS),當(dāng)然也可以不關(guān)閉。只有很少一點(diǎn)代碼與上例不同,如下所示。
sbit P2_4=P2^4;
#ifdef MASTER
SPCTL=0xf0; // 1111 0000
#else
SPCTL=0x60; // 0110 0000
#endif
………
P2_4=0; // 打開(kāi)從機(jī)片選 SPDAT=tmpdata; // SPI 發(fā)送數(shù)據(jù)
…… // 等待SPI發(fā)送完畢
P2_4=1; // 關(guān)閉從機(jī)片選


(3)STC-SPI硬接口(互為主從)

程序功能說(shuō)明:

1號(hào)單片機(jī)與2號(hào)單片機(jī)互為主從,分別通過(guò)串口與計(jì)算機(jī)相連,靜態(tài)時(shí)2個(gè)單片機(jī)都設(shè)置為 需要片選的從機(jī)方式,如果哪個(gè)單片機(jī)收到計(jì)算機(jī)發(fā)來(lái)的數(shù)據(jù),就設(shè)置為主機(jī)方式,拉低/SS 片選線選中從機(jī),并發(fā)送數(shù)據(jù)給從機(jī),主機(jī)收到從機(jī)的返回?cái)?shù)據(jù)發(fā)計(jì)算機(jī),從機(jī)收到主機(jī)的數(shù) 據(jù)也發(fā)計(jì)算機(jī),總體效果是2個(gè)計(jì)算機(jī)串口可以對(duì)傳數(shù)據(jù)。本實(shí)驗(yàn)在硬件上需要2個(gè)計(jì)算機(jī)串 口,串口助手可用STC_ISP打開(kāi)2個(gè)串口助手窗口,R/C時(shí)鐘頻率22.1184MHz,波特率為9600、n、

8、1。

完整代碼請(qǐng)參見(jiàn)教材P186-P187。

(4)STC-SPI硬接口(單主多從),硬件電路如圖所示。


•功能與程序請(qǐng)參見(jiàn)教材P188-P190。
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏11 分享淘帖 頂1 踩

相關(guān)帖子

回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:65956 發(fā)表于 2018-1-27 14:40 | 只看該作者
很好,學(xué)習(xí)了,不過(guò)有點(diǎn)少,再多點(diǎn)會(huì)更好,謝謝了
回復(fù)

使用道具 舉報(bào)

板凳
ID:439493 發(fā)表于 2018-12-4 19:48 | 只看該作者
很好,學(xué)習(xí)了,不過(guò)有點(diǎn)少,再多點(diǎn)會(huì)更好,謝謝了
回復(fù)

使用道具 舉報(bào)

地板
ID:520862 發(fā)表于 2019-4-24 21:13 | 只看該作者
感謝作者,很有幫助
回復(fù)

使用道具 舉報(bào)

5#
ID:693147 發(fā)表于 2020-3-12 09:54 | 只看該作者
感謝作者,幫助很大
回復(fù)

使用道具 舉報(bào)

6#
ID:810028 發(fā)表于 2020-7-31 13:58 | 只看該作者
不錯(cuò),值得學(xué)習(xí)
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表