通常SPI通過4個引腳與外部器件相連: ● MISO:主設備輸入/從設備輸出引腳。該引腳在從模式下發送數據,在主模式下接收數據。 ● MOSI:主設備輸出/從設備輸入引腳。該引腳在主模式下發送數據,在從模式下接收數據。 ● SCK:串口時鐘,作為主設備的輸出,從設備的輸入 ●NSS:從設備選擇。這是一個可選的引腳,用來選擇主/從設備。它的功能是用來作為“片選引腳”,讓主設備可以單獨地與特定從設備通訊,避免數據線上的沖突。從設備的NSS引腳可以由主設備的一個標準I/O引腳來驅動。一旦被使能(SSOE位),NSS引腳也可以作為輸出引腳,并在SPI處于主模式時拉低;此時,所有的SPI設備,如果它們的NSS引腳連接到主設備的NSS引腳,則會檢測到低電平,如果它們被設置為NSS硬件模式,就會自動進入從設備狀態。當配置為主設備、NSS配置為輸入引腳(MSTR=1,SSOE=0)時,如果NSS被拉低,則這個SPI設備進入主模式失敗狀態:即MSTR位被自動清除,此設備進入從模式。
時鐘信號的相位和極性 SPI_CR寄存器的CPOL和CPHA位,能夠組合成四種可能的時序關系。CPOL(時鐘極性)位控制在沒有數據傳輸時時鐘的空閑狀態電平,此位對主模式和從模式下的設備都有效。如果CPOL被清’0’,SCK引腳在空閑狀態保持低電平;如果CPOL被置’1’,SCK引腳在空閑狀態保持高電平。 如果CPHA(時鐘相位)位被置’1’,SCK時鐘的第二個邊沿(CPOL位為0時就是下降沿,CPOL位為’1’時就是上升沿)進行數據位的采樣,數據在第二個時鐘邊沿被鎖存。如果CPHA位被清’0’,SCK時鐘的第一邊沿(CPOL位為’0’時就是下降沿,CPOL位為’1’時就是上升沿)進行數據位采樣,數據在第一個時鐘邊沿被鎖存。 CPOL時鐘極性和CPHA時鐘相位的組合選擇數據捕捉的時鐘邊沿。
圖212顯示了SPI傳輸的4種CPHA和CPOL位組合。此圖可以解釋為主設備和從設備的SCK腳、MISO腳、MOSI腳直接連接的主或從時序圖。
1398086209323335046.jpeg (6.86 KB, 下載次數: 77)
下載附件
2017-2-18 23:08 上傳
CPOL時鐘極性和CPHA時鐘相位的組合選擇數據捕捉的時鐘邊沿。
上圖顯示了SPI傳輸的4種CPHA和CPOL位組合。此圖可以解釋為主設備和從設備的SCK腳、MISO腳、MOSI腳直接連接的主或從時序圖。
注意: 1. 在改變CPOL/CPHA位之前,必須清除SPE位將SPI禁止。
2. 主和從必須配置成相同的時序模式。
3.SCK的空閑狀態必須和SPI_CR1寄存器指定的極性一致(CPOL為’1’時,空閑時應上拉SCK為高電平;CPOL為’0’時,空閑時應下拉SCK為低電平)。
4. 數據幀格式(8位或16位)由SPI_CR1寄存器的DFF位選擇,并且決定發送/接收的數據長度。 我只要知道主機和從機的CPOL和CPHA位要一致就夠了。
有2種NSS模式:
●軟件NSS模式:可以通過設置SPI_CR1寄存器的SSM位來使能這種模式。在這種模式下NSS引腳可以用作它用,而內部NSS信號電平可以通過寫SPI_CR1的SSI位來驅動
● 硬件NSS模式,分兩種情況:
─NSS輸出被使能:當STM32F10xxx工作為主SPI,并且NSS輸出已經通過SPI_CR2寄存器的SSOE位使能,這時NSS引腳被拉低,所有NSS引腳與這個主SPI的NSS引腳相連并配置為硬件NSS的SPI設備,將自動變成從SPI設備。當一個SPI設備需要發送廣播數據,它必須拉低NSS信號,以通知所有其它的設備它是主設備;如果它不能拉低NSS,這意味著總線上有另外一個主設備在通信,這時將產生一個硬件失敗錯誤(HardFault)。
─ NSS輸出被關閉:允許操作于多主環境。
//我們用軟件NSS主從的轉換都可借助庫來實現
數據幀格式
根據SPI_CR1寄存器中的LSBFIRST位,輸出數據位時可以MSB在先也可以LSB在先。
根據SPI_CR1寄存器的DFF位,每個數據幀可以是8位或是16位。所選擇的數據幀格式對發送和/或接收都有效。
配置一個SPI 這里選SPI2
如下:
SPI_InitTypeDef SPI_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);
SPI_Cmd(SPI2, DISABLE); //必須先禁能,才能改變MODE
SPI_InitStructure.SPI_Direction =SPI_Direction_2Lines_FullDuplex; //兩線全雙工
SPI_InitStructure.SPI_Mode =SPI_Mode_Master; //主
SPI_InitStructure.SPI_DataSize =SPI_DataSize_8b; //8位
SPI_InitStructure.SPI_CPOL =SPI_CPOL_High; //CPOL=1時鐘懸空高
SPI_InitStructure.SPI_CPHA =SPI_CPHA_1Edge; //CPHA=1 數據捕獲第2個
SPI_InitStructure.SPI_NSS =SPI_NSS_Soft; //軟件NSS
SPI_InitStructure.SPI_BaudRatePrescaler =SPI_BaudRatePrescaler_2; //2分頻
SPI_InitStructure.SPI_FirstBit =SPI_FirstBit_MSB; //高位在前
SPI_InitStructure.SPI_CRCPolynomial =7; //CRC7
SPI_Init(SPI2,&SPI_InitStructure);
SPI_Cmd(SPI2, ENABLE); //spi的配置結束了可以使用了。
也可用 函數SPI_StructInit 把SPI_InitStruct中的每一個參數按缺省值填入
_____________________________________________________________________________________
發送緩沖器空閑標志(TXE)【3.0 SPI_I2S_FLAG_TXE】
此標志為’1’時表明發送緩沖器為空,可以寫下一個待發送的數據進入緩沖器中。當寫入SPI_DR時,TXE標志被清除。
接收緩沖器非空(RXNE)【3.0 SPI_I2S_FLAG_RXNE】
此標志為’1’時表明在接收緩沖器中包含有效的接收數據。讀SPI數據寄存器可以清除此標志。
注意在2.0的庫中函數 SPI_SendData SPI_ReceiveDataSPI_GetFlagStatus 等在3.0的庫中 變為 SPI_I2S_SendData SPI_I2S_ReceiveData SPI_I2S_GetFlagStatus
寫一個發送/接受函數
static u8 SPIByte(u8 byte) {
while((SPI2->SR &SPI_I2S_FLAG_TXE)==RESET);
//while((SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE))==RESET);
SPI2->DR = byte;
//SPI_I2S_SendData(SPI2,byte);
while((SPI2->SR &SPI_I2S_FLAG_RXNE)==RESET); //while((SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE))==RESET);
return(SPI2->DR); //returnSPI_I2S_ReceiveData(SPI2);讀寄存器用硬件清除標志位。
//SPI_I2S_ClearFlag(SPI2,SPI_I2S_FLAG_RXNE) ;直接軟件清除標志位。
}
|