SPI介紹+軟件模擬SPI


1.什么是SPI

 SPI通常有一個主設備和一個或多個從設備,通常采用的是4根線,它們是MISO(數據輸入,針對主機來說)、MOSI(數據輸出,針對主機來說)、SCLK(時鍾,主機產生)、CS/SS(片選,一般由主機發送或者直接使能,通常為低電平有效)。全雙工。

2.SPI物理層

 

圖1 SPI物理層連接圖

 一個主機可以連接多個從機,其中SCK,MOSI,MISO所有從機共用。SSx單獨連接主機。當主機需要和從機通信時,主機把對應的從機的SSx線拉低。從機發現自己的SSx線被拉低,則表示主機要和它通信了。對比IIC,SPI不需要外接上拉電阻,也不需要廣播地址來尋機。

3.SPI協議層

圖2 SPI 協議層信號

 

 SPI只有開始信號,停止信號,和數據有效性信號,讀寫信號(同步的)。相比IIC,少了應答機制。

(1)開始信號:NSS被拉低的下降沿(SSx、CS。都叫做使能線,片選線。叫法很多,作用一樣 都是讓從機使能通信)

(2)停止信號:NSS被拉高的上升沿。

(3)觸發,轉移,一樣的意思。表示主機讀一位從機的數據,從機讀一位主機的數據。

(4)采樣,采集,讀取,一樣的意思,表示總線的上數據已就緒,可以讀了。采樣后,MISO、MOSI線上的數據被鎖存直到被轉移。

4.SPI的4種模式

4.1.極性和相位組合成4種模式

 要說SPI的4種模式,就要先說一下兩個概念:時鍾極性CPOL和時鍾相位CPHA。CPOL和CPHA均有0 1兩種狀態,組合成4種狀態。

時鍾極性:時鍾極性 CPOL 是指 SPI 通訊設備處於空閑狀態時,SCK 信號線的電平信號(SPI 通訊開始前、 NSS 線為高電平時 SCK 的狀態)

       CPOL=0 時, SCK 在空閑狀態時為低電平①,在SCK有效期間為高電平 ②

       CPOL=1 時,SCK 在空閑狀態時為高電平③,在SCK有效期間為低電平 ④
                      

 

圖3 時鍾極性規定的空閑狀態的電平

 時鍾相位:時鍾相位 CPHA 是指數據的采樣的時刻,

       當 CPHA=0 時, MOSI MISO 數據線上的信號將會在 SCK 時鍾線的“奇數邊沿” 被采樣。

                   當 CPHA=1 時,數據線在 SCK 的“偶數邊沿” 采樣。

                    

圖4 時鍾相位CPHA = 0時

  當 CPHA=0 時, MOSI 或 MISO 數據線上的信號將會在 SCK 時鍾線的“奇數邊沿” 被采樣。根據時鍾極性的不同,奇數邊沿可能是上升沿也可能是下降沿。

  可以看到,采集數據是邊沿觸發的,且沒有明確要求是上升沿還是下降沿。CPHA=0時,采集數據是在奇數邊沿,則轉換數據是在偶數邊沿。

                  

 

   圖5 時鍾相位 CPHA = 1時

當 CPHA=1時, MOSI 或 MISO 數據線上的信號將會在 SCK 時鍾線的“偶數邊沿” 被采樣。根據時鍾極性的不同,奇數邊沿可能是上升沿也可能是下降沿。

可以看到 CPHA=1時,采集數據是在偶數邊沿,則轉換數據是在奇數邊沿。

關於幾個關鍵詞的描述:

(1)采集、采樣:當采樣時,主機要發給從機的數據已經在MOSI上了,從機要發送給主機的數據已經在MISO上了。可以去讀取了。(什么時候准備數據的,下面說)

(2)轉換:因為SPI是全雙工的,可以同時收發數據。主機在發送出一位數據,就會接收到一位數據。在同一個時鍾周期同步轉換。

         為什么叫轉換?從下面圖6中看到,兩個設備都有一個shift寄存器。比如當CPHA=0時,在第一個邊沿采集到了數據,在第二個邊沿轉換,

        主機的shift寄存器的最高位移到了從機的shift寄存器的最低位。兩個寄存器都左移,循環8次。就能完成8位數據的交換,主機shift寄存器的數據都移到從記得shift寄存器里面了。從機的也都移到主機里了。(很巧妙 用互相轉移完成讀寫同步)

               

 

圖6 shift register

 

4.2.為什么需要4種模式 以及什么時候采集數據,什么時候發送數據

模式0:CPOL=0,CPHA =0  SCK空閑為低電平,數據在SCK的上升沿被采樣(提取數據)

模式1:CPOL=0,CPHA =1  SCK空閑為低電平,數據在SCK的下降沿被采樣(提取數據)

模式2:CPOL=1,CPHA =0  SCK空閑為高電平,數據在SCK的下降沿被采樣(提取數據)

模式3:CPOL=1,CPHA =1  SCK空閑為高電平,數據在SCK的上升沿被采樣(提取數據)

簡單;來說就是有些外設在被選中后(CS被拉低)就會把數據放到總線上,讓主機區讀。這個時候用CPHA=0模式。而有些在設備發送數據前需要一個SCK時鍾來激活外設,外設在接收到第一個始終后才會把數據放到總線上。這個時候用CPHA=1模式。

CPHA=0時:主機從機給總線上准備數據,讀寫,轉移的過程(從摩托羅拉SPI協議4.4.2 翻譯過來的,大概翻譯,不完全)

           

(1)時鍾的第一個邊沿發生時,MOSI、MISO上的數據將被采集並被鎖存,在第一個時鍾邊沿發生之前,必須有個CS被拉低的信號(設備必須使能),從CS被拉低。到第一個時鍾邊沿發生,需要有個延時。為什么需要延時?因為在CS被拉低到出現第一個邊沿這個過程中,被使能的從機設備將會把自己的數據放在MISO上讓主機去讀。主機把自己的數據放在MOSI上讓從機去讀。

(2)當時鍾的第二個邊沿發生時,MISO、MOSI上被采集並鎖存的數據將會轉移。(交換一位,參考圖6)

(3)第二個時鍾沿發生后,從機的下一位數據將會被發送到MISO上,主機上,我們需要主動把數據放在MOSI上。這個也就是說的在奇數邊沿采集,在偶數邊沿轉移。我們可以看到發送8位數據,需要8個時鍾周期,16個時鍾邊沿。

(4)在第16個時鍾邊沿發生后,主機的shift寄存器和從機的shift寄存器的數據就完全交換了。

 

CPHA=1時:主機從機給總線上准備數據,讀寫,轉移的過程(從摩托羅拉SPI協議4.4.3 翻譯過來的,大概翻譯,不完全)

        

 

 

 

 (1)在奇數數邊沿轉移,在偶數邊沿采集。按照權威的文檔中說,有些設備需要得到一個時鍾后才會把數據放到MISO線上。不像上面介紹的設備一旦CS選中就發數據。

 (2)這種設備在第一個邊沿先轉移一下,用來激活設備,設備才會把數據放到MISO線上。在第二個邊沿采集,又回到第一個邊沿轉移,設備准備數據到MISO上,第二個邊沿采集,循環。

這里還有點疑惑。先記錄一下吧。是不是只第一次讀取從設備的數據時需要一個時鍾激活,激活后,一旦發生轉移,從設備的下一位數據就自動就緒了。可能是第一個時鍾轉移(激活),轉移后自動准備下一位數據。我覺得可能是第二種,只要一個時鍾激活就可以了。第一個時鍾激活,第一個時鍾轉移,那轉移一次數據,從設備就會被激活。

    

4.3 什么時候用哪種模式?

時鍾相位CPHA = 0。這種模式適合那種從設備一旦被片選后就輸出數據到MISO線上。

時鍾相位CPHA = 0。這種模式適合那種從設備被片選后還需要一個時鍾才能 輸出數據到MISO線上。

4.4軟件模擬

轉自內陸的咸水魚

  1 /* CPOL = 0, CPHA = 0, MSB first */
  2 uint8_t SOFT_SPI_RW_MODE0( uint8_t write_dat )
  3 {
  4     uint8_t i, read_dat;
  5     for( i = 0; i < 8; i++ )
  6     {
  7         if( write_dat & 0x80 )
  8             MOSI_H;  
  9         else                    
 10             MOSI_L;  
 11         write_dat <<= 1;
 12         delay_us(1);    
 13         SCK_H; 
 14         read_dat <<= 1;  
 15         if( MISO ) 
 16             read_dat++; 
 17         delay_us(1);
 18         SCK_L; 
 19         __nop();
 20     }
 21     
 22     return read_dat;
 23 }
 24  
 25  
 26 /* CPOL=0,CPHA=1, MSB first */
 27 uint8_t SOFT_SPI_RW_MODE1(uint8_t byte) 
 28 {
 29     uint8_t i,Temp=0;
 30  
 31     for(i=0;i<8;i++)     // 循環8次
 32     {
 33         SCK_H;     //拉高時鍾
 34         if(byte&0x80)
 35         {
 36             MOSI_H;  //若最到位為高,則輸出高
 37         }
 38         else      
 39         {
 40             MOSI_L;   //若最到位為低,則輸出低
 41         }
 42         byte <<= 1;     // 低一位移位到最高位
 43         delay_us(1);
 44         SCK_L;     //拉低時鍾
 45         Temp <<= 1;     //數據左移
 46  
 47         if(MISO)
 48             Temp++;     //若從從機接收到高電平,數據自加一
 49         delay_us(1);
 50  
 51     }
 52     return (Temp);     //返回數據
 53 }
 54  
 55 /* CPOL=1,CPHA=0, MSB first */
 56 uint8_t SOFT_SPI_RW_MODE2(uint8_t byte) 
 57 {
 58     uint8_t i,Temp=0;
 59  
 60     for(i=0;i<8;i++)     // 循環8次
 61     {
 62         if(byte&0x80)
 63         {
 64             MOSI_H;  //若最到位為高,則輸出高
 65         }
 66         else      
 67         {
 68             MOSI_L;   //若最到位為低,則輸出低
 69         }
 70         byte <<= 1;     // 低一位移位到最高位
 71         delay_us(1);
 72         SCK_L;     //拉低時鍾
 73         Temp <<= 1;     //數據左移
 74  
 75         if(MISO)
 76             Temp++;     //若從從機接收到高電平,數據自加一
 77         delay_us(1);
 78         SCK_H;     //拉高時鍾
 79         
 80     }
 81     return (Temp);     //返回數據
 82 }
 83  
 84  
 85 /* CPOL = 1, CPHA = 1, MSB first */
 86 uint8_t SOFT_SPI_RW_MODE3( uint8_t write_dat )
 87 {
 88     uint8_t i, read_dat;
 89     for( i = 0; i < 8; i++ )
 90     {
 91         SCK_L; 
 92         if( write_dat & 0x80 )
 93             MOSI_H;  
 94         else                    
 95             MOSI_L;  
 96         write_dat <<= 1;
 97         delay_us(1);    
 98         SCK_H; 
 99         read_dat <<= 1;  
100         if( MISO ) 
101             read_dat++; 
102         delay_us(1);
103         __nop();
104     }
105     return read_dat;
106 }
107  

 

 

參考資料

文中圖片來自野火資料

軟件模擬SPI接口程序代碼(4種模式) https://blog.csdn.net/zwj695535100/article/details/107303648/

摩托羅拉SPI總線協議規范  https://wenku.baidu.com/view/eb052d1289eb172dec63b700.html(4.4章節)

https://www.cnblogs.com/fedorayang/p/8564792.html

https://www.sohu.com/a/270796067_288206


免責聲明!

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



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