SPI總線協議介紹


  一、概述

  SPI = Serial Peripheral Interface,是串行外圍接口設備,是一種高速,全雙工,同步的通信總線。常規只占用四根線,節約了芯片管腳,PCB的布局省空間。

  • 優點:

    支持全雙工,push-pull的驅動性能相比open-drain信號完整性更好。

    支持高速(100MHz以上)。

    協議支持字節長不限於8bits,可根據應用特點靈活選擇消息字長

    硬件連接簡單。

  • 缺點:

    相比I2C多兩根線。

    沒有尋址機制,只能靠片選選擇不同設備。

    沒有從設備接收ACK,主設備對於發送成功與否不得而知。

    典型應用只支持單主控

    相比RS232  RS485和CAN總線,SPI傳輸距離短

 

  二、硬件結構

  SPI總線定義兩個及以上設備間的數據通信,提供時鍾的設備為主設備Master,接收時鍾的設備為從設備Slave;

  信號定義如下:

    SCK :Serial Clock 串行時鍾

    MOSI:Master Ouput,Slave Input 主發從收信號

    MISO:Master Input,Slave Input主收從發信號

    SS/CS:Slave Select片選信號

  電路連接如下:

  單個主設備和單個從設備:

  

  單個主設備和多個從設備:

  

 

  三、寄存器類型

    摩托羅拉定義的SPI寄存器包括:

    SPI Control Register 1 控制寄存器1

    SPI Control Register 2 控制寄存器2

    SPI Baud Rate Register 波特率寄存器

    SPI Status Register(SPISR)   狀態寄存器(只讀 其余均可讀可寫)

    SPI Data Register(SPIDR) 數據寄存器

    通過往寄存器中寫入不同的值,設置SPI模塊的不同屬性

  四、SPI傳輸模式  

    SPI通信有四種模式,簡單地講就是設置SCLK時鍾信號線的那種信號為有效信號

    通過設置控制寄存器SPICR1中的CPOL和CPHA位,將SPI可以分成四種傳輸模式

 

    時鍾極性CPOL,即Clock Polarity,決定時鍾空閑時狀態電平。對於SPI數據傳輸格式沒有顯著影響

    CPOL = 0 ,表示當SCLK=0時處於空閑狀態,所以有效狀態就是SCLK處於高電平狀態時

    CPOL = 1, 表示當SCLK=1時處於空閑狀態,所以有效狀態就是SCLK處於低電平狀態時

 

    CPHA,即Clock Phase,定義SPI數據傳輸的兩種基本模式

    CPHA = 0 ,在時鍾的第一個跳變沿(上升沿或下降沿)進行數據采樣。,在第2個邊沿發送數據

    CPHA = 1, 在時鍾的第二個跳變沿(上升沿或下降沿)進行數據采樣。,在第1個邊沿發送數據

    

 

    四種模式如下圖所示:

    先看第一列兩張圖(CPHA = 0),采樣發生在第一個時鍾跳變沿,即數據采樣發生在SCK奇數邊沿;

    再看第二列兩張圖(CPHA = 1),采樣發生在第二個時鍾跳變沿,即數據采樣發生在SCK偶數邊沿。

    

    MODE0:CPOL=0,CPHA=0:此時空閑態時,SCLK處於低電平,數據采樣是在第一個邊沿,也就是SCLK由低電平到高電平的跳變,所以數據采樣是在上升沿(准備數據),(發送數據)數據發送是在下沿

    MODE1:CPOL=0,CPHA=1:此時空閑態時,SCLK處於低電平,數據發送是在第一個邊沿,也就是SCLK由低電平到高電平的跳變,所以數據采樣是在下降沿,數據發送是在上升沿

    MODE2:CPOL=1,CPHA=0:此時空閑態時,SCLK處於高電平,數據采樣是在第一個邊沿,也就是SCLK由高電平到低電平的跳變,所以數據采樣是在下降沿,數據發送是在上升沿    

    MODE3:CPOL=1,CPHA=1:此時空閑態時,SCLK處於高電平,數據發送是在第一個邊沿,也就是SCLK由高電平到低電平的跳變,所以數據采樣是在上升沿,數據發送是在下降沿

 

 

    五、讀寫操作

    標准SPI讀寫為例

    片選——讀指令——地址——數據讀出

    

    片選——寫指令——地址——數據寫入

    

 

    SPI通信協議

    

    

    主從設備必須使用相同的工作模式——SCLK、CPOL 和 CPHA,才能正常工作。如果有多個從設備,並且它們使用了不同的工作模式,那么主設備必須在讀寫不同從設備時需要重新修改對應從設備的模式。以上SPI總線協議的主要內容。

    是不是感覺,這就完了? SPI就是如此,他沒有規定最大傳輸速率,沒有地址方案,也沒規定通信應答機制,沒有規定流控制規則。

    只要四根信號線連接正確,SPI模式相同,將CS/SS信號線拉低,即可以直接通信,一次一個字節的傳輸,讀寫數據同時操作,這就是SPI

    一些通信控制都得通過SPI設備自行實現,SPI並不關心物理接口的電氣特性,例如信號的標准電壓。

    

   

   STM32中SPI初始化配置

    1.初始化GPIO口,配置相關引腳的復用功能,使能SPIx時鍾。調用函數:void GPIO_Init();

    2.使能SPI時鍾總線:RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE)

    3.配置SPI初始化的參數,設置SPI工作模式:SPI_Init(SPI1,&SPI_Initstructure)

    4.使能SPI外設:SPI_Cmd(SPI1,ENABLE);

    SPI配置設置

    

  typedef struct
  {
    uint16_t SPI_Direction; /*!< 傳輸方向,兩向全雙工,單向接收等*/
    uint16_t SPI_Mode; /*!< 模式選擇,確定主機還是從機 */
    uint16_t SPI_DataSize; /*!< 數據大小,8位還是16位 */
    uint16_t SPI_CPOL; /*!< 時鍾極性選擇 */
    uint16_t SPI_CPHA; /*!< 時鍾相位選擇 */
    uint16_t SPI_NSS; /*!< 片選是硬件還是軟件*/
    uint16_t SPI_BaudRatePrescaler; /*!< 分頻系數 */
    uint16_t SPI_FirstBit; /*!< 指定數據傳輸是從MSB還是LSB位開始的。MSB就是二進制第一位,LSB就是最后一位 */
    uint16_t SPI_CRCPolynomial; /*!< CRC校驗 ,設置 CRC 校驗多項式,提高通信可靠性,大於 1 即可*/
  }SPI_InitTypeDef;
void SPI2_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  SPI_InitTypeDef  SPI_InitStructure;
 
  RCC_APB2PeriphClockCmd(    RCC_APB2Periph_GPIOB, ENABLE );//PORTB時鍾使能 
  RCC_APB1PeriphClockCmd(    RCC_APB1Periph_SPI2,  ENABLE );//SPI2時鍾使能     
 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //PB13/14/15復用推挽輸出 
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB
 
  GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);  //PB13/14/15上拉
 
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //設置SPI單向或者雙向的數據模式:SPI設置為雙線雙向全雙工
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;        //設置SPI工作模式:設置為主SPI
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;        //設置SPI的數據大小:SPI發送接收8位幀結構
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;        //串行同步時鍾的空閑狀態為高電平
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;    //串行同步時鍾的第二個跳變沿(上升或下降)數據被采樣
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;        //NSS信號由硬件(NSS管腳)還是軟件(使用SSI位)管理:內部NSS信號有SSI位控制
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;        //定義波特率預分頻的值:波特率預分頻值為256
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;    //指定數據傳輸從MSB位還是LSB位開始:數據傳輸從MSB位開始
  SPI_InitStructure.SPI_CRCPolynomial = 7;    //CRC值計算的多項式
  SPI_Init(SPI2, &SPI_InitStructure);  //根據SPI_InitStruct中指定的參數初始化外設SPIx寄存器
 
  SPI_Cmd(SPI2, ENABLE); //使能SPI外設
    
  SPI2_ReadWriteByte(0xff);//啟動傳輸    
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM