STM32 SPI通訊_摘自


  • 通信方式:高速全雙工
    • 作用:  主機與從機之間同步交換數據 
    •   時鍾:  最大18Mhz,支持DMA,可以配置SPI協議
  • 通信線
    •   MISO 主輸入從輸出
        MOSI 主輸出從輸入
        SCLK 時鍾信號,主設備產生
        CS 片選信號,主設備控制

 

 

  • 協議層
    • 起始信號
      • NSS 信號由高變低
    • 終止信號
      • NSS 信號由低變高
    • 數據有效性
      • 采樣:
        • MOSI 及 MISO 的數據在 SCK 的上升沿期間變化輸出,在 SCK 的下降沿時被采樣。
        • 即在 SCK 的下降沿時刻,MOSI 及 MISO 的數據有效,高電平時表示數據“1”,為低電平時表示數據“0”。在其它時刻,數據無效,
      • 觸發:
        • MOSI 及 MISO 的數據在 SCK 的上升沿期間變化輸出,在 SCK 的下降沿時被采樣.
    • 通訊模式
      • 共4種,區別於 SCK 的時鍾狀態以及數據采樣時刻

 

 

 

  • SPI外設
    • 時鍾:
      • SPI1 是 APB2 上的設備,最高通信速率達 36Mbtis/s,SPI2、SPI3 是 APB1 上的設備,最高通信速率為 18Mbits/s
    • 引腳
  • 通訊過程
    • (1) 控制 NSS 信號線,產生起始信號(NSS拉低,圖中沒有畫出);
    • (2) 把要發送的數據寫入到“數據寄存器 DR”中,該數據會被存儲到發送緩沖區;
    • (3) 通訊開始,SCK 時鍾開始運行。MOSI 把發送緩沖區中的數據一位一位地傳輸出去;MISO 則把數據一位一位地存儲進接收緩沖區中;
    • (4) 當發送完一幀數據的時候,“狀態寄存器 SR”中的“TXE 標志位”會被置 1,表示傳輸完一幀,發送緩沖區已空;類似地,當接收完一幀數據的時候,“RXNE標志位”會被置 1,表示傳輸完一幀,接收緩沖區非空;
    • (5) 等待到“TXE 標志位”為 1 時,若還要繼續發送數據,則再次往“數據寄存器DR”寫入數據即可;等待到“RXNE 標志位”為 1 時,通過讀取“數據寄存器DR”可以獲取接收緩沖區中的內容。
  • 處理收發數據
    • 中斷方式
      • 使能TXE 或 RXNE 中斷,TXE 或 RXNE 置 1 時會產生 SPI 中斷信號,進入同一個中斷服務函數,到 SPI 中斷服務程序后,可通過檢查寄存器位來了解是哪一個事件,再分別進行處理
    • DMA方式
      • 使用 DMA 方式來收發“數據寄存器 DR”中的數據。
  • 配置流程

    •   配置相關引腳的復用功能,使能 SPI2 時鍾 ,設置 SPI2 的相關引腳為復用輸出,這樣才會連接到 SPI2 
    •   初始化 SPI2,設置 SPI2 工作模式 
    •   使能 SPI2 
    •   SPI 傳輸數據 
    •   查看 SPI 傳輸狀態 

裸機--SPI--FLASH讀寫
  • 硬件連接
    • WP 引腳可控制寫保護功能,當該引腳為低電平時,禁止寫入數據。我們直接接電源,不使用寫保護功能。
  • 指令表
    • 帶括號的字節參數,方向為 FLASH 向主機傳輸,即命令響應,不帶括號的則為主機向 FLASH 傳輸
    • 表中“A0~A23”指 FLASH 芯片內部存儲器組織的地址;
    • “M0~M7”為廠商號(MANUFACTURER ID);
    • “ID0-ID15”為 FLASH 芯片的ID;
    • “dummy”指該處可為任意數據;
    • “D0~D7”為 FLASH 內部存儲矩陣的內容。

 

  • FLASH操作
    • 一般流程
      • CS拉低
      • 發送指令
      • 操作數據
      • CS拉高
      • 等待
    • 扇區擦除
      • 只能把原來為“1”的數據位改寫成“0”,而原來為“0”的數據位不能直接改寫為“1”。在寫入前,必須要對目標存儲矩陣進行擦除操作,把矩陣中的數據位擦除為“1”,在數據寫入的時候,如果要存儲數據“1”,那就不修改存儲矩陣 ,在要存儲數據“0”時,才更改該位。
      • FLASH 芯片的最小擦除單位為扇區(Sector),而一個塊(Block)包含 16 個扇區,
      • 流程:
        • 發送寫使能
        • CS拉低
        • 發送擦除指令
        • 發送擦除地址
        • CS拉高
        • 等待擦除完畢
1 /**
2 * @brief 擦除 FLASH 扇區
3 * @param SectorAddr:要擦除的扇區地址
4 * @retval 無
5 */
6 void SPI_FLASH_SectorErase(u32 SectorAddr)
7 {
8     /* 發送 FLASH 寫使能命令 */
9     SPI_FLASH_WriteEnable();
10     SPI_FLASH_WaitForWriteEnd();
11     /* 擦除扇區 */
12     /* 選擇 FLASH: CS 低電平 */
13     SPI_FLASH_CS_LOW();
14     /* 發送扇區擦除指令*/
15     SPI_FLASH_SendByte(W25X_SectorErase);
16     /*發送擦除扇區地址的高位*/
17     SPI_FLASH_SendByte((SectorAddr & 0xFF0000) >> 16);
18     /* 發送擦除扇區地址的中位 */
19     SPI_FLASH_SendByte((SectorAddr & 0xFF00) >> 8);
20     /* 發送擦除扇區地址的低位 */
21     SPI_FLASH_SendByte(SectorAddr & 0xFF);
22     /* 停止信號 FLASH: CS 高電平 */
23     SPI_FLASH_CS_HIGH();
24     /* 等待擦除完畢*/
25     SPI_FLASH_WaitForWriteEnd();
26 }

 

 

 

  • 頁寫入
    • 最多寫入256字節
    • 一般以扇區單位進行讀寫
    • 流程
      • 發送寫使能
      • CS拉低
      • 發送寫指令
      • 發送寫地址
      • 寫入數據
      • CS拉高
      • 等待
1 /**
2     * @brief 對 FLASH 按頁寫入數據,調用本函數寫入數據前需要先擦除扇區
3     * @param pBuffer,要寫入數據的指針
4     * @param WriteAddr,寫入地址
5     * @param NumByteToWrite,寫入數據長度,必須小於等於頁大小
6     * @retval 無
7 */
8 void SPI_FLASH_PageWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
9 {
10     /* 發送 FLASH 寫使能命令 */
11     SPI_FLASH_WriteEnable();
12
13     /* 選擇 FLASH: CS 低電平 */
14     SPI_FLASH_CS_LOW();
15     /* 寫送寫指令*/
16     SPI_FLASH_SendByte(W25X_PageProgram);
17     /*發送寫地址的高位*/
18     SPI_FLASH_SendByte((WriteAddr & 0xFF0000) >> 16);
19     /*發送寫地址的中位*/
20     SPI_FLASH_SendByte((WriteAddr & 0xFF00) >> 8);
21     /*發送寫地址的低位*/
22     SPI_FLASH_SendByte(WriteAddr & 0xFF);
23
24     if (NumByteToWrite > SPI_FLASH_PerWritePageSize)
25     {
26         NumByteToWrite = SPI_FLASH_PerWritePageSize;
27         FLASH_ERROR("SPI_FLASH_PageWrite too large!");
28     }
29
30     /* 寫入數據*/
31     while (NumByteToWrite--)
32     {
33         /* 發送當前要寫入的字節數據 */
34         SPI_FLASH_SendByte(*pBuffer);
35         /* 指向下一字節數據 */
36         pBuffer++;
37     }
38
39     /* 停止信號 FLASH: CS 高電平 */
40     SPI_FLASH_CS_HIGH();
41
42     /* 等待寫入完畢*/
43     SPI_FLASH_WaitForWriteEnd();
44 }

 

 

  • 讀取數據
    • 流程
      • CS拉低
      • 發送讀指令
      • 發送讀地址
      • 讀取數據
      • CS拉高


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM