1. 程式人生 > >SPI通訊協議學習總結

SPI通訊協議學習總結

SPI通訊

1.簡介

這裡介紹STM32通過SPI實現對外部SPIFlash的讀寫功能,其中,SPI作為主裝置,SPIFlash作為從裝置。為了驗證SPI Flash收到的資料是否是STM32通過SPI傳送給它的資料,我們將SPIFlash讀取的資料顯示在螢幕上(TFTLCD)。

1.1 SPI簡介

SPI就是序列外圍裝置介面,它是一種高速的,全雙工,同步的通訊匯流排,並且在晶片的管腳上只佔用四根線,這四根線的定義分別是:

 MISO:主裝置資料輸入,從裝置資料輸出;

 MOSI:主裝置資料輸出,從裝置資料輸入;

 SCLK:時鐘訊號,由主裝置產生;

 CS:從裝置片選訊號,由主裝置控制;

SPI為了和外設進行資料交換,根據外設工作要求,其輸出串行同步時鐘極性和相位可以進行配置,時鐘極性(CPOL)對傳輸協議沒有重大的影響。如果CPOL=0,串行同步時鐘的空閒狀態為低電平;如果CPOL=1,串行同步時鐘的空閒狀態為高電平。時鐘相位(CPHA)能夠配置用於選擇兩種不同的傳輸協議之一進行資料傳輸。如果CPHA=0,在串行同步時鐘的第一個跳變沿(上升或下降)資料被取樣;如果CPHA=1,在串行同步時鐘的第二個跳變沿(上升或下降)資料被取樣。SPI匯流排資料傳輸時序圖如下圖:

資料傳輸過程如下:SCK的第一個時鐘週期在時鐘的前沿取樣資料(上升沿,第一個時鐘沿鍾沿),在時鐘的後沿輸出資料(下降沿,第二個時鐘沿)。首先來看主器件,主器件的輸出口MOSI輸出的資料,在時鐘的前沿被從器件取樣,那主器件是在何時刻輸出資料的呢?資料的輸出時刻實際上在SCK訊號有效以前,比SCK的上升沿還要早半個時鐘週期。資料的輸出時刻與SSEL訊號沒有關係。再來看從器件,主器件的輸入口MISO同樣是在時鐘的前沿取樣從器件輸出的資料,那從器件又是在何時刻輸出資料的呢? 從器件是在SSEL訊號有效後,立即輸出資料,儘管此時SCK訊號還沒有起效。

1.2 SPI Flash簡介

SPI Flash以W25Q64為例進行介紹,W25Q64將8M的容量分為128個塊(Block ),每個塊大小為64K位元組,每個塊又分為16個扇區(Sector),每個扇區4K個位元組。W25Q64 的最少擦除單位為一個扇區,也就是每次必須擦除4K個位元組。這樣我們需要給W25Q64 開闢一個至少4K的快取區。

SPI Flash的寫入資料基本過程是:先獲得首地址(WriteAddr)所在的扇區,並計算在扇區內的偏移,然後判斷要寫入的資料長度是否超過本扇區所剩下的長度,如果不超過,再先看看是否要擦除,如果不要,則直接寫入資料即可,如果要則讀出整個扇區,在偏移處開始寫入指定長度的資料,然後擦除這個扇區,再一次性寫入。當所需要寫入的資料長度超過一個扇區的長度的時候,我們先按照前面的步驟把扇區剩餘部分寫完,再在新扇區內執行同樣的操作,如此迴圈,直到寫入結束。

2. 硬體設計

我們利用STM32自帶的SPI和SPIFlash通訊,通訊過程中SPI是主裝置,SPIFlash是從裝置,硬體設計如下圖所示:


3. 軟體設計

3.1 SPI軟體設計

(1)使能SPI時鐘,且定義相關引腳的複用功能;

使能SPI時鐘,且配置SPI佔用的幾個GPIO引腳的功能為複用功能;SPI和STM32共用一個時鐘,可以對SPI頻率進行設定,SPI時鐘通過APB2進行分頻,分頻係數可以是2、4、8等,最低是256分頻。

(2)設定SPI工作引數

主要對SPI以下幾個工作引數進行設定:

設定SPI的通訊方式,可以是全雙工、半雙工等方式;

設定SPI的主從模式;

設定SPI傳輸方式:8位傳輸還是16位傳輸;

設定SPI的時鐘極性;

設定SPI的時鐘相位;

設定SPI的分頻係數;

設定SPI的CRC校驗多項式;

(3)使能SPI外設;

(4)SPI傳送接收資料;

(5)檢視SPI傳輸狀態;

3.2 SPI Flash軟體設計

(1)SPIFlash讀出資料;讀取資料過程:由於W25Q64 支援以任意地址(但是不能超過W25Q64的地址範圍)開始讀取資料,在傳送24 位地址之後,程式就可以開始迴圈讀資料了,其地址會自動增加的,不過要注意,不能讀的資料超過了W25Q64的地址範圍。

(2)SPIFlash寫入資料;寫入資料基本過程:先獲得首地址(WriteAddr)所在的扇區,並計算在扇區內的偏移,然後判斷要寫入的資料長度是否超過本扇區所剩下的長度,如果不超過,再先看看是否要擦除,如果不要,則直接寫入資料即可,如果要則讀出整個扇區,在偏移處開始寫入指定長度的資料,然後擦除這個扇區,再一次性寫入。當所需要寫入的資料長度超過一個扇區的長度的時候,我們先按照前面的步驟把扇區剩餘部分寫完,再在新扇區內執行同樣的操作,如此迴圈,直到寫入結束。