51單片機輕松入門—基于STC15W4K系列(C語言版)
李友全 編著:http://www.zg4o1577.cn/bbs/dpj-37954-1.html
第5章 單片機SPI通信 1 接口定義 2 SPI接口相關寄存器 3 SPI接口運用舉例 (1)單主機-單從機通信方式(從機不用片選) (2)STC-SPI硬接口(單主單從_從機使用片選) (3)STC-SPI硬接口(互為主從) (4)STC-SPI硬接口(單主多從)
1 接口定義 UART串口通信速度一般只能到達115200位/秒,SPI通信數據速率可達8MHz (16M位/秒)以上的水平。 SPI接口共有4根信號線,分別是:設備選擇線(片選)、時鐘線、串行數據輸出 線、串行數據輸入線,如下圖所示。 ① MOSI(Master Out Slave In):主器件數據輸出,從器件數據輸入,用于主器件到從 器件的數據傳輸。 ② MISO(Master In Slave Out):主器件數據輸入,從器件數據輸出,用于從器件到主 器件的數據傳輸。 ③ SCLK (SPI Clock) :時鐘信號,只能由主器件產生。 ④ /SS:設備選擇線(片選),由主器件控制,當從器件片選信號輸入低電平時為選中狀 態,/SS是針對從器件而言的,作為主器件,不需要使用/SS。 單片機為了和外設進行數據交換,根據外設工作要求,單片機輸出時鐘信號有幾種不同的狀 態。 (1)時鐘極性(CPOL)定義了時鐘空閑狀態的電平。 CPOL=0:時鐘空閑狀態為低電平。 CPOL=1:時鐘空閑狀態為高電平。 (2)時鐘相位(CPHA)定義數據的采樣時刻。 CPHA=0:單片機在每個時鐘周期的第一個跳變沿(上升或下降) 采樣外部數據,第二個 跳變沿輸出數據。 CPHA=1:在每個時鐘周期的第一個跳變沿(上升或下降) 輸出數據,第二個跳變沿采樣 外部數據。 時鐘極性(CPOL)和時鐘相位(CPHA)的組合可形成四種不同的數據傳輸時序,如下圖所示。 前沿采樣后沿輸出
2 SPI接口相關寄存器 表5-1 SPCTL控制寄存器(復位值為0000 0100B) 位號 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | 位名稱 | SSIG | SPEN | DORD | MSTR | CPOL | CPHA | SPR1 | SPR0 |
典型設置舉例: l 2個單片機3線制主從通信(從機不用片選線),主機設置:0xF0(1111 0000), 從機設置:0xE0(1110 0000)。 l 2個單片機4線制通信(從機使用片選線),主機設置:0xF0(1111 0000), 從機設置:0x60(0110 0000)。 l 2個單片機互為主從4線制通信(從機使用片選線),主機設置:0xF0(1111 0000), 從機設置:0x60(0110 0000)。 各位詳細說明: SSIG :/SS引腳忽略控制位。 1:忽略/SS引腳,由D4(MSTR)位確定器件為主機還是從機,MSTR=1(主機),MSTR=0(從機)。 0:作從機且使用片選線時設為0,同時將D4(MSTR)位設0成為從機,當片選線/SS為低時芯片 選中,可正常通信,當片選線/SS為高時芯片沒選中,不參與通信。 SPEN :SPI使能位。1:使能SPI。0:禁止SPI,所有SPI引腳都作為普通IO口使用。 DORD:設定數據發送和接收的順序。1:低位在前,高位在后。 0:高位在前,低位在后。 MSTR :MSTR=1(主機),MSTR=0(從機)。 CPOL:時鐘極性。1:SPI空閑時,時鐘線為高電平。0:SPI空閑時,時鐘線為低電平。 CPHA:時鐘相位選擇。1:時鐘前沿輸出,后沿采樣。0:時鐘前沿采樣,后沿輸出。 SPR1與SPR0:主機輸出時鐘速率選擇,見下表。
說明:SYS_clk表示CPU運行時鐘,若沒進行分頻設置(默認值),SYS_clk就是內部R/C時鐘 或外部晶振頻率,作為主機方式,上面4種配置方式都可以穩定工作,但建議時鐘頻率一般不 要超過3M,這樣既可增強SPI傳輸穩定性又能減小高頻信號對電路板上其它器件產生干擾。對 于從機,時鐘速率設置無效,它完全是由主機時鐘頻率控制,從機能接受的時鐘頻率要求控 制在SYS_clk/4以內,比如主機和從機都使用內部R/C時鐘33.1776MHZ,主機和從機最高允許 時鐘頻率率33.1776/4≈8.3MHz。
表5-3 SPSTAT狀態寄存器(復位值為00xx xxxxB) 位號 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | 位名稱 | SPIF | WOCL | - | - | - | - | - | - |
SPIF:SPI傳輸完成標志。當一次傳輸完成時,SPIF被置1,此時,如果SPI中斷被打開 (ESPI=1,EA=1),則產生中斷,SPIF標志通過軟件向其寫入1而清零,比如:SPSTAT=0xC0; 執行后SPSTAT=0x00。 WOCL:SPI寫沖突標志。當一個數據還在傳輸,又向數據寄存器SPDAT寫入數據時,WOCL被 置1,WOCL標志通過軟件向其寫入1而清零。 表5-4 SPDAT數據寄存器(復位值為0000 0000B) 位號 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | 位名稱 | MSB |
|
|
|
|
|
| LSB |
位7~0:保存SPI通信數據字節。MSB為最高位,LSB為最低位。例如,主機發送數據: SPDAT=tmpdata; // 將tmpdata變量中的數據發送出去,執行此命令后硬件電路自動輸出 tmpdata變量數據并接收從機數據。 重點說明:如下圖所示,SPDAT是SPI接口內部移位寄存器配備的一個數據緩沖寄存器,其物 理地址與移位寄存器一樣,當對SPDAT進行讀操作時,讀取的是緩沖寄存器中的內容,當對 SPDAT進行寫操作時,數據將被直接寫入移位寄存器并啟動發送過程。 3 SPI接口運用舉例 (1)單主機-單從機通信方式(從機不用片選),硬件電路如圖所示。 程序功能說明: 計算機向主單片機(1號)發送一個字節數據,主單片機的串口每次收到1個字節數據后就立 刻將這個字節通過SPI口發送到從單片機(2號),同時,主單片機收到從單片機發回的一個 字節,并把收到的這個字節通過串口發送到計算機,可使用串口助手觀察實驗結果。 從單片機SPI口收到數據后,把收到的數據(SPDAT中讀出的內容)放到自己的移位寄存器中 (對SPDAT寫入數據),當下一次主單片機發送一個字節過來時把數據發回到主單片機,R/C 時鐘頻率22.1184MHz,計算機串口波特率設置為9600、n、8、1,十六進制發送與接收。
#include "STC15W4K.H" | // | 注意宏定義后面沒分號 | bit SPI_Receive; | // | SPI 端口收到數據標志位 | unsigned char SPI_buffer; | // | 保存SPI端口收到的數據 |
/************************************************************************** - 功能描述:STC15單片機串口1初始化,使用T1方式2自重載方式做波特率發生器 **************************************************************************/ void UART_init(void) // 9600bps@22.1184MHz { // 下面代碼設置定時器1 TMOD |= 0x20; // 0010 0000 定時器1工作于方式2(8位自動重裝方式) TH1 = 0xFA; // 波特率:9600 /22.1184MHZ TL1 = 0xFA; // 波特率:9600 /22.1184MHZ TR1 = 1; // 下面代碼設置定串口 AUXR = 0x00; // 很關鍵,使用定時器1作為波特率發生器,S1ST2=0 SCON = 0x50; // 01010 0000 SM0.SM1=01(最普遍的8位通信),REN=1(允許接受) } void Switch_port() // 根據硬件連接切換端口 { 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口設為準雙向弱上拉方式。 UART_init(); // 初始化串口2C9600bps@22.1184MHz],9600bps@22.1184MHz SPCTL=0xF0; // 主機 (或SPCTL=0xFC; ) Switch_port(); // 端口切換 while(1) // 主循環 { if(RI) // 判串口是否收到數據 { tmpdata=SBUF; // 讀取串口中收到的數據 RI=0; P35=!P35; // 串口接收數據指示燈,調試時觀察串口工作是否正常 SPDAT=tmpdata; // 將數據發送到從機SPI SPI_status=0; while(SPI_status==0) { SPI_status=SPSTAT; // 等待SPIF=1即等待SPI發送完畢 SPI_status=SPI_status&0x80; } SPSTAT=0xC0; // 清0標志位SPIF和WCOL SPI_buffer=SPDAT; // 保存收到的數據 SBUF=SPI_buffer; // 將接收到的數據從串口發送到計算機 while(TI==0); // 等待發送完畢 TI=0; // 清零串口發送中斷標志 } } }
#include "STC15W4K.H" | // | 注意宏定義后面沒分號 | bit SPI_Receive; | // | SPI 端口收到數據標志位 | unsigned char SPI_buffer; | // | 保存SPI端口收到的數據 | void port_mode() {} | // | 端口模式,與主單片機相同 | void main(void) |
|
| { |
|
| port_mode(); | // | 所有IO口設為準雙向弱上拉方式。 | SPCTL=0xE0; | // | 從機 (或SPCTL=0xEC; ) | IE2=IE2|0x02; | // | ESPI(IE2.1)=1,允許SPIF產生中斷 | EA=1; | // | 開總中斷 | SPI_Receive=0; | // | 清標志字 | while(1) | // | 主循環 | { |
|
| if (SPI_Receive) |
| // 判收是否收到主機SPI發來的數據 | { |
|
| SPI_Receive=0; |
| // 清0主單片機SPI端口收到數據標志位 |
SPDAT=SPI_buffer; // 將收到數據送SPDAT,準備下一次通訊時發回 } } } void SPI(void) interrupt 9 { SPSTAT=0xC0; // 清0標志位SPIF和WCOL SPI_buffer=SPDAT; // 保存收到的數據 SPI_Receive=1; // 設置SPI端口收到數據標志 } (2)STC-SPI硬接口(單主單從_從機使用片選)
我們使用片選的目的是要實現多機選擇,如果只有一個從機就沒有必要多使用一條片選線 了,因此程序中在SPI傳輸前打開片選(拉低從機SS),SPI傳輸完成后關閉片選(拉高 從機SS),當然也可以不關閉。只有很少一點代碼與上例不同,如下所示。 sbit P2_4=P2^4; #ifdef MASTER SPCTL=0xf0; // 1111 0000 #else SPCTL=0x60; // 0110 0000 #endif ……… P2_4=0; // 打開從機片選 SPDAT=tmpdata; // SPI 發送數據 …… // 等待SPI發送完畢 P2_4=1; // 關閉從機片選
(3)STC-SPI硬接口(互為主從) 程序功能說明: 1號單片機與2號單片機互為主從,分別通過串口與計算機相連,靜態時2個單片機都設置為 需要片選的從機方式,如果哪個單片機收到計算機發來的數據,就設置為主機方式,拉低/SS 片選線選中從機,并發送數據給從機,主機收到從機的返回數據發計算機,從機收到主機的數 據也發計算機,總體效果是2個計算機串口可以對傳數據。本實驗在硬件上需要2個計算機串 口,串口助手可用STC_ISP打開2個串口助手窗口,R/C時鐘頻率22.1184MHz,波特率為9600、n、 8、1。
完整代碼請參見教材P186-P187。 (4)STC-SPI硬接口(單主多從),硬件電路如圖所示。
•功能與程序請參見教材P188-P190。 |