SPI總線

數據帶寬=(總線頻率×數據位寬)÷8

B表示帶寬,F表示存儲器時鐘頻率,D表示存儲器數據總線位數,則帶寬爲:
B(峯值帶寬)=F(時鐘頻率MHz)×D(總線位數bit)/8
例如,PC-100的SDRAM帶寬計算如下:
100MHz×64bit/8=800MB/S

由於SPI(serial peripheral interface)總線佔用的接口線(4根)少,通信效率高.eg:外接M25P64型號的SPIFLASH時,SPI總線的最大傳輸速率爲75MHz/8=9375KB/S,因爲該SPIFLASH的頻率:75 MHz.普通IIC總線傳輸速率爲10kbps--400kbps.並且SPI支持大部分處理器芯片,因而是一種理想的選擇.

SPI通信是串行發送或接收數據的,即一位一位的發送和接收(按位傳輸),且傳輸一般是高位MSB在前,低位LSB在後.

SPI模式可以允許同時同步發送和接收8位數據,不同於IIC.IIC只有一條數據線,所以IIC每次只能發送數據或傳輸數.SPI是利用4根信號線進行通信的串行同步接口協議,包括主/從兩種模式.4個接口信號爲:串行數據輸入(MISO,主設備輸入、從設備輸出)、串行數據輸出(MOSI,主設備輸出、從設備輸入)、移位時鐘(SCK)、低電平有效的從設備使能信號(CS).SPI最大的特點是由主設備時鐘信號的出現與否來確定主/從設備間的通信(不想傳數據時可採用停止時鐘的方式).一旦檢測到主設備的時鐘信號,數據開始傳輸.

SPI在遠距離傳輸中很少用到,主要因爲其抗干擾能力差,可靠傳輸距離只有1—3m.SPI

採用的是單端非平衡的傳輸方式,即傳輸的數據位的電壓電平是以公共地作爲參考的.在這種傳輸方式中,對於已進入信號中的干擾是無法消除和減弱的.而信號在傳輸過程中總會受到干擾,而且距離越長干擾越嚴重,以致於信號傳輸產生錯誤.在這種條件下,信號傳輸就變得毫無意義了.另外,由於單端非平衡傳輸方式以公共地作爲參考點,地線作爲信號迴流線,因此也存在信號電流.當傳輸線兩端的系統之間存在交流電位差時,這個電位差將直接竄到信號中,形成噪聲干擾.所以,爲了解決抗干擾問題,通常採用平衡傳輸(balanced transmission)方式,這裏採用比較常見的RS-422.

1. SPI器件的主從模式設置

SPI接口的器件,分爲主設備(Master)和從設備(Slave).主設備產生時鐘信號,從設備使用主設備的產生的時鐘.主設備能主動發起數據傳輸.單片機的SPI控制寄存器SPCR中的MSTR位就是用來選擇單片機在傳輸中是作爲主設備還是從設備的.MSTR設爲1時爲主設備,設爲0的時候爲從設備.對單片機來講管腳SS的電平也會影響SPI的工作模式,在主設備模式下,如果SS是輸入且爲低電平那麼MSTR會被清零,設備進入從模式.MISO信號由從機在主機的控制下產生.

下圖是由一個主機對接一個從機進行全雙工通信的系統構成的方式.在該系統中,由於主機和從機的角色是固定不變的,並且只有一個從機,因此,可以將主機的SS端接高電平,將從機的SS端固定接地.

下圖是一個主機和多個從器件的通信系統.各個從器件是單片機的外圍擴展芯片,它們的片選端SS分別獨佔單片機的一條通用I/O引腳,由單片機分時選通它們建立通信.這樣省去了單片機在通信線路上發送地址碼的麻煩,但是佔用了單片機的引腳資源.當外設器件只有一個時,可以不必選通而直接將SS端接地即可.

採用由三個單片機互相連接構成多主機通信系統連接方法如下:

2. SPI器件的時鐘極性和相位設置

所有的SPI設備都採用相同的接口方式,可以通過調整處理器內部寄存器改變時鐘的極性和相位.由於SPI器件並不一定遵循同一標準,比如EEPROM、DAC、ADC、實時時鐘及溫度傳感器等器件的SPI接口的時序都有所不同,爲了能夠滿足不同的接口需要,採用時鐘的極性和相位可配就能夠調整SPI的通信時序.

SPI主機與之通信的從機的時鐘極性和相位應該一致.可以先看看另一篇博文,專門講解了時鐘極性和相位:http://www.cnblogs.com/jason-lu/articles/3713319.html

SPI數據傳輸的模式根據時鐘的極性和相位有四種組合,這就是四種不同的傳輸模式.分別稱爲模式0,模式1,模式2,模式3.有的SPI接口的器件只支持幾種模式,比如SPI接口的EEPROMAT25128可以工作於模式0和模式3.在實際使用中需要設置爲和外圍器件兼容的模式.

設置舉例:

M25P64數據手冊上給出的時鐘的極性和相位和數據讀寫的對應的時序

如上圖所示:

時鐘極性和相位都是0時,上升沿爲前沿,數據穩定被採樣(鎖存),下降沿爲後沿,被寫入SPI總線.

時鐘極性和相位都是1時,上升沿爲後沿,數據穩定被採樣(鎖存),下降沿爲前沿,被寫入SPI總線.

和M25P64數據手冊上給出的時鐘的極性和相位和數據讀寫的對應的時序匹配的omapl138數據手冊上給出的時序

注:

  • 從機對時序的響應和主機對時序的響應相同但要比主機反應遲鈍
  • 圖30-9和圖30-10的區別:雖都表示時序上是下降沿寫上升沿讀,但30-10表示片選一拉低數據就被寫出,而30-9表示當片選拉低後還要等時鐘的下降沿來臨數據才被寫出.
  • 數據在上升沿被鎖存

所以對應的程序:

//SPIFMT0寄存器 bit 8-15 是配置時鐘頻率,bit16是時鐘延時,bit17是時鐘極性(在高電平觸發還是低電平觸發)
SPI1->SPIFMT0 = 0x00020608;//startware配置
//SPI1->SPIFMT0 = 0x00010208;(ok logicpd配置)

3. SPI的傳輸原理

SPI設備傳輸數據過程中總是先發送或接收高字節數據,每個時鐘週期接收器或收發器左移

1位數據(SPI總線是按位傳輸的).對於小於16位的數據在發送之前必須左對齊,如果接收的數據小於16位則採用軟件將無效的數據位屏蔽,如圖1所示.對應的C代碼:

主機和從機都有一個串行移位寄存器,主機通過向它的SPI串行寄存器寫入一個字節來發起一次傳輸.主機的移位寄存器通過MOSI信號線將字節傳送給從機的移位寄存器,從機也將自己的移位寄存器中的內容通過MISO信號線返回給主機的移位寄存器中(如下圖所示).這樣,兩個移位寄存器中的內容就被交換.外設的寫操作和讀操作是同步完成的.

如果只進行寫操作,主機只需忽略接收到的字節;當然,若主機要讀取從機的一個字節,則應該發送一個空字節來引發從機的傳輸.

SPI的傳輸實際上相當於兩個八位移位寄存器首位相連.每個時鐘週期,數據從一個設備的移位寄存器移出,同時移入了另一個寄存器.八位數據全部移出時,兩個寄存器就實現了一次數據交換.因此,SPI的發送和接收是同時進行的,實際都是發送一個字節發起的,只不過需要接收的時候發送的是一個我們不關心的任意字節.

4. SPI傳輸示例編程

當主機發送一個連續的數據流時,有些外設能夠進行多字節傳輸.多數具有SPI接口的存儲芯片就以這種方式工作.在這種傳輸方式下,從機的片選端必須在整個傳輸過程中保持低電平.此時,一次傳輸可能會涉及到成千上萬字節的信息,而不必在每個字節的數據發送的前後都去檢測其起始位和結束位(片選拉低開始,片選拉高結束),這正是同步傳輸方式優於異步傳輸方式的原因所在.

針對外設是M25P64 外設的SPI的傳輸

方式:命令字(一個字節)+FLASH的地址(三個字節)+要發送或接收的數據(n個字節)

複製代碼
/* Send read command to the flash (one byte) */
tx_data =  0x03; //SPI_FLASH_READ,這是單字節指令代碼
SpiTransfer(&tx_data, &rx_data, 1);

/* Send the address to start reading from (3 bytes) ,共24位*/
addr[0] = (unsigned char)(flashAddr >> 16);
addr[1] = (unsigned char)(flashAddr >> 8);
addr[2] = (unsigned char)flashAddr;

len = 0;
while (len < sizeof(addr))
{
    SpiTransfer(&addr[len], &rx_data, 1);
    len++;
}

/* Read all the bytes */
len = 0;
while(len < size)
{
    SpiTransfer(&tx_data, destAddr, 1);
    destAddr++;//共20個字節,一個字節一個字節放入
    len++;
}
複製代碼

命令字:

複製代碼
// numonyx spi flash commands.
#define NUMONYX_CMD_WREN            (0x06)
#define NUMONYX_CMD_WRDI            (0x04)
#define NUMONYX_CMD_RDID            (0x9F)
#define NUMONYX_CMD_RDSR            (0x05)
#define NUMONYX_CMD_WRSR            (0x01)
#define NUMONYX_CMD_READ            (0x03)
#define NUMONYX_CMD_FAST_READ       (0x0B)
#define NUMONYX_CMD_PAGE_PROG       (0x02)
#define NUMONYX_CMD_SEC_ERASE       (0xD8)
#define NUMONYX_CMD_BULK_ERASE      (0xC7)
#define NUMONYX_CMD_RD_ELEC_SIG     (0xAB)
複製代碼

本文爲網友熱心整理,本人純屬拿來主義.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章