SPI基本知識
SPI:高速同步串行口。是一種標准的四線同步雙向串行總線。
SPI,是英語Serial Peripheral interface的縮寫,顧名思義就是串行外圍設備接口。是Motorola首先在其MC68HCXX系列處理器上定義的。SPI接口主要應用在 EEPROM,FLASH,實時時鍾,AD轉換器,還有數字信號處理器和數字信號解碼器之間。SPI,是一種高速的,全雙工,同步的通信總線,並且在芯片的管腳上只占用四根線,節約了芯片的管腳,同時為PCB的布局上節省空間,提供方便,正是出於這種簡單易用的特性,如今越來越多的芯片集成了這種通信協議,比如AT91RM9200。
SPI總線系統是一種同步串行外設接口,它可以使MCU與各種外圍設備以串行方式進行通信以交換信息。外圍設置FLASHRAM、網絡控制器、LCD顯示驅動器、A/D轉換器和MCU等。SPI總線系統可直接與各個廠家生產的多種標准外圍器件直接接口,該接口一般使用4條線:串行時鍾線(SCLK)、主機輸入/從機輸出數據線MISO、主機輸出/從機輸入數據線MOSI和低電平有效的從機選擇線SS(有的SPI接口芯片帶有中斷信號線INT、有的SPI接口芯片沒有主機輸出/從機輸入數據線MOSI)。
SPI的通信原理很簡單,它以主從方式工作,這種模式通常有一個主設備和一個或多個從設備,需要至少4根線,事實上3根也可以(用於單向傳輸時,也就是半雙工方式)。也是所有基於SPI的設備共有的,它們是SDI(數據輸入)、SDO(數據輸出)、SCLK(時鍾)、CS(片選)。
MOSI–SPI總線主機輸出/ 從機輸入(SPI Bus Master Output/Slave Input);
MISO–SPI總線主機輸入/ 從機輸出(SPI Bus Master Input/Slave Output);
SCLK–時鍾信號,由主設備產生;
CS–從設備使能信號,由主設備控制(Chip select),有的IC此pin腳叫SS。
其中CS是控制芯片是否被選中的,也就是說只有片選信號為預先規定的使能信號時(高電位或低電位),對此芯片的操作才有效。這就允許在同一總線上連接多個SPI設備成為可能。
3根線MOSI,MISO,SCLK負責通訊。通訊是通過數據交換完成的,SPI是串行通訊協議,也就是說數據是一位一位的傳輸的。由SCK提供時鍾脈沖,SDI,SDO則基於此脈沖完成數據傳輸,這就是SCLK時鍾線存在的原因。數據輸出通過 SDO線,數據在時鍾上升沿或下降沿時改變,在緊接着的下降沿或上升沿被讀取。完成一位數據傳輸,輸入也使用同樣原理。這樣,在至少8次時鍾信號的改變(上沿和下沿為1次),就可以完成8位數據的傳輸。
在點對點的通信中,SPI接口不需要進行尋址操作,且為全雙工通信,簡單高效。在多個從設備的系統中,每個從設備需要獨立的使能信號,硬件上比I2C要稍微復雜。
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用來配置數據采樣是在第幾個SCLK脈沖邊沿:
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由高電平到低電平的跳變,所以數據采集是在上升沿,數據發送是在下降沿。
SPI庫函數
SPISettings 配置SPI總線端口
Description 描述
The SPISettings object is used to configure the SPI port for your SPI device. All 3 parameters are combined to a single SPISettings object, which is given to SPI.beginTransaction().
When all of your settings are constants, SPISettings should be used directly in SPI.beginTransaction(). See the syntax section below. For constants, this syntax results in smaller and faster code.
If any of your settings are variables, you may create a SPISettings object to hold the 3 settings. Then you can give the object name to SPI.beginTransaction(). Creating a named SPISettings object may be more efficient when your settings are not constants, especially if the maximum speed is a variable computed or configured, rather than a number you type directly into your sketch.
Syntax 語法
SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE0))
Note:Best if all 3 settings are constants
SPISettings mySettting(speedMaximum, dataOrder, dataMode)
Note:Best when any setting is a variable''
Parameters 參數
speedMaximum: The maximum speed of communication. For a SPI chip rated up to 20 MHz, use 20000000.
dataOrder: MSBFIRST or LSBFIRST
dataMode : SPI_MODE0, SPI_MODE1, SPI_MODE2, or SPI_MODE3 四種數據傳送模式
Returns None 返回
begin() 初始化SPI總線的參數
Description
Initializes the SPI bus by setting SCK, MOSI, and SS to outputs, pulling SCK and MOSI low, and SS high.
Syntax SPI.begin()
Parameters None
Returns None
end() 關閉SPI總線
Description
Disables the SPI bus (leaving pin modes unchanged).
Syntax SPI.end()
Parameters None
Returns None
beginTransaction() 開始使用SPI總線
Description
Initializes the SPI bus using the defined SPISettings.
Syntax
SPI.beginTransaction(mySettings);
Parameters
mySettings: the chosen settings according to SPISettings.
Returns None.
endTransaction() 停用SPI總線
Description
Stop using the SPI bus. Normally this is called after de-asserting the chip select, to allow other libraries to use the SPI bus.
Syntax
SPI.endTransaction()
Parameters None.
Returns None.
setBitOrder() 設置傳輸數據時的先后順序
Description
This function should not be used in new projects. Use SPISettings with SPI.beginTransaction() to configure SPI parameters.
Sets the order of the bits shifted out of and into the SPI bus, either LSBFIRST (least-significant bit first) or MSBFIRST (most-significant bit first).
Syntax
SPI.setBitOrder(order)
Parameters
order: either LSBFIRST or MSBFIRST
Returns None
setClockDivider() 設置時鍾分頻器
Description
This function should not be used in new projects. Use SPISettings with SPI.beginTransaction() to configure SPI parameters.
Sets the SPI clock divider relative to the system clock. On AVR based boards, the dividers available are 2, 4, 8, 16, 32, 64 or 128. The default setting is SPI_CLOCK_DIV4, which sets the SPI clock to one-quarter the frequency of the system clock (4 Mhz for the boards at 16 MHz).
Arduino Due
On the Due, the system clock can be divided by values from 1 to 255. The default value is 21, which sets the clock to 4 MHz like other Arduino boards.
Syntax
SPI.setClockDivider(divider)
Parameters
Returns None
setDataMode() 設置數據模式,即時鍾的極性和相位
Description
This function should not be used in new projects. Use SPISettings with SPI.beginTransaction() to configure SPI parameters.
Sets the SPI data mode: that is, clock polarity and phase. See the Wikipedia article on SPI for details.
Syntax
SPI.setDataMode(mode)
Parameters
Returns None
transfer(), transfer16() 數據傳送
Description
SPI transfer is based on a simultaneous send and receive: the received data is returned in receivedVal (or receivedVal16). In case of buffer transfers the received data is stored in the buffer in-place (the old data is replaced with the data received).
Syntax
receivedVal = SPI.transfer(val)
receivedVal16 = SPI.transfer16(val16)
SPI.transfer(buffer, size)
Parameters
val: the byte to send out over the bus
val16: the two bytes variable to send out over the bus
buffer: the array of data to be transferred
Returns the received data
usingInterrupt() 在中斷中做SPI處理
Description
If your program will perform SPI transactions within an interrupt, call this function to register the interrupt number or name with the SPI library. This allows SPI.beginTransaction() to prevent usage conflicts. Note that the interrupt specified in the call to usingInterrupt() will be disabled on a call to beginTransaction() and re-enabled in endTransaction().
Syntax
SPI.usingInterrupt(interruptNumber)
Parameters
interruptNumber: the associated interrupt number.
Returns None.