1. 程式人生 > >SPI讀寫總結

SPI讀寫總結

SPI協議是主從模式:從機不主動發起訪問,總是被動執行操作。
CSN:片選訊號。
SCK:時鐘訊號。
MOSI:master output slave input,即主機輸出從機輸入。可以理解主機寫從裝置。
MISO:master input slave output,即主機輸入從機輸出。可以理解主機讀從裝置。

SPI全稱:Serial Peripheral interface,即序列外圍裝置介面。SPI協議自然是序列地傳輸資料,每次
按 1 bit讀寫裝置,而不是像並行每次1byte(8bit)傳輸。

nRF24L01支援標準SPI四線介面。以nRF24L01晶片的PDF為例說明SPI的基本讀寫。
20788517_1322727043Pt8e.jpg20788517_1322727047U2GK.jpg

如圖示為SPI讀時序和寫時序。按照讀寫時序輸出位元組(MOSI)就會從MSB 迴圈輸出,同將輸入位元組(MISO)從LSB 迴圈移入,每次移動一位。

顯然對於nRF24L01來說上升沿輸入,下降沿輸出。也即是說:MCU在時鐘訊號的上升沿時寫(write),下降沿時讀(read).


單位元組讀時序:
  1. /*
  2. ** 函式名 : SPI_Read_OneByte
  3. ** 返回值 : temp--SPI讀取的一位元組資料
  4. ** 參  數 : None
  5. ** 描  述 : 下降沿讀資料,每次讀取 1 bit
  6. */
  7. uint8 SPI_Read_OneByte(void)
  8. {
  9.   uint8 i;
  10.   uint8 temp = 0;
  11.   for(i=0;i<8;i++)
  12.   {
  13.    temp <<= 1;       //讀取MISO 8次輸入的值,存入temp。之所以不放在“SCK = 0”語句之後的位置是因為:
  14.                      /
    /讀取最後1byte的最後一位(即LSB)之後,不能再左移了
  15.    SCK = 1;         
  16.    if(MISO)          //讀取最高位,儲存至最末尾,通過左移位完成讀整個位元組
  17.      temp |= 0x01;
  18.     else
  19.      temp &= ~0x01;
  20.    SCK = 0;          //下降沿來了(SCK從1-->0),MISO上的資料將發生改變,穩定後讀取存入temp
  21.   }
  22.   return temp;
  23. }
單位元組寫時序:
  1. /*
  2. ** 函式名 : SPI_Write_OneByte
  3. ** 返回值 : None
  4. ** 參  數 :
    u8_writedata--SPI寫入的一位元組資料
  5. ** 描  述 : 上升沿寫資料,每次寫入 1 bit
  6. */
  7. void SPI_Write_OneByte(uint8 u8_writedata)
  8. {
  9.   uint8 i;
  10.   for(i=0;i<8;i++)
  11.   {
  12.     if(u8_writedata & 0x80)      //判斷最高位,總是傳送最高位
  13.      MOSI_ON;                    //MOSI輸出1,資料匯流排準備資料1
  14.     else
  15.      MOSI_OFF;                   //MOSI輸出0,資料匯流排準備資料0
  16.     SCK = 1;                     //上升沿來了(SCK從0-->1),資料匯流排上的資料寫入到器件
  17.     u8_writedata <<= 1;          //左移拋棄已經輸出的最高位
  18.     SCK = 0;                     //拉低SCK訊號,初始化為0
  19.   }
  20. }
在此基礎可以寫出nRF24L01暫存器的讀寫函式。
nRF24L01暫存器寫入函式:
  1. /*
  2. ** 函式名: nRF24L01_WriteReg
  3. ** 返回值: None
  4. ** 參 數 : (1)uint8 addr--暫存器地址
  5. **         (2)uint8 value--寫入值
  6. ** 說 明 : nRF24L01暫存器寫函式
  7. */
  8. void nRF24L01_WriteReg(uint8 addr, uint8 value)
  9. {
  10.     CSN_OFF();                  //CS片選拉低
  11.     SPI_Write_OneByte(addr|WR); //SPI寫地址命令
  12.     SPI_Write_OneByte(value);   //SPI寫資料
  13.     CSN_ON();                   //CS片選拉高
  14. }
nRF24L01讀暫存器函式:
  1. /*
  2. ** 函式名: nRF24L01_ReadReg
  3. ** 返回值: value--讀取暫存器值
  4. ** 參 數 : addr--暫存器地址
  5. ** 說 明 : nRF24L01暫存器讀函式
  6. */
  7. uint8 nRF24L01_ReadReg(uint8 addr)
  8. {
  9.     uint8 value;
  10.     CSN_OFF();                   //CS片選拉低
  11.     SPI_Write_OneByte(addr|RR);  //SPI寫地址命令
  12.     value = SPI_Read_OneByte();  //SPI讀資料
  13.     CSN_ON();                    //CS片選拉高
  14.     return value;
  15. }

注:可以整合讀寫程式如下:


  1. /*
  2. ** 函式名 : SPI_WriteAndRead_OneByte
  3. ** 返回值 : u8_readdata--SPI讀取的一位元組資料
  4. ** 參 數 : u8_writedata--SPI寫入的一位元組資料
  5. ** 描 述 : 上升沿寫,下降沿讀
  6. */
  7. uint8 SPI_WriteAndRead_OneByte(uint8 u8_writedata)
  8. {
  9.   uint8 i;
  10.   uint8 u8_readdata = 0x00;
  11.   for(i=0;i<8;i++)
  12.   {
  13.     u8_readdata <<= 1;      //讀取MISO 8次輸入的值,存入u8_readdata。
  14.     if(u8_writedata & 0x80) //判斷最高位,總是寫最高位(輸出最高位)
  15.       MOSI_ON;              //MOSI輸出1,資料匯流排準備資料1
  16.     else
  17.       MOSI_OFF;             //MOSI輸出0,資料匯流排準備資料0
  18.     u8_writedata <<= 1;     //左移拋棄已經輸出的最高位
  19.     SCK = 1;                //上升沿來了(SCK從0-->1),資料匯流排上的資料寫入器件
  20.     if(MISO)                //讀取最高位,儲存至最末尾,通過左移位完成讀整個位元組
  21.       u8_readdata |= 0x01;
  22.     else
  23.       u8_readdata &= ~0x01;
  24.     SCK = 0;                //下降沿來了(SCK從1-->0),MISO上將產生新的資料,讀取存入u8——readdata
  25.    }
  26.   return u8_readdata;
  27. }

Freedomxura原創,歡迎指正與轉載,請註明出處,http://xurafreedom.cublog.cn

<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script> 閱讀(1) | 評論(0) | 轉發(0) | 給主人留下些什麼吧!~~ 評論熱議