摘要:上一篇文章我們具體講解了FSMC的原理配置,這一章主要是關(guān)于使用FSMC的SRAM初始化流程,以及使用STM32CubeMX對FSMC進行配置。
一、SRAM初始化流程
通過上面的講解,通過對 FSMC 相關(guān)的寄存器的描述,大家對 FSMC 的原理有了一個初步的認識,如果還不熟悉的朋友,請一定要搜索網(wǎng)絡(luò)資料理解FSMC的原理。只有理解了原理,使用庫函數(shù)才可以得心應(yīng)手。那么在庫函數(shù)中是怎么實現(xiàn)FSMC的配置的呢?FSMC_BCRx,F(xiàn)SMC_BTRx 寄存器在庫函數(shù)是通過什么函數(shù)來配置的呢?下面我們來講解一下 FSMC 相關(guān)的庫函數(shù):
1.1 使能FSMC時鐘
要使用FSMC,當然首先得開啟其時鐘。然后需要把FSMC_D0—15,F(xiàn)SMCA0—18等相關(guān)IO 口,全部配置為復用輸出,并使能各 IO 組的時鐘。
?
RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC,ENABLE);//使能?FSMC?時鐘
?
配置 IO 口為復用輸出的關(guān)鍵行代碼為:
?
GPIO_InitStructure.GPIO_Mode?=?GPIO_Mode_AF;//復用輸出
?
關(guān)于引腳復用映射配置,這在 LCD 實驗章節(jié)也講解非常詳細,調(diào)用函數(shù)為:
?
void?GPIO_PinAFConfig(GPIO_TypeDef*?GPIOx,?uint16_t?GPIO_PinSource,?uint8_t?GPIO_AF);
?
針對每個復用引腳調(diào)用這個函數(shù)即可,例如 GPIOD.0引腳復用映射配置方法為:
?
GPIO_PinAFConfig(GPIOD,GPIO_PinSource0,GPIO_AF_FSMC);//PD0,AF12
?
1.2 FSMC初始化函數(shù)
根據(jù)前面的講解,初始化 FSMC 主要是初始化三個寄存器FSMC_BCRx,F(xiàn)SMC_BTRx,F(xiàn)SMC_BWTRx,那么在固件庫中是怎么初始化這三個參數(shù)的呢?
固件庫提供了 3 個FSMC 初始化函數(shù)分別為:
?
FSMC_NORSRAMInit(); FSMC_NANDInit(); FSMC_PCCARDInit();
?
這三個函數(shù)分別用來初始化 4 種類型存儲器。這里根據(jù)名字就很好判斷對應(yīng)關(guān)系。用來初始化NOR和 SRAM 使用同一個函數(shù) FSMC_NORSRAMInit()。所以我們之后使用的 FSMC 初始化函數(shù)為FSMC_NORSRAMInit()。下面我們看看函數(shù)定義:
?
void?FSMC_NORSRAMInit(FSMC_NORSRAMInitTypeDef* FSMC_NORSRAMInitStruct);
?
這個函數(shù)只有一個入口參數(shù),也就是FSMC_NORSRAMInitTypeDef類型指針變量,這個結(jié)構(gòu)體的成員變量非常多,因為FSMC相關(guān)的配置項很多,但是對于SRAM我們只需要配置對應(yīng)的成員就可以了,并不是所有結(jié)構(gòu)體成員都需要配置。
1.3 SRAM 初始化結(jié)構(gòu)體
?
typedef?struct { ?uint32_t?FSMC_Bank;/*設(shè)置要控制的?Bank?區(qū)域?*/ ?uint32_t?FSMC_DataAddressMux;/*設(shè)置地址總線與數(shù)據(jù)總線是否復用?*/ ?uint32_t?FSMC_MemoryType;/*設(shè)置存儲器的類型?*/ ?uint32_t?FSMC_MemoryDataWidth;/*設(shè)置存儲器的數(shù)據(jù)寬度*/ ?uint32_t?FSMC_BurstAccessMode;/*設(shè)置是否支持突發(fā)訪問模式,只支持同步類型的存儲器?*/? ?uint32_t?FSMC_AsynchronousWait;/*設(shè)置是否使能在同步傳輸時的等待信號,*/ ?uint32_t?FSMC_WaitSignalPolarity;/*設(shè)置等待信號的極性*/ ?uint32_t?FSMC_WrapMode;/*設(shè)置是否支持對齊的突發(fā)模式?*/ ?uint32_t?FSMC_WaitSignalActive;/*配置等待信號在等待前有效還是等待期間有效?*/ ?uint32_t?FSMC_WriteOperation;/*設(shè)置是否寫使能?*/ ?uint32_t?FSMC_WaitSignal;/*設(shè)置是否使能等待狀態(tài)插入?*/ ?uint32_t?FSMC_ExtendedMode;/*設(shè)置是否使能擴展模式?*/ ?uint32_t?FSMC_WriteBurst;/*設(shè)置是否使能寫突發(fā)操作*/ ?/*當不使用擴展模式時,本參數(shù)用于配置讀寫時序,否則用于配置讀時序*/? ?FSMC_NORSRAMTimingInitTypeDef*?FSMC_ReadWriteTimingStruct; ?/*當使用擴展模式時,本參數(shù)用于配置寫時序*/ ?FSMC_NORSRAMTimingInitTypeDef*?FSMC_WriteTimingStruct; }FSMC_NORSRAMInitTypeDef;
?
從這個初始化結(jié)構(gòu)體我們可以看出,前面有13個基本類型(unit32_t)的成員變量,這 13 個參數(shù)是用來配置片選控制寄存器FSMC_BCRx。最后面還有兩個FSMC_NORSRAMTimingInitTypeDef 指針類型的成員變量。前面我們講到,F(xiàn)SMC有讀時序和寫時序之分,所以這里就是用來設(shè)置讀時序和寫時序的參數(shù)了, 也就是說,這兩個參數(shù)是用來配置寄存器SMC_BTRx和FSMC_BWTRx,后面我們會講解到。下面我們主要來看看模式A下的相關(guān)配置參數(shù):
FSMC_Bank 用來設(shè)置使用到的存儲塊標號和區(qū)號,前面講過,我們是使用的存儲塊 1 區(qū)號 3,所以選擇值為FSMC_Bank1_NORSRAM3。
可以選擇的存儲器區(qū)域及區(qū)域?qū)?yīng)的地址范圍
FSMC_MemoryType 用來設(shè)置存儲器類型,我們這里是 SRAM,所以選擇值為FSMC_MemoryType_SRAM。
FSMC_MemoryDataWidth 用來設(shè)置數(shù)據(jù)寬度,可選 8 位還是 16 位,這里我們是 16 位數(shù)據(jù)寬度,所以選擇值為 FSMC_MemoryDataWidth_16b。
FSMC_WriteOperation 用來設(shè)置寫使能,毫無疑問,我們前面講解過我們要向SRAM寫數(shù)據(jù),所以要寫使能,這里我們選擇 FSMC_WriteOperation_Enable。
FSMC_ExtendedMode 是設(shè)置擴展模式使能位,也就是是否允許讀寫不同的時序,這里我們采取的讀寫相同的時序,所以設(shè)置值為 FSMC_ExtendedMode_Disable。
上面的這些參數(shù)是與模式A相關(guān)的,下面我們也來稍微了解一下其他幾個參數(shù)的意義吧:
FSMC_DataAddressMux 用來設(shè)置地址/數(shù)據(jù)復用使能,若設(shè)置為使能,那么地址的低 16位和數(shù)據(jù)將共用數(shù)據(jù)總線,僅對 NOR 和 PSRAM 有效,所以我們設(shè)置為默認值不復用,值FSMC_DataAddressMux_Disable。
FSMC_BurstAccessMode,F(xiàn)SMC_AsynchronousWait,F(xiàn)SMC_WaitSignalPolarity,F(xiàn)SMC_WaitSignalActive,F(xiàn)SMC_WrapMode,F(xiàn)SMC_WaitSignal,F(xiàn)SMC_WriteBurst和FSMC_WaitSignal 這些參數(shù)在成組模式同步模式才需要設(shè)置,大家可以參考中文參考手冊了解相關(guān)參數(shù)的意思。
讀寫時序參數(shù)的兩個變量FSMC_ReadWriteTimingStruct 和FSMC_WriteTimingStruct,它們都是 FSMC_NORSRAMTimingInitTypeDef 結(jié)構(gòu)體指針類型,這兩個參數(shù)在初始化的時候分別用來初始化片選控制寄存器FSMC_BTRx和寫操作時序控制寄存器 FSMC_BWTRx。下面我們看看 FSMC_NORSRAMTimingInitTypeDef 類型的定義:
1.4 SRAM時序結(jié)構(gòu)體
控制 FSMC使用 SRAM 存儲器時主要是配置時序寄存器以及控制寄存器,利用ST 標準庫的 SRAM 時序結(jié)構(gòu)體以及初始化結(jié)構(gòu)體可以很方便地寫入?yún)?shù)。
?
typedef?struct { ?uint32_t?FSMC_AddressSetupTime;/*地址建立時間,0-0xF個HCLK?周期*/ ?uint32_t?FSMC_AddressHoldTime;/*地址保持時間,0-0xF個HCLK?周期*/ ?uint32_t?FSMC_DataSetupTime;/*數(shù)據(jù)保持時間,0-0xF個HCLK?周期*/ ?uint32_t?FSMC_BusTurnAroundDuration;/*總線轉(zhuǎn)換周期,0-0xF個HCLK?周期,在NOR?FLASH才用到,對于SRAM無效?*/ ?uint32_t?FSMC_CLKDivision;/*時鐘分頻因子,1-0xF,若控制異步存儲器,本參數(shù)無效?*/ ?uint32_t?FSMC_DataLatency;/*數(shù)據(jù)延遲時間,若控制異步存儲器,本參數(shù)無效?*/ ?uint32_t?FSMC_AccessMode;/*設(shè)置訪問模式?*/ }FSMC_NORSRAMTimingInitTypeDef;
?
這個結(jié)構(gòu)體成員定義的都是 SRAM 讀寫時序中的各項時間參數(shù),這些成員的的參數(shù)都與 FSMC_BRT 及 FSMC_BWTR 寄存器配置對應(yīng),各個成員介紹如下:
FSMC_AddressSetupTime本成員設(shè)置地址建立時間,即FSMC讀寫時序圖中的 ADDSET 值,它可以被設(shè)置為 0-0xF個HCLK周期數(shù),按STM32標準庫的默認配置,HCLK的時鐘頻率為168MHz,即一個 HCLK周期為 1/168微秒。
FSMC_AddressHoldTime本成員設(shè)置地址保持時間,它可以被設(shè)置為 0-0xF個HCLK周期數(shù)。地址保持時間(ADDHLD)模式A未用到,配置為0x00即可。
FSMC_DataSetupTime本成員設(shè)置數(shù)據(jù)建立時間,即FSMC讀寫時序圖中的 DATAST值,它可以被設(shè)置為0-0xF個HCLK周期數(shù)。
FSMC_BusTurnAroundDuration本成員設(shè)置總線轉(zhuǎn)換周期,在NOR FLASH存儲器中,地址線與數(shù)據(jù)線可以分時復用,總線轉(zhuǎn)換周期就是指總線在這兩種狀態(tài)間切換需要的延時,防止沖突。但是在控制其它存儲器時(如SRAM)這個參數(shù)無效,配置為0即可。
FSMC_CLKDivision本成員用于設(shè)置時鐘分頻,它以 HCLK時鐘作為輸入,經(jīng)過 FSMC_CLKDivision分頻后輸出到 FSMC_CLK引腳作為通訊使用的同步時鐘。控制其它異步通訊的存儲器時這個參數(shù)無效,我們的SRAM屬于異步通訊的存儲器,用不到這個參數(shù),所以配置為 0即可。
FSMC_DataLatency本成員設(shè)置數(shù)據(jù)保持時間,它表示在讀取第一個數(shù)據(jù)之前要等待的周期數(shù),該周期指同步時鐘的周期,本參數(shù)僅用于同步 NOR FLASH類型的存儲器,控制其它類型的存儲器時這個參數(shù)無效,我們的SRAM屬于異步通訊的存儲器,用不到這個參數(shù),所以配置為0即可。
FSMC_AccessMode本成員設(shè)置存儲器訪問模式,不同的模式下 FSMC訪問存儲器地址時引腳輸出的時序不一樣,可選 FSMC_AccessMode_A/B/C/D 模式。一般來說控制 SRAM 時使用A模式,其實就是模式A,在控制SRAM是也沒有見到過用其他模式的。
所以綜上述所我們這7個成員變量,我們的SRAM使用到了其中的3個,其他的四個是NOR FLASH需要配置的,其他的4個配置為0就可以了。具體的配置如下。
?
//地址建立時間(ADDSET)為1個HCLK,1/168M?=?6ns readWriteTiming.FSMC_AddressSetupTime?=?0x00;//(0+1)個HCLK周期=6ns?>0ns?滿足要求 //數(shù)據(jù)保持時間(DATAST)+?1個HCLK?=?9/168M=54ns(對EM的SRAM芯片) readWriteTiming.FSMC_DataSetupTime?=?0x08;//(8+1)個HCLK周期=54ns?>25ns?滿足要求? //以上的設(shè)置滿足6>0 54>25 54+6>55三個條件,所以設(shè)置是合理的。 //以下配置跟異步SRAM無關(guān),默認設(shè)置為0就可以了 //地址保持時間(ADDHLD)模式A未用到 readWriteTiming.FSMC_AddressHoldTime?=?0x00;? //設(shè)置總線轉(zhuǎn)換周期,僅用于復用模式的NOR操作(這里是SRAM,不用管) readWriteTiming.FSMC_BusTurnAroundDuration?=?0x00; //設(shè)置時鐘分頻,僅用于同步類型的存儲器(這里是異步型的SRAM,不用管) readWriteTiming.FSMC_CLKDivision?=?0x00; //數(shù)據(jù)保持時間,僅用于同步型的NOR(這里是異步型的SRAM,不用管) readWriteTiming.FSMC_DataLatency?=?0x00; //選擇匹配SRAM的模式 readWriteTiming.FSMC_AccessMode?=?FSMC_AccessMode_A;
?
上面我們設(shè)置了FSMC_AddressSetupTime 地址建立時間為0,F(xiàn)SMC_DataSetupTime 數(shù)據(jù)保持時間為8,為什么要這樣設(shè)置呢?
這就需要看SRAM的時序圖和FSMC模式A的時序圖了,只有在時序圖中才能找到答案,同時我們在操作別的存儲器時也是需要通過時序圖來配置具體的參數(shù)的。下面就來看看時序圖吧。
IS62WV51216數(shù)據(jù)手冊上的SRAM 的讀時序 | IS62WV51216翻譯過來的SRAM 的讀時序 |
IS62WV51216數(shù)據(jù)手冊上的SRAM 的寫時序 | IS62WV51216翻譯過來的SRAM 的寫時序 |
STM32F4參考手冊FSMC的讀時序 | STM32F4參考手冊FSMC的寫時序 |
IS62WV51216讀時序關(guān)鍵特性 IS62WV51216寫時序關(guān)鍵特性
使用模式A,讀寫共用時序(共用時序時,以寫時序為準),配置代碼如下:
?
//地址建立時間(ADDSET)為1個HCLK,1/168M?=?6ns readWriteTiming.FSMC_AddressSetupTime?=?0x00;//(0+1)個HCLK周期=6ns?>0ns?滿足要求 //地址保持時間(ADDHLD)模式A未用到 readWriteTiming.FSMC_AddressHoldTime?=?0x00;? //數(shù)據(jù)保持時間(DATAST)+?1個HCLK?=?9/168M=54ns(對EM的SRAM芯片) readWriteTiming.FSMC_DataSetupTime?=?0x08;//(8+1)個HCLK周期=54ns?>25ns?滿足要求?
?
為什么地址建立時間是0ns呢?因為從IS62WV51216寫時序關(guān)鍵特性中可以看到,Address Setup Time為0,所以配置時,地址建立時間要等于0。
地址保持時間模式A未用到,所以配置為0。
數(shù)據(jù)建立時間為什么是54ns呢?因為從IS62WV51216寫時序關(guān)鍵特性中可以看到,Dataup to Write End最小值為30ns,所以配置時,數(shù)據(jù)保持時間要大于30ns。至于選擇的54ns并不是嚴格按照手冊時間來的,這需要實際調(diào)試才能確定具體值。
那為什么數(shù)據(jù)建立時間配置為8,但卻是9個HCLK周期時間呢?從STM32中文參考手冊的時序圖中可以看到,模式A寫入時序的數(shù)據(jù)建立時間為:數(shù)據(jù)建立時間=HCLK周期+1,初始化程序時,如果設(shè)置DATAST=0,則實際數(shù)據(jù)建立周期為1,即實際數(shù)據(jù)建立周期比DATAST值多1個HCLK周期。
經(jīng)過上面的設(shè)置后寫一次操作的時間就是(0+1)*6ns+(8+1)*6ns=60ns>55ns,是滿足要求的。
參數(shù)確定大體就是這樣的思路,其他模式及不同的芯片確定參數(shù)的思路是一樣的。
最后是在帖子中看到的關(guān)于時序的講解,挺有趣,一并放在文章中。
“
先搞清邏輯關(guān)系。這是CPU讀存儲器的時序。CPU索取,存儲器付出。我有很多單元,你要讀我,至少要把那個單元的門牌號告訴我吧?——這就是地址線,由CPU填寫(輸出);地址線上非1即0,你放不放地址都這樣的,所以,你要告訴我什么時候是“地址”,什么時候是“垃圾”吧?——這就是OE線下降沿的作用,也要CPU填寫。(一般來說,要在地址穩(wěn)定以后,OE才發(fā)出下降沿。上面圖沒有給出這個差別。)好了,CPU該辦的手續(xù)已經(jīng)完了,球到了存儲器一邊。我要去這個單元找東西,總需要點時間吧?——這就是OE下降沿以后,RAM發(fā)出數(shù)據(jù)的時間間隔。艾瑪,累死我了,你要的東西找到了,我放上去了!按說,數(shù)據(jù)放到總線上了,可是CPU如何才能知道數(shù)據(jù)來了呢?因為不論是數(shù)據(jù)還是垃圾,那電線上面總有1、0這些東西。這時出現(xiàn)不同解決方法了。一種方法,由存儲器給CPU發(fā)出一個通知信號:好了,快來拿!這個信號通常叫做 Data Available,數(shù)據(jù)可得,簡寫 DAV,可能有人見過。CPU接到這個信號,自然會做。另一種方法,有老大強勢規(guī)定:OE下降沿之后,你丫必須在1秒鐘之內(nèi)把東西交出來!我只管時間到就來拿!這是多數(shù)存儲器遵守的規(guī)定。這兩種方法,由于是不同的公司提出的,經(jīng)常以公司名字來命名。Motorola總線,intel總線,聽說過吧?OK,明白這些意思,稍微想一想,應(yīng)當就可以理解各種時序的時間了。以后再不用問人了。另外,手冊里經(jīng)??梢钥吹?,這些時間一般會有最大值、最小值,有些只給出一項。比如上面提到,從OE下降沿到存儲器交出數(shù)據(jù)的時間,在存儲器手冊里面,這個時間只會給出最大值。因為用戶必須按“最長時間”操作,不能有僥幸心理。給出最小值沒有實際意義。
”
1.5 FSMC使能
FSMC 對不同的存儲器類型同樣提供了不同的使能函數(shù):
?
void?FSMC_NORSRAMCmd(uint32_t?FSMC_Bank,?FunctionalState?NewState); void?FSMC_NANDCmd(uint32_t?FSMC_Bank,?FunctionalState?NewState); void?FSMC_PCCARDCmd(FunctionalState?NewState);
?
這個就比較好理解,我們這里不講解,我們是SRAM,所以使用的是第一個函數(shù)。
?
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM3,?ENABLE);?//?使能?BANK3
?
通過以上幾個步驟,我們就完成了FSMC的配置,可以訪問IS62WV51216有了,這里還需要注意,因為我們使用的是BANK1的區(qū)域3,所以 HADDR[27:26]=10,故外部內(nèi)存的首地址為0X68000000。
二、硬件連接
下面來說一下在STM32F407中SRAM的硬件連接:對于FSMC來說,它已經(jīng)集成到了單片機內(nèi)部,它的提供給的管腳已經(jīng)確定了,是不改動的,這個可以參考STM32對應(yīng)芯片的 Datasheet。唯具有靈活性的就是FSMC_NE,具體用哪個 FSMC_NE管腳來和你的SRAM相連,當然是你的自由,但是不要忘了,你要找到你選的 FSMC_NE所對應(yīng)的地址范圍,不然寫程序的時候就搞不清喏!
我們需要將SRAM芯片和STM32單片機連接起來,就要來看看他們之間的連線和接口
SRAM功能框圖 | FSMC引腳圖 |
SRAM芯片引腳圖 | SRAM的AD原理圖 |
STM32FSMC外設(shè) | SRAM內(nèi)存芯片 | 引腳說明 |
---|---|---|
FSMC_NE3 | ? | 片選信號,低電平有效 |
FSMC_OE | ? | 輸出使能信號,低電平有效 |
NWE | ? | 寫使能信號,低電平有效 |
FSMC_NBL0 | ? | 低字節(jié)控制信號 |
FSMC_NBL1 | ? | 高字節(jié)控制信號 |
FMSC_A[0:18] | ? | 地址信號線 |
SMC_D[0:15] | ? | 數(shù)據(jù)信號線 |
備注:在MCU芯片手冊中的信號引腳一般有前綴,前綴“ N ”表示相關(guān)的信號為低電平有效。在數(shù)字芯片手冊中的信號引腳一般在引腳上面加一條橫線表示低電平有效。
tRC是讀周期時間,它表示對芯片連續(xù)倆次讀操作之間的最小間隔時間。
tAA是讀出時間,它表示地址線上的有效地址給出之后,經(jīng)過譯碼電路,驅(qū)動電路的延時,到讀出所選單元內(nèi)容,并經(jīng)I/O電路延時,直到數(shù)據(jù)在數(shù)據(jù)總線上穩(wěn)定出現(xiàn)所需要的時間。
tOHA是輸出保持時間,它表示地址失效之后,數(shù)據(jù)線上的有效數(shù)據(jù)維持的時間,以確保所讀的數(shù)據(jù)真實可靠。
搜索并選中芯片STM32F407ZGT6
配置時鐘源
如果選擇使用外部高速時鐘(HSE),則需要在System Core中配置RCC;如果使用默認內(nèi)部時鐘(HSI),這一步可以略過;
這里我都使用外部時鐘:
調(diào)試選項配置
默認沒有配置下載引腳,燒錄之后下載器將無法再檢測到,這里我使用JLink,所以配置為SW選項:
配置串口
開發(fā)板板載了一個CH340換串口,連接到USART1,但是引腳不是默認引腳,需要手動修改。
接下來開始配置USART1:
配置FSMC外設(shè)
FSMC配置
我們板子上面的雙口SRAM原理圖如下:
通過原理圖可以看出:
數(shù)據(jù)總線位寬使用了8bit:FSMC D0 - FSMC D7;
地址總線位寬使用了15bit:FSMC A0 - FSMC A14;
片選信號線:使用FSMC NE3,對應(yīng)使用Bank1的Bank3子區(qū)域;
通用信號線:FSMC_NOE、FSMC_NWE;
數(shù)據(jù)掩碼信號線:使用 FMC NBL0 和 FMC NBL1,分別控制輸出高8位還是低8位;
根據(jù)這些信息,在STM32CubeMX中先配置SRAM1的基本設(shè)置:
SRAM基本參數(shù)配置
這部分信息直接配置即可:
配置情況如下:
配置時鐘樹
STM32F407ZGT6的最高主頻到168M,使HCLK=168Mhz即可:
生成工程設(shè)置
生成代碼
點擊GENERATE CODE即可生成MDK-V5工程:
審核編輯:湯梓紅
評論
查看更多