SPI協(xié)議解析
概述
????SPI是串行外設接口(Serial Peripheral Interface)的縮寫,是一種高速的,全雙工,同步的通信總線,并且在芯片的管腳上只占用四根線,節(jié)約了芯片的管腳,同時為PCB的布局上節(jié)省空間,提供方便,正是出于這種簡單易用的特性,越來越多的芯片集成了這種通信協(xié)議,比如AT91RM9200。
????SPI是一種高速、高效率的串行接口技術。通常由一個主模塊和一個或多個從模塊組成,主模塊選擇一個從模塊進行同步通信,從而完成數(shù)據(jù)的交換。SPI是一個環(huán)形結構,通信時需要至少4根線(事實上在單向傳輸時3根線也可以)。
接口
? ? SPI的通信原理很簡單,它以主從方式工作,這種模式通常有一個主設備和一個或多個從設備,需要至少4根線,事實上3根也可以(單向傳輸時)。也是所有基于SPI的設備共有的,它們是MISO(主設備數(shù)據(jù)輸入)、MOSI(主設備數(shù)據(jù)輸出)、SCLK(時鐘)、CS(片選)。
MISO– Master Input Slave Output,主設備數(shù)據(jù)輸入,從設備數(shù)據(jù)輸出;
MOSI– Master Output Slave Input,主設備數(shù)據(jù)輸出,從設備數(shù)據(jù)輸入;
SCLK – Serial Clock,時鐘信號,由主設備產(chǎn)生;
CS – Chip Select,從設備使能信號,由主設備控制。
????其中,CS是從芯片是否被主芯片選中的控制信號,也就是說只有片選信號為預先規(guī)定的使能信號時(高電位或低電位),主芯片對此從芯片的操作才有效。這就使在同一條總線上連接多個SPI設備成為可能。
????接下來就負責通訊的3根線了。通訊是通過數(shù)據(jù)交換完成的,這里先要知道SPI是串行通訊協(xié)議,也就是說數(shù)據(jù)是一位一位的傳輸?shù)?。這就是SCLK時鐘線存在的原因,由SCLK提供時鐘脈沖,SDI,SDO則基于此脈沖完成數(shù)據(jù)傳輸。數(shù)據(jù)輸出通過 SDO線,數(shù)據(jù)在時鐘上升沿或下降沿時改變,在緊接著的下降沿或上升沿被讀取。完成一位數(shù)據(jù)傳輸,輸入也使用同樣原理。因此,至少需要8次時鐘信號的改變(上沿和下沿為一次),才能完成8位數(shù)據(jù)的傳輸。
????時鐘信號線SCLK只能由主設備控制,從設備不能控制。同樣,在一個基于SPI的設備中,至少有一個主設備。這樣的傳輸方式有一個優(yōu)點,在數(shù)據(jù)位的傳輸過程中可以暫停,也就是時鐘的周期可以為不等寬,因為時鐘線由主設備控制,當沒有時鐘跳變時,從設備不采集或傳送數(shù)據(jù)。SPI還是一個數(shù)據(jù)交換協(xié)議:因為SPI的數(shù)據(jù)輸入和輸出線獨立,所以允許同時完成數(shù)據(jù)的輸入和輸出。芯片集成的SPI串行同步時鐘極性和相位可以通過寄存器配置,IO模擬的SPI串行同步時鐘需要根據(jù)從設備支持的時鐘極性和相位來通訊。
????最后,SPI接口的一個缺點:沒有指定的流控制,沒有應答機制確認是否接收到數(shù)據(jù)。

SPI四種通信模式
????不同的從設備可能在出廠是就是配置為某種模式,這是不能改變的;但我們的通信雙方必須是工作在同一模式下,所以我們可以對我們的主設備的SPI模式進行配置,通過CPOL(時鐘極性)和CPHA(時鐘相位)來
????控制我們主設備的通信模式,具體如下:
????時鐘極性(CPOL)定義了時鐘空閑狀態(tài)電平:
????CPOL=0,表示當SCLK=0時處于空閑態(tài),所以有效狀態(tài)就是SCLK處于高電平時
????CPOL=1,表示當SCLK=1時處于空閑態(tài),所以有效狀態(tài)就是SCLK處于低電平時
時鐘相位(CPHA)定義數(shù)據(jù)的采集時間。
????CPHA=0,在時鐘的第一個跳變沿(上升沿或下降沿)進行數(shù)據(jù)采樣,在第2個邊沿發(fā)送數(shù)據(jù)。
????CPHA=1,在時鐘的第二個跳變沿(上升沿或下降沿)進行數(shù)據(jù)采樣,在第1個邊沿發(fā)送數(shù)據(jù)。
????Mode0:CPOL=0,CPHA=0:此時空閑態(tài)時,SCLK處于低電平,數(shù)據(jù)采樣是在第1個邊沿,也就是SCLK由低電平到高電平的跳變,所以數(shù)據(jù)采樣是在上升沿(準備數(shù)據(jù)),(發(fā)送數(shù)據(jù))數(shù)據(jù)發(fā)送是在下降沿。

????Mode1:CPOL=0,CPHA=1:此時空閑態(tài)時,SCLK處于低電平,數(shù)據(jù)發(fā)送是在第1個邊沿,也就是SCLK由低電平到高電平的跳變,所以數(shù)據(jù)采樣是在下降沿,數(shù)據(jù)發(fā)送是在上升沿。

????Mode2:CPOL=1,CPHA=0:此時空閑態(tài)時,SCLK處于高電平,數(shù)據(jù)采集是在第1個邊沿,也就是SCLK由高電平到低電平的跳變,所以數(shù)據(jù)采集是在下降沿,數(shù)據(jù)發(fā)送是在上升沿。

????Mode3:CPOL=1,CPHA=1:此時空閑態(tài)時,SCLK處于高電平,數(shù)據(jù)發(fā)送是在第1個邊沿,也就是SCLK由高電平到低電平的跳變,所以數(shù)據(jù)采集是在上升沿,數(shù)據(jù)發(fā)送是在下降沿。


????這樣兩兩組合就出現(xiàn)了4種通訊模式,但是通信原理是一樣的。
示例
????使用之前的文章作為案例:STM32CUBEMX(13)--SPI,W25Q128外部Flash移植。

????使用BSP_W25Qx_Init進行初始化,BSP_W25Qx_Read_ID進行讀取設備ID。
????定義如下。
????首先進行初始化,函數(shù)為BSP_W25Qx_Init(),其中含有2個函數(shù),分別是BSP_W25Qx_Reset()和BSP_W25Qx_GetStatus();在BSP_W25Qx_Reset()中為發(fā)生0x66和0x99,在BSP_W25Qx_GetStatus()中為發(fā)生0x05,之后獲取一個uint8_t類型的數(shù)據(jù)。
????之后進行讀取ID,函數(shù)為BSP_W25Qx_Read_ID(),首先發(fā)送4個字節(jié)的數(shù)據(jù),分別是0x90,0x00,0x00,0x00,之后讀取設備ID,為2個字節(jié)的數(shù)據(jù),W25Q128的ID為0XEF17。
????HAL_SPI_Transmit,HAL_SPI_Received都是半工通信,HAL_SPI_Transmits使用的時候MOSI上有數(shù)據(jù),忽略MISO,HAL_SPI_Received反之,HAL_SPI_TransmitReceive是全雙工通信,發(fā)送數(shù)據(jù)的同時也在接收數(shù)據(jù),故在HAL_SPI_Receive讀取的時候,雖然也有發(fā)送數(shù)據(jù),但是忽略。
????通過示波器抓取的波形如下所示。

????首先查看初始化設備發(fā)送的0x66和0x99的波形。

????在查看讀取設備ID發(fā)送的0x90,0x00,0x00,0x00的波形。

????在查看設備發(fā)送給主機的ID波形。
????HAL_SPI_Transmit,HAL_SPI_Received都是半工通信,故在HAL_SPI_Receive讀取的時候,雖然也有發(fā)送數(shù)據(jù),但是忽略。
