SPI協議內容及STM32 SPI的操作
阿新 • • 發佈:2019-01-07
SPI匯流排協議簡介及內容
簡介
SPI,是英語Serial Peripheral Interface的縮寫,顧名思義就是序列外圍裝置介面。SPI,是一種高速的,全/半雙工,同步的通訊匯流排,並且在晶片的管腳上只佔用三/四根線,節約了晶片的管腳,同時為PCB的佈局上節省空間,提供方便,正是出於這種簡單易用的特性,現在越來越多的晶片集成了這種通訊協議。
SPI特徵
3根/4根線全雙工同步傳輸
8或16位傳輸幀格式選擇
主從操作模式
支援多主操作模式
從模式頻率(最大為fpclk/2)
可程式設計的時鐘極性和相位
可程式設計的資料順序,MSB在前或LSB在前
可觸發中斷的專用傳送和標誌
SPI匯流排忙狀態標誌
支援可靠通訊的CRC
功能
SPI框圖
SPI通常都是採用四個引腳和外圍裝置相連,每個引腳的含義:
- MISO 主裝置輸入/從裝置輸出引腳。該引腳在從模式下發送資料,在主模式下接收資料。
- MOSI 主裝置輸出/從裝置輸入引腳。該引腳在從模式下接收資料,在主模式下發送資料。
- SCK 串列埠時鐘,作為主裝置的輸出,從裝置的輸入。
- NSS 從裝置選擇(片選引腳),是一個可選的引腳,用來選擇主/從裝置。
SPI時鐘極性(CPOL)和時鐘相位(CPHA)的組合時序圖
SPI的極性和相位組合有四種:
- CPHA=0,表示第一個邊沿:
對於CPOL=0,idle時候的是低電平,第一個邊沿就是從低變到高,所以是上升沿;
對於CPOL=1,idle時候的是高電平,第一個邊沿就是從高變到低,所以是下降沿; - CPHA=1,表示第二個邊沿:
對於CPOL=0,idle時候的是低電平,第二個邊沿就是從高變到低,所以是下降沿;
對於CPOL=1,idle時候的是高電平,第一個邊沿就是從低變到高,所以是上升沿;
- CPHA=0,表示第一個邊沿:
可以相互組合通過暫存器(SPI_CR1)設定不同的時鐘極性和時鐘相位組合。
STM32 的SPI暫存器對映及復位值
- SPI暫存器對映
用STM32韌體庫函式程式設計配置SPI匯流排操作
- SPI所用到的GPIO初始化
void SPI_GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Configure SPI2 -------------------------*/
GPIO_StructInit(&GPIO_InitStructure);
//CS | NSS
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//SCK
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//MISO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//MOSI
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
- SPI配置初始化
void SPI_Configuration(void)
{
SPI_InitTypeDef SPI_InitStructure;
SPI_Cmd(SPI2, DISABLE);
SPI_StructInit(&SPI_InitStructure);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI2, &SPI_InitStructure);
/*Enable SPI1.NSS as a GPIO*/
SPI_SSOutputCmd(SPI2, ENABLE);
// GPIO_SetBits(GPIOD, GPIO_Pin_7);
GPIO_SetBits(GPIOB, GPIO_Pin_12); //CS = 1 | NSS=1
/* Enable SPI1 */
SPI_Cmd(SPI2, ENABLE);
}
Tips
對於SPI配置中的CPOL和CPHA兩個選項,可以根據連線外設需求不同進行修改配置,參考上面提到的四種模式。
SPI傳送和接收
u8 SPI_SendByte(u8 tempdata)
{
/* Loop while DR register in not emplty */
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
/* Send byte through the SPI1 peripheral */
SPI_I2S_SendData(SPI2, tempdata); //send tempdata
/* Wait to receive a byte */
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
/* Return the byte read from the SPI bus */
return SPI_I2S_ReceiveData(SPI2);
}
u8 SPI_ReceiveByte(void)
{
return (SPI_SendByte(0x00));
}
一般在SPI匯流排外圍所接裝置
- 一般常見的SPI連線外圍裝置有:
Flash儲存晶片,感測器類晶片。