SPI通信協議(SPI總線)學習


SPI是串行外設接口(Serial Peripheral Interface)的縮寫。是 Motorola 公司推出的一
種同步串行接口技術,是一種高速的,全雙工,同步的通信總線。

支持全雙工通信
通信簡單
數據傳輸速率塊
沒有指定的流控制,沒有應答機制確認是否接收到數據,

所以跟IIC總線協議比較在數據可靠性上有一定的缺陷

1):高速、同步、全雙工、非差分、總線式

2):主從機通信模式

1):SPI的通信原理很簡單,它以主從方式工作,這種模式通常有一個主設備和一個或多
個從設備,需要至少4根線,事實上3根也可以(單向傳輸時)。也是所有基於SPI的設備共
有的,它們是SDI(數據輸入)、SDO(數據輸出)、SCLK(時鍾)、CS(片選)。
(1)SDO/MOSI – 主設備數據輸出,從設備數據輸入;
(2)SDI/MISO – 主設備數據輸入,從設備數據輸出;
(3)SCLK – 時鍾信號,由主設備產生;
(4)CS/SS – 從設備使能信號,由主設備控制。當有多個從設備的時候,因為每個從設
備上都有一個片選引腳接入到主設備機中,當我們的主設備和某個從設備通信時將需
要將從設備對應的片選引腳電平拉低或者是拉高。

2):需要說明的是,我們SPI通信有4種不同的模式,不同的從設備可能在出廠是就是配
置為某種模式,這是不能改變的;但我們的通信雙方必須是工作在同一模式下,所以我們
可以對我們的主設備的SPI模式進行配置,通過CPOL(時鍾極性)和CPHA(時鍾相位)來
控制我們主設備的通信模式,具體如下:
Mode0:CPOL=0,CPHA=0
Mode1:CPOL=0,CPHA=1
Mode2:CPOL=1,CPHA=0
Mode3:CPOL=1,CPHA=1

時鍾極性CPOL是用來配置SCLK的電平出於哪種狀態時是空閑態或者有效態,時鍾相位CPHA
是用來配置數據采樣是在第幾個邊沿:

CPOL=0,表示當SCLK=0時處於空閑態,所以有效狀態就是SCLK處於高電平時
CPOL=1,表示當SCLK=1時處於空閑態,所以有效狀態就是SCLK處於低電平時
CPHA=0,表示數據采樣是在第1個邊沿,數據發送在第2個邊沿
CPHA=1,表示數據采樣是在第2個邊沿,數據發送在第1個邊沿

例如:

 

 

CPOL=0,CPHA=0:此時空閑態時,SCLK處於低電平,數據采樣是在第1個邊沿,也就是

SCLK由低電平到高電平的跳變,所以數據采樣是在上升沿(准備數據),(發送數據)數據發送是在下降沿。

CPOL=0,CPHA=1:此時空閑態時,SCLK處於低電平,數據發送是在第1個邊沿,也就是
SCLK由低電平到高電平的跳變,所以數據采樣是在下降沿,數據發送是在上升沿。
CPOL=1,CPHA=0:此時空閑態時,SCLK處於高電平,數據采集是在第1個邊沿,也就是
SCLK由高電平到低電平的跳變,所以數據采集是在下降沿,數據發送是在上升沿。
CPOL=1,CPHA=1:此時空閑態時,SCLK處於高電平,數據發送是在第1個邊沿,也就是
SCLK由高電平到低電平的跳變,所以數據采集是在上升沿,數據發送是在下降沿。

模式1
 1 /*
 2 函數功能:模擬SPI總線發送並且接收一個字節
 3 函數形參:需要發送的數據
 4 函數返回值:接收道的結果
 5 備注:通信速度:100MHz
 6 */
 7 u8 spi_send_and_recive_byte(u8 send_byte_data)
 8 {
 9     u8 recive_byte_data = 0;
10     u8 value = 0;
11     
12     //下降沿准備數據;上升沿發送並且接收數據
13     for(value = 0; value < 8; value++)
14     {
15         CLK = 0;//讓主從設備准備數據
16         if(send_byte_data & (0x80 >> value))
17         {
18             MOSI = 1;
19         }
20         else
21         {
22             MOSI = 0;
23         }
24         CLK = 1;//讓主從設備發送並且接收數據
25         recive_byte_data <<= 1;
26         recive_byte_data |= MISO;
27     }
28     
29 }
View Code

 

需要注意的是:我們的主設備能夠控制時鍾,因為我們的SPI通信並不像UART或者IIC通信
那樣有專門的通信周期,有專門的通信起始信號,有專門的通信結束信號;所以我們的
SPI協議能夠通過控制時鍾信號線,當沒有數據交流的時候我們的時鍾線要么是
保持高電平要么是保持低電平。

最后,再附上用IO口來模擬的四種SPI模式程序,僅作參考理解用,還要根據實際情況改寫,如下:

 1 //表示相關引腳高低電平,要根據實際引腳修改。
 2 SSEL_D(0) SSEL_D(1)  //片選
 3 SCK_D(0)  SCK_D(1)     //時鍾信號
 4 MOSI_D(0) MOSI_D(1)   //SDO
 5 MISO_I(0) MISO_I(1)       //SDI
 6 #define _CPOL     1  //時鍾極性
 7 #define _CPHA     0  //時鍾相位
 8 //延時子程序
 9 void delay()
10 unsigned char m,n;
11    for(n=0;n<5;n++);
12   for(m=0;m<100;m++);
13 /**********************************************
14 ***********************************************/
頭部
 1 #if _CPOL==0&&_CPHA==0          //MODE   0  0 
 2 void SPI_Send_Dat(unsigned char dat)
 3 unsigned char n;
 4 for(n=0;n<8;n++)
 5 SCK_D(0);
 6 if(dat&0x80)MOSI_D(1);
 7 else MOSI_D(0);
 8 dat<<=1;
 9 SCK_D(1);
10 SCK_D(0);
11 /*********************************************
12 *********************************************/
13 unsigned char SPI_Receiver_Dat(void)
14 unsigned char n ,dat,bit_t;
15 for(n=0;n<8;n++)
16 SCK_D(0);
17 dat<<=1;
18 if(MISO_I())dat|=0x01;
19 else dat&=0xfe;
20 SCK_D(1);
21 SCK_D(0);
22 return dat;
23 #endif
24 /*********************************************
25 *********************************************/
模式0
 1 #if _CPOL==0&&_CPHA==1           //MODE  0  1(上升沿准備,下降沿發送)
 2 void SPI_Send_Dat(unsigned char dat)
 3 unsigned char n;
 4 SCK_D(0);
 5 for(n=0;n<8;n++)
 6 SCK_D(1);
 7 if(dat&0x80)MOSI_D(1);
 8 else MOSI_D(0);
 9 dat<<=1;
10 SCK_D(0);
11 /*********************************************
12 *********************************************/
13 unsigned char SPI_Receiver_Dat(void)
14 unsigned char n ,dat,bit_t;
15 for(n=0;n<8;n++)
16 SCK_D(1);
17  dat<<=1;
18 if(MISO_I())dat|=0x01;
19 else dat&=0xfe;
20 SCK_D(0);
21 SCK_D(0);
22 return dat;
23 #endif
24 /**********************************************
25 ***********************************************/
模式1
 1 #if _CPOL==1&&_CPHA==0           //MODE   1  0
 2 void SPI_Send_Dat(unsigned char dat)
 3 unsigned char n;
 4 for(n=0;n<8;n++)
 5 SCK_D(1);
 6 if(dat&0x80)MOSI_D(1);
 7 else MOSI_D(0);
 8 dat<<=1;
 9 SCK_D(0);
10 SCK_D(1);
11 /*********************************************
12 *********************************************/
13 unsigned char SPI_Receiver_Dat(void)
14 unsigned char n ,dat,bit_t;
15 for(n=0;n<8;n++)
16 SCK_D(1);
17 dat<<=1;
18 if(MISO_I())dat|=0x01;
19 else dat&=0xfe;
20 SCK_D(0);
21 SCK_D(1);
22 return dat;
23 #endif
24 /**********************************************
25 ***********************************************/
模式2
 1 #if _CPOL==1&&_CPHA==1            //MODE  1  1
 2 void SPI_Send_Dat(unsigned char dat)
 3 unsigned char n;
 4 SCK_D(1);
 5 for(n=0;n<8;n++)
 6 SCK_D(0);
 7 if(dat&0x80)MOSI_D(1);
 8 else MOSI_D(0);
 9 dat<<=1;
10 SCK_D(1);
11 /************************************
12 ************************************/
13 unsigned char SPI_Receiver_Dat(void)
14 unsigned char n ,dat,bit_t;
15 SCK_D(0);
16 for(n=0;n<8;n++)
17 { SCK_D(0);
18 dat<<=1;
19 if(MISO_I())dat|=0x01;
20 else dat&=0xfe;
21 SCK_D(1);
22 SCK_D(1);
23 return dat;
24 #endif
模式3

 


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM