STM32實例教程,帶你了解FSMC的功能和用法
FSMC 簡介
STM32F103 100 引腳以上系列芯片都帶有 FSMC 接口,我們開發板上使用的是 STM32F103ZET6,因此也具有FSMC 接口。
FSMC(Flexible Static Memory Controller,靈活的靜態存儲控制器)是
STM32 系列采用一種新型的存儲器擴展技術,能夠連接同步、異步存儲器和 16位 PC 存儲卡。STM32通過FSMC可以與SRAM、 ROM、 PSRAM、 NOR Flash和NANDFlash等存儲器的引腳直接相連。STM32F1的FSMC內部框圖如下圖所示:(大家也可以查看 《STM32F10x中文參考手冊》-19 靈活的靜態存儲控制器(FSMC)-19.2 章節內容)
我們把 FSMC 結構框圖分成3 個子模塊,按照順序依次進行簡單介紹。
(1)標號 1:時鐘輸入
FSMC 的時鐘來至時鐘控制器HCLK,在前面我們講解“存儲器與寄存器”時,我們知道,AHB 區域內包含 FSMC 模塊,所以如果要使用 FSMC,必須使能 AHB 總線時鐘。
(2)標號 2:AHB 接口
CPU 和其它 AHB 總線主設備可通過該 AHB 從設備接口訪問外部靜態存儲
器。FSMC 可通過一個寄存器組進行配置。有關 NOR Flash/PSRAM 控制寄存器的詳細說明,請參《STM32F10x 中文參考手冊》-19 靈活的靜態存儲控制器(FSMC)-19.5章節內容。
(3)FSMC 外部設備
STM32F1 的 FSMC 將外部設備分為 2 類:NOR/PSRAM 設備、NAND/PC 卡設備。他們共用地址數據總線等信號,但具有不同的 CS 以區分不同的設備。
本實驗我們使用的是FSMC 的 NOR/PSRAM 存儲器控制器部分,即把TFTLCD當成 SRAM 設備使用。為什么可以把 TFTLCD 當成 SRAM 設備用,這個首先要了解 NOR/PSRAM 存儲器控制器的接口信號,其接口信號功能如下:
從上圖中可以看出外部 SRAM 的控制一般有:地址線(如 A0A25)、雙向數據線(如 D0D15)、寫信號( NWE)、讀信號( NOE)、片選信號(NE[x]),如果 SRAM 支持字節控制,那么還有 UB/LB 信號。而 TFTLCD 的信號我們在上一節有介紹,包括:RS、DB0-DB15、 WR、 RD、 CS、 RST 等,其中真正在操作 LCD 的時候需要用到的就只有:RS、 DB0-DB15、 WR、 RD、 CS。這樣一來它們的操作接口信號完全類似,唯一不同就是 TFTLCD 有 RS 信號,但是沒有地址信號。
TFTLCD 通過 RS 信號來決定傳送的數據是數據還是命令,本質上可以理解
為一個地址信號,比如我們把 RS 接在 A0 上面,那么當 FSMC 控制器寫地址 0的時候,會使得 A0 變為 0,對 TFTLCD 來說,就是寫命令。而 FSMC 寫地址 1的時候, A0 將會變為 1,對 TFTLCD 來說,就是寫數據了。這樣,就把數據和命令區分開了,他們其實就是對應 SRAM 操作的兩個連續地址。當然 RS 也可以接在其他地址線上,我們STM32F1 開發板是把 RS 連接在 A10 上面的。
知道了可以將 TFTLCD 當做 SRAM 設備用,下面我們就來看下 FSMC 的外部設備地址映射,從 FSMC 的角度,外部存儲器被劃分為 4 個固定大小的存儲區域(Bank),每個存儲區域的大小為 256 MB,共 1GB 空間。如下圖所示:
本實驗使用到的是Bank1,所以我們只講解這塊存儲區域,其他的區域大家可參考《STM32F10x 中文參考手冊》-19 靈活的靜態存儲控制器(FSMC)章節內容。
存儲區域 1 可連接多達 4 個 NOR Flash 或 PSRAM 存儲器器件。此存儲區域被劃分為 4 個 NOR/PSRAM 區域, 帶 4 個專用片選信號。存儲區域 2 和 3 用于連接 NAND Flash 器件(每個存儲區域一個器件)。存儲區域 4 用于連接 PC卡設備。對于每個存儲區域, 所要使用的存儲器類型由用戶在配置寄存器中定義。
STM32F1 的 FSMC 各 Bank 配置寄存器如下圖所示:
STM32F1 的 FSMC 存儲塊 1 ( Bank1) 又被分為 4 個區, 每個區管理 64M 字節空間,每個區都有獨立的寄存器對所連接的存儲器進行配置。 Bank1 的 256M字節空間由 28 根地址線 (HADDR[27:0]) 尋址。 這里 HADDR 是內部 AHB 地址 總線, 其 中 HADDR[25:0] 來自外部存儲器地 址 FSMC_A[25:0], 而 HADDR[26:27]對 4 個區進行尋址。如下圖所示:
本實驗我們使用的是 Bank1 的第 4 區,即起始地址為 0X6C000000。這里要特別注意 HADDR[25:0], HADDR[25:0]包含外部存儲器地址。由于 HADDR 為字節地址,而存儲器按字尋址,所以根據存儲器數據寬度不同,實際向存儲器發送的地址也將有所不同,如下圖所示:
如果外部存儲器的寬度為 8 位, FSMC 將使用內部的 HADDR[25:0] 地址來作為對外部存儲器的尋址地址 FSMC_A[25:0]。
這里請大家特別留意,如果外部存儲器的寬度為 16 位, FSMC 將使用內部的 HADDR[25:1] 地址來作為對外部存儲器的尋址地址 FSMC_A[24:0],相當于右移了一位,在后面我們設置 A10 地址的時候就要使用到。無論外部存儲器的寬度為 16 位還是 8 位, FSMC_A[0] 都應連接到外部存儲器地址 A[0]。
另外,HADDR[27:26]的設置,是不需要我們干預的,比如:當你選擇使用Bank1 的第三個區,即使用 FSMC_NE3 來連接外部設備的時候,即對應了
HADDR[27:26]=10,我們要做的就是配置對應第 3 區的寄存器組,來適應外部設備即可。FSMC 的各 Bank配置寄存器在上圖 38.1.2.3 以列出。
對于 NOR FLASH 控制器,主要是通過 FSMC_BCRx、 FSMC_BTRx 和
FSMC_BWTRx 寄存器設置(其中 x=1~4,對應 4 個區)。通過這 3 個寄存器,可以設置 FSMC 訪問外部存儲器的時序參數, 拓寬了可選用的外部存儲器的速度范圍。
FSMC 的 NOR FLASH 控制器支持同步和異步突發兩種訪問方式。選用同步突發訪問方式時, FSMC 將 HCLK(系統時鐘)分頻后,發送給外部存儲器作為同步時鐘信號 FSMC_CLK。此時需要的設置的時間參數有 2 個:
①HCLK 與 FSMC_CLK 的分頻系數(CLKDIV),可以為 2~16 分頻;
②同步突發訪問中獲得第 1 個數據所需要的等待延遲(DATLAT)。
對于異步突發訪問方式, FSMC 主要設置 3 個時間參數:地址建立時間
(ADDSET)、 數據建立時間(DATAST)和地址保持時間(ADDHLD)。FSMC 綜合了 SRAM/ROM、 PSRAM 和 NORFlash 產品的信號特點,定義了 4 種不同的異步時序模型。選用不同的時序模型時,需要設置不同的時序參數,如下圖所列:
在實際擴展時,根據選用存儲器的特征確定時序模型,從而確定各時間參數與存儲器讀/寫周期參數指標之間的計算關系;利用該計算關系和存儲芯片數據手冊中給定的參數指標,可計算出 FSMC 所需要的各時間參數,從而對時間參數寄存器進行合理的配置。
本實驗我們使用異步模式 A( ModeA)方式來控制 TFTLCD,模式 A 的讀操作時序如下圖所示:
模式 A 支持獨立的讀寫時序控制, 這個對我們驅動 TFTLCD 來說非常有用,因為 TFTLCD 在讀的時候,一般比較慢,而在寫的時候可以比較快,如果讀寫用一樣的時序,那么只能以讀的時序為基準,從而導致寫的速度變慢,或者在讀數據的時候,重新配置 FSMC 的延時,在讀操作完成的時候,再配置回寫的時序,這樣雖然也不會降低寫的速度,但是頻繁配置,比較麻煩。而如果有獨立的讀寫時序控制,那么我們只要初始化的時候配置好,之后就不用再配置,既可以滿足速度要求,又不需要頻繁改配置。模式 A 的寫操作時序如下圖所示:
模式 A 讀寫時序中的 ADDSET 與 DATAST,是通過不同的寄存器設置的。由于篇幅限制, 本文并沒有對 FSMC 相關寄存器進行介紹, 大家可以參考 《STM32F10x中文參考手冊》-19 靈活的靜態存儲控制器(FSMC)章節寄存器內容,里面有詳細的講解。不過,這里還要給大家做下科普,在標準庫的寄存器定義里面,并沒有定義 FSMC_BCRx、 FSMC_BTRx、 FSMC_BWTRx 等這個單獨的寄存器,而是將他們進行了一些組合。
FSMC_BCRx 和 FSMC_BTRx, 組合成 BTCR[8]寄存器組, 他們的對應關系如下:
BTCR[0]對應 FSMC_BCR1, BTCR[1]對應 FSMC_BTR1
BTCR[2]對應 FSMC_BCR2, BTCR[3]對應 FSMC_BTR2
BTCR[4]對應 FSMC_BCR3, BTCR[5]對應 FSMC_BTR3
BTCR[6]對應 FSMC_BCR4, BTCR[7]對應 FSMC_BTR4
FSMC_BWTRx 則組合成 BWTR[7],他們的對應關系如下:
BWTR[0]對應 FSMC_BWTR1, BWTR[2]對應 FSMC_BWTR2,
BWTR[4]對應 FSMC_BWTR3, BWTR[6]對應 FSMC_BWTR4,
BWTR[1]、 BWTR[3]和 BWTR[5]保留,沒有用到。
FSMC 內部還是比較復雜的,如果看不懂的可以暫時放下,因為我們使用的是庫函數開發,只需簡單配置下即可使用。