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