STM32 SPI通信協議總結

簡介

       SPI是一種高速的,全雙工,同步的通信總線,並且在芯片的管腳上只佔用四根線,以主從方式工作,這種模式通常有一個主設備和一個或多個從設備,需要至少4根線,事實上3根也可以(單向傳輸時)。也是所有基於SPI的設備共有的,它們是SDI(數據輸入),SDO(數據輸出),SCK(時鐘),CS(片選)。

       SDO  --主設備數據輸出,從設備數據輸入

       SDI   --主設備數據輸入,從設備數據輸出

       SCLK  --時鐘信號,由主設備產生

      CS    --從設備使能信號,由主設備控制 

       

工作過程:

          1、主機啓動發送過程,送出時鐘脈衝信號

          2、主移位寄存器的數據通過SDO移入到從移位寄存器,同時從移位寄存器中的數據通過SDI移人到主移位寄存器中

          3、8(16)個時鐘脈衝過後,時鐘停頓,主移位寄存器中的8(16)位數據全部移人到從移位寄存器中,隨即又被自動裝入從接收緩衝器中,從機接收緩衝器滿標誌位(BF)和中斷標誌位(SSPIF)置“1”。同理,從移位寄存器中的8位數據全部移入到主寄存器中,隨即又被自動裝入到主接收緩衝器中.主接收緩衝器滿標誌位(BF)和中斷標誌位(SSPIF)置“1”

          4、主CPU檢測到主接收緩衝器的滿標誌位或者中斷標誌位置1後,就可以讀取接收緩衝器中的數據。同樣,從CPU檢測到 從接收緩衝器滿標誌位或中斷標誌位置1後,就可以讀取接收緩衝器中的數據。

       SPI有四種不同的數據傳輸時序,由CPOL和CPHL決定,CPOL是用來決定SCK時鐘信號空閒時的電平,CPHA是用來決定採樣時刻的:

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

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

       CPHA=0,表示數據採樣是在第1個邊沿,數據發送在第2個邊沿

       CPHA=1,表示數據採樣是在第2個邊沿,數據發送在第1個邊沿

      

       

STM32 SPI相關結構體:

typedef struct
{
  uint16_t SPI_Direction;
  uint16_t SPI_Mode; 
  uint16_t SPI_DataSize; 
  uint16_t SPI_CPOL; 
  uint16_t SPI_CPHA; 
  uint16_t SPI_NSS;   
  uint16_t SPI_BaudRatePrescaler;  
  uint16_t SPI_FirstBit;    
  uint16_t SPI_CRCPolynomial; 
}SPI_InitTypeDef;

STM32的配置步驟:

1、配置相關引腳的複用功能,使能SPIx時鐘。   調用函數:void GPIO_Init();

2、初始化SPIx相關參數,設置SPIx工作模式。   調用函數:void SPI_Init();

3、使能SPIx。                                                      調用函數:void SPI_Cmd();

4、SPI傳輸數據。     調用函數:void SPI_I2S_SendData();uint16_t SPI_I2S_ReceiveData();

5、查看SPI傳輸狀態。調用函數:SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE);

void SPI2_Init(void)
{
 	GPIO_InitTypeDef GPIO_InitStructure;
        SPI_InitTypeDef  SPI_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE );//GPIOB時鐘使能 
	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單向或者雙向的數據模式:SPI設置爲雙線雙向全雙工
	SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  
	SPI_InitStructure.SPI_Mode = SPI_Mode_Master;	 //設置SPI工作模式:設置爲主SPI
        //設置SPI的數據大小:SPI發送接收8位幀結構
	SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;	
        SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;	//串行同步時鐘的空閒狀態爲高電平
        //串行同步時鐘的第二個跳變沿(上升或下降)數據被採樣
	SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;	
        //NSS信號由硬件(NSS管腳)還是軟件(SSI位)管理:內部NSS信號有SSI位控制	
        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;		
        //定義波特率預分頻的值:波特率預分頻值爲256
	SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;	
   	//指定數據傳輸從MSB位還是LSB位開始:數據傳輸從MSB位開始
	SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
	SPI_InitStructure.SPI_CRCPolynomial = 7;	//CRC值計算的多項式
	SPI_Init(SPI2, &SPI_InitStructure); //根據SPI_InitStruct初始化外設SPIx寄存器
	SPI_Cmd(SPI2, ENABLE); //使能SPI外設
	SPI2_ReadWriteByte(0xff);//啓動傳輸		 
}   
//SPIx 讀寫一個字節,TxData:要寫入的字節,返回值:讀取到的字節
u8 SPI2_ReadWriteByte(u8 TxData)
{		
	u8 retry=0;	
        //檢查指定的SPI標誌位設置與否:發送緩存空標誌位			 	
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) 
	{
		retry++;
		if(retry>200) return 0;
	}			  
	SPI_I2S_SendData(SPI2, TxData); //通過外設SPIx發送一個數據
	retry=0;
        //檢查指定的SPI標誌位設置與否:接受緩存非空標誌位
	while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) 
	{
		retry++;
		if(retry>200) return 0;
	}	  						    
	return SPI_I2S_ReceiveData(SPI2); //返回通過SPIx最近接收的數據					    
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章