1. 程式人生 > >SPI協議內容及STM32 SPI的操作

SPI協議內容及STM32 SPI的操作

SPI匯流排協議簡介及內容

簡介

SPI,是英語Serial Peripheral Interface的縮寫,顧名思義就是序列外圍裝置介面。SPI,是一種高速的,全/半雙工,同步的通訊匯流排,並且在晶片的管腳上只佔用三/四根線,節約了晶片的管腳,同時為PCB的佈局上節省空間,提供方便,正是出於這種簡單易用的特性,現在越來越多的晶片集成了這種通訊協議。

SPI特徵

3根/4根線全雙工同步傳輸
8或16位傳輸幀格式選擇
主從操作模式
支援多主操作模式
從模式頻率(最大為fpclk/2)
可程式設計的時鐘極性和相位
可程式設計的資料順序,MSB在前或LSB在前
可觸發中斷的專用傳送和標誌
SPI匯流排忙狀態標誌
支援可靠通訊的CRC

功能
  • SPI框圖
    SPI框圖

  • SPI通常都是採用四個引腳和外圍裝置相連,每個引腳的含義:

    • MISO 主裝置輸入/從裝置輸出引腳。該引腳在從模式下發送資料,在主模式下接收資料。
    • MOSI 主裝置輸出/從裝置輸入引腳。該引腳在從模式下接收資料,在主模式下發送資料。
    • SCK 串列埠時鐘,作為主裝置的輸出,從裝置的輸入。
    • NSS 從裝置選擇(片選引腳),是一個可選的引腳,用來選擇主/從裝置。
  • SPI時鐘極性(CPOL)和時鐘相位(CPHA)的組合時序圖
    SPI極性和相位時序圖

  • SPI的極性和相位組合有四種:

    • CPHA=0,表示第一個邊沿:
      對於CPOL=0,idle時候的是低電平,第一個邊沿就是從低變到高,所以是上升沿;
      對於CPOL=1,idle時候的是高電平,第一個邊沿就是從高變到低,所以是下降沿;
    • CPHA=1,表示第二個邊沿:
      對於CPOL=0,idle時候的是低電平,第二個邊沿就是從高變到低,所以是下降沿;
      對於CPOL=1,idle時候的是高電平,第一個邊沿就是從低變到高,所以是上升沿;
  • 可以相互組合通過暫存器(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儲存晶片,感測器類晶片。