STM32第十章-SPI通信應用

  上一章咱們講到了IIC通信,這一章來講一說SPI通訊,一樣的不少模塊也用到了SPI通訊,好比0.96寸的OLED模塊。玩過單片機的小夥伴都知道OLED有4針的也有7針的,4針的就是IIC通訊,7針的就是SPI通訊。緩存

1、 SPI 簡介

  SPI 是英語 Serial Peripheral interface 的縮寫,顧名思義就是串行外圍設備接口。是 Motorola首先在其 MC68HCXX 系列處理器上定義的。SPI 接口主要應用在 EEPROM,FLASH,實時時鐘,AD 轉換器,還有數字信號處理器和數字信號解碼器之間。SPI是一種高速的,全雙工,同步的通訊總線,而且在芯片的管腳上只佔用四根線,節約了芯片的管腳,同時爲 PCB 的佈局上節省空間,提供方便,正是出於這種簡單易用的特性,如今愈來愈多的芯片集成了這種通訊協議,STM32 也有 SPI 接口。SPI通信使用 3 條總線及片選線,3條總線分別爲 SCK、MOSI、MISO、SS。markdown

在這裏插入圖片描述

  (1) SCK (Serial Clock):時鐘信號線,用於通信數據同步。它由通信主機STM32產生,決定了通信的速率,不一樣的設備支持的最高時鐘頻率不同,如STM32的SPI 時鐘頻率最大爲fpclk /2,兩個設備之間通信時,通信速率受限於低速設備。函數

  (2) MOSI (Master Output, Slave Input):主設備STM32輸出/從設備輸入引腳。STM32的數據從這條信號線輸出,從機由這條信號線讀入STM32發送的數據,即這條線上數據的方向爲STM32到從機。佈局

  (3) MISO(Master Input,,Slave Output):主設備STM32輸入/從設備輸出引腳。STM32從這條信號線讀入數據,從機的數據由這條信號線輸出到STM32,即在這條線上數據的方向爲從機到STM32。spa

  (4) SS( Slave Select):片選信號線,也稱爲 NSS、CS。當有多個SPI 從設備與 SPI 主機STM32相連時,設備的其它信號線 SCK、MOSI及 MISO同時並聯到相同的 SPI總線上,即不管有多少個從設備,都共同只使用這 3 條總線;而每一個從設備都有獨立的這一條 NSS 信號線,本信號線獨佔主機的一個引腳,即有多少個從設備,就有多少條片選信號線。I2C 協議中經過設備地址來尋址、選中總線上的某個設備並與其進行通信;而 SPI 協議中沒有設備地址,它使用 NSS 信號線來尋址,當主機要選擇從設備時,把該從設備的 NSS 信號線設置爲低電平,該從設備即被選中,即片選有效,接着主機開始與被選中的從設備進行 SPI 通信。因此SPI通信以 NSS 線置低電平爲開始信號,以 NSS 線被拉高做爲結束信號。3d

2、 具體代碼編寫

1.SPI引腳初始化

  咱們使用 STM32 的 SPI1 的主模式,第一步就要是能 SPI1 的時鐘,SPI1 的時鐘經過 APB2ENR 的第12位來設置。其次要設置 SPI1 的相關引腳爲複用輸出,這樣纔會鏈接到 SPI1 上不然這些 IO 口仍是默認的狀態,也就是標準輸入輸出口。這裏咱們使用的是 PA五、PA六、PA7 這 3 個,因此設置這三個爲複用 IO。code

void SPI1_Init(void) {
GPIO_InitTypeDef GPIO_InitStructure;    
RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOA|RCC_APB2Periph_SPI1, ENABLE );	 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //複用推輓輸出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);	
GPIO_SetBits(GPIOA,GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
}
複製代碼

2.設置SPI1工做模式

  接下來咱們要初始化 SPI1,這在庫函數中是經過 SPI_Init 函數來實現的,和STM32的其餘外設同樣一樣須要配置這些參數,使用中咱們不須要關心這些具體的設置。設置 SPI1 爲主機模式,設置數據格式爲 8 位,然設置 SCK 時鐘極性及採樣方式。並設置 SPI1 的時鐘頻率(最大 18Mhz),以及數據的格式(MSB 在前仍是LSB 在前)。這在庫函數中是經過 SPI_Init 函數來實現的。orm

SPI_InitTypeDef  SPI_InitStructure;
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(SPI1, &SPI_InitStructure); //根據SPI_InitStruct中指定的參數初始化外設SPIx寄存器 
複製代碼

3.使能SPI1

初始化完成以後接下來是要使能 SPI1 通訊了,在使能 SPI1 以後,咱們就能夠開始 SPI 通信了。接口

SPI_Cmd(SPI1, ENABLE); //使能SPI外設
複製代碼

4.使用SPI讀寫一個字節

u8 SPI1_ReadWriteByte(u8 TxData) {		
	u8 retry=0;				 	
	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET)//檢查指定的SPI標誌位設置與否:發送緩存空標誌位
	{
		retry++;
		if(retry>200)return 0;
	}			  
	SPI_I2S_SendData(SPI1, TxData);//經過外設SPIx發送一個數據
	retry=0;
	while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)//檢查指定的SPI標誌位設置與否:接受緩存非空標誌位
	{
		retry++;
		if(retry>200)return 0;
	}	  						    
	return SPI_I2S_ReceiveData(SPI1); //返回經過SPIx最近接收的數據 
}
複製代碼

  本函數中不包含 SPI 起始和中止信號,只是收發的主要過程,因此在調用本函數先後要作好起始和中止信號的操做;事件

  循環調用庫函數SPI_I2S_GetFlagStatus 檢測事件,若檢測到事件,則進入通信的下一階段,若未檢測到事件則停留在此處一直檢測,當檢測200次都還沒等待到事件則認爲通信失敗,退出通信;

  經過檢測TXE標誌,獲取發送緩衝區的狀態,若發送緩衝區爲空,則表示可能存在的上一個數據已經發送完畢;等待至發送緩衝區爲空後,調用庫函數 SPI_I2S_SendData 把要發送的數據「TxData」寫入到 SPI的數據寄存器 DR,寫入 SPI數據寄存器的數據會存儲到發送緩衝區,由 SPI外設發送出去;

  寫入完畢後經過循環200次等待RXNE 事件,即接收緩衝區非空事件。因爲 SPI 雙線全雙工模式下MOSI 與 MISO 數據傳輸是同步的,當接收緩衝區非空時,表示上面的數據發送完畢,且接收緩衝區也收到新的數據;

  等待至接收緩衝區非空時,經過調用庫函數 SPI_I2S_ReceiveData 讀取 SPI 的數據寄存器 DR,就能夠獲取接收緩衝區中的新數據了。代碼中使用關鍵字「return」把接收到的這個數據做爲SPI_SendByte 函數的返回值。

  以上的步驟咱們就搞定了SPI 的基本收發單元,還須要瞭解如何對FLASH 芯片進行讀寫。FLASH 芯片自定義了不少指令,咱們經過控制 STM32 利用 SPI 總線向 FLASH 芯片發送指令,FLASH芯片收到後就會執行相應的操做。而這些指令,對主機端(STM32)來講,只是它遵照最基本的 SPI 通信協議發送出的數據,但在設備端(FLASH 芯片)把這些數據解釋成不一樣的意義,因此才成爲指令。查看FLASH 芯片的數據手冊可瞭解各類它定義的各類指令的功能及指令格式。這裏我就不過多的將寫了。

相關文章
相關標籤/搜索