天天看點

STM32Cube學習筆記-SPI通訊

引言  使用STM32Cube開發東西最怕的就是寫的代碼太多,為什麼呢?因為不會寫,我深有體會。SPI通訊是一種常用的常用的通訊方式,同步、串行。同步代表着實時性好,串行代表着接線少,很多的裝置願意采用這種方法,廢話少說,關于SPI通訊的由來,基本的原理可以百度,我這裡介紹用STM32F103ZET6和W25Q64開發SPI通訊。

使用的工具

SMT32F103的開發闆,SPI連接配接了W25Q64的Flash晶片;用到了序列槽作為調試;

軟體是STM32Cube MX,和Keil 5,用到了序列槽調試助手;

文檔用到了W25Q64的說明文檔;開發闆的原理圖

開始工作

1. 打開STM32Cube MX進行基本配置,包括下載下傳方式、時鐘頻率、配置序列槽1;

STM32Cube學習筆記-SPI通訊
STM32Cube學習筆記-SPI通訊
STM32Cube學習筆記-SPI通訊
STM32Cube學習筆記-SPI通訊

2. 配置SPI。查閱 開發闆的原理圖,使用的是SPI1同W25Q64連接配接,使用的引腳是PA4、PA5、PA6、PA7,是以配置好引腳,使能SPI1,配置分頻以及SPI1的一些其他配置。

STM32Cube學習筆記-SPI通訊
STM32Cube學習筆記-SPI通訊

3. 說明幾點,配置分頻為4,SPI1挂接的時鐘為APB2上,時鐘頻率為72MHz,那麼問題來了如何判斷我的外設是挂接在哪個時鐘上呢?我貼一下STM32f103的時鐘挂接圖。(切記,F103是M3的核心,F407是M4的核心,時鐘是不一樣的,切記切記)。

STM32Cube學習筆記-SPI通訊
STM32Cube學習筆記-SPI通訊

 那麼STM32F103的SPI支援的時鐘頻率是多少呢?是18MHz,是以配置為4分頻,得到18MHz的SPI時鐘頻率。

STM32Cube學習筆記-SPI通訊

 First Bit配置,most significant bit或者是low significant bit。MSB(Most Significant Bit),即最高有效位,若MSB=1,則表示資料為負值,若MSB=0,則表示資料為正。與其相對應的LSB(Least Significant Bit),意思為最低有效位。MSB位于二進制數的最左側,LSB位于二進制數的最右側。

這一位是配置的雙方通訊約定,就是雙方配置相同就可以了,那麼W25Q64是如何配置的呢?查閱W25Q64的文檔,得到的結果是MSB First。

STM32Cube學習筆記-SPI通訊

4. 然後是配置CPOL和CPHA,這兩個參數是規定了四種通訊模式,即

STM32Cube學習筆記-SPI通訊

 那麼如何了解這四種模式呢?模式0就是

STM32Cube學習筆記-SPI通訊

空閑時為低電平,在奇數沿采樣,即1、3、5、7、9 對應到STM32Cube MX就是下面的

STM32Cube學習筆記-SPI通訊

模式3就是

STM32Cube學習筆記-SPI通訊

空閑時為高電平,在偶數沿采樣,即2、4、6、8、10。了解了模式0和模式3就很容易了解模式1和模式2,不過常用的就是模式0和模式3,因為好操作。 對應到STM32Cube MX就是 

STM32Cube學習筆記-SPI通訊

 而W25Q64支援模式0和模式3,是以這兩個配置都是可以的,這個也是雙方協定的事情。

SPI配置界面最下面的是校驗配置,寫的是無校驗。

5. 上面配置完了,然後就是生成代碼開始讀寫資料,這裡先介紹生成的HAL庫函數。根據前幾篇部落格裡寫的方法,找到SPI的庫函數

初始化相關

HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef *hspi);

HAL_StatusTypeDef HAL_SPI_DeInit(SPI_HandleTypeDef *hspi);

void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi);

void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi);

寄存器相關

#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)

HAL_StatusTypeDef HAL_SPI_RegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID, pSPI_CallbackTypeDef pCallback);

HAL_StatusTypeDef HAL_SPI_UnRegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID);

#endif

資料收發

HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout);

HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout);

HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, uint32_t Timeout);

中斷相關

HAL_StatusTypeDef HAL_SPI_Transmit_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);

HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);

HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData,uint16_t Size);

DMA相關

HAL_StatusTypeDef HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);

HAL_StatusTypeDef HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size);

HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData,  uint16_t Size);

HAL_StatusTypeDef HAL_SPI_DMAPause(SPI_HandleTypeDef *hspi);

HAL_StatusTypeDef HAL_SPI_DMAResume(SPI_HandleTypeDef *hspi);

HAL_StatusTypeDef HAL_SPI_DMAStop(SPI_HandleTypeDef *hspi);

我們比較關心的就是資料收發相關的函數(标紅的函數);

有三個,SPI發送,SPI接收,SPI收發。疑問:有發送函數和接收函數就好,為啥還要搞一個收發函數?

SPI通訊的方法是,output一個資料後input一個資料,就相當于把對方想發給自己的資料給“擠出來”,發送資料,就是直接HAL_SPI_Transmit,得到一個資料就是,給對方發一定長度的資料,把對方想給自己的資料傳回來。假如我想收到對方發的10個資料,那就HAL_SPI_Receive,資料長度設定為10,HAL_SPI_TransmitReceive,用在同時收發的時候,size設定為10.之是以這樣設定是應不同的需求場合。有的情況是同時收同時發。

6. 搞完上面的事情,現在要對FLASH進行操作。

擦除扇區-在位址上寫入資料-從位址上讀取資料。

W25Q64使用的是指令+位址+資料的形式。下面是指令集

STM32Cube學習筆記-SPI通訊
STM32Cube學習筆記-SPI通訊
STM32Cube學習筆記-SPI通訊

 以Read Data為例,就是先發03h,然後發位址高位,然後發位址中位,然後發位址低位,最後再發資料接收到從機的資料。

以Pag Program為例,這個是頁寫,先發02h,然後發位址,然後發要寫的資料。

flash的讀寫過程,擦除扇區 Sector Erase  02H,擦除整片  Block Erase或者Chip Erase;

寫資料之前要Write Enable,寫完可以Write Disable;讀一下晶片的ID等參數可以發90H,4BH,ABH等等,可以根據名稱對晶片進行操作。下面就讀寫一下資料。

先讀ID

STM32Cube學習筆記-SPI通訊

 然後是讀取狀态寄存器,這個是為了在SPI busy的時候等待;

STM32Cube學習筆記-SPI通訊
STM32Cube學習筆記-SPI通訊

然後是寫使能函數和寫失能函數

STM32Cube學習筆記-SPI通訊
STM32Cube學習筆記-SPI通訊

下面是擦除扇區函數

STM32Cube學習筆記-SPI通訊

資料寫入函數

STM32Cube學習筆記-SPI通訊

資料讀取函數 

STM32Cube學習筆記-SPI通訊

主函數調用這些進行資料讀寫:

STM32Cube學習筆記-SPI通訊
STM32Cube學習筆記-SPI通訊
STM32Cube學習筆記-SPI通訊

 本篇部落格介紹了使用STM32Cube MX配置SPI,使STM32f103和W25Q64進行通訊,實作對W25Q64的讀寫操作。親測可用,代碼不夠完善,還需要繼續測試。

繼續閱讀