什么是FSMC
FSMC(Flexible Static Memory Controller,可變靜態(tài)存儲(chǔ)控制器)是STM32系列采用的一種新型的存儲(chǔ)器擴(kuò)展技術(shù)。在外部存儲(chǔ)器擴(kuò)展方面具有獨(dú)特的優(yōu)勢(shì),可根據(jù)系統(tǒng)的應(yīng)用需要,方便地進(jìn)行不同類型大容量靜態(tài)存儲(chǔ)器的擴(kuò)展。
STM32系列微控制器為用戶提供了豐富的選擇,可適用于工業(yè)控制、智能家電、建筑安防、醫(yī)療設(shè)備以及消費(fèi)類電子產(chǎn)品等多方位嵌入式系統(tǒng)設(shè)計(jì)。STM32系列采用一種新型的存儲(chǔ)器擴(kuò)展技術(shù)——FSMC,在外部存儲(chǔ)器擴(kuò)展方面具有獨(dú)特的優(yōu)勢(shì),可根據(jù)系統(tǒng)的應(yīng)用需要,方便地進(jìn)行不同類型大容量靜態(tài)存儲(chǔ)器的擴(kuò)展。
fsmc就是為了擴(kuò)展內(nèi)存的,如我們?cè)赟TM32芯片外添加一個(gè)sram芯片,那么我們只需要把 sram芯片的地址線和數(shù)據(jù)線和STM32連接后,然后將內(nèi)核規(guī)定的地址數(shù)賦給sram的地址,那么我們就可以通過(guò)內(nèi)核規(guī)定的地址去訪問(wèn)sram芯片了。
STM32_FMSC使用理解
第一個(gè)角度理解
? ? ? ? STM32有FSMC(其實(shí)其他芯片基本都有類似的總線功能),F(xiàn)SMC的好處就是你一旦設(shè)置好之后,WR(寫)、RD(讀)、DB0-DB15這些控制線和數(shù)據(jù)線,都是FSMC自動(dòng)控制的。打個(gè)比方,當(dāng)你在程序中寫到:
*(volatile unsigned short int *)(0x60000000)=val;
那么FSMC就會(huì)自動(dòng)執(zhí)行一個(gè)寫的操作,其對(duì)應(yīng)的主控芯片的WE、RD這些腳,就會(huì)呈現(xiàn)出寫的時(shí)序出來(lái)(即WE=0,RD=1),數(shù)據(jù)val的值也
會(huì)通過(guò)DB0-15自動(dòng)呈現(xiàn)出來(lái)(即FSMC-D0:FSMC-D15=val )。地址0x60000000會(huì)被呈現(xiàn)在數(shù)據(jù)線上(即A0-A25=0,地址線的對(duì)應(yīng)最麻煩,要根據(jù)具體情況來(lái),好好看看FSMC手冊(cè))。
那么在硬件上面,我們需要做的,僅僅是MCU和LCD控制芯片的連接關(guān)系:
WE-WR,均為低電平有效
RD-RD,均為低電平有效
FSMC-D0-15接LCD DB0-15
FSMC_NE1--CS接PD7
連接好之后,讀寫時(shí)序都會(huì)被FSMC自動(dòng)完成。但是還有一個(gè)很關(guān)鍵的問(wèn)題,就是RS沒(méi)有接因?yàn)樵贔SMC里面,根本就沒(méi)有對(duì)應(yīng)RS。怎么辦呢?這個(gè)時(shí)候,有一個(gè)好方法,就是用某一根地址線來(lái)接RS。比如我們選擇了A16這根地址線來(lái)接,那么當(dāng)我們要寫寄存器的時(shí)候,我們需要RS,也就是A16(RS為高)置高。軟件中怎么做呢?也就是將FSMC要寫的地址改成0x60020000,如下:
*(volatile unsigned short int *)(0x60020000)=val;
這個(gè)時(shí)候,A16在執(zhí)行其他FSMC的同時(shí)會(huì)被拉高,因?yàn)锳0-A18要呈現(xiàn)出地址0x60020000。0x60020000里面的Bit17=1,就會(huì)導(dǎo)致A16為1。
當(dāng)要讀數(shù)據(jù)時(shí),地址由0x60020000改為了0x60000000,這個(gè)時(shí)候A16就為0了。
那么有朋友就會(huì)有疑問(wèn),第一,為什么地址是0x6xxxxxxx而不是0x0xxxxxxx;第二,CS怎么接;第三,為什么Bit17對(duì)應(yīng)A16?
RS問(wèn)題:RS為0表示;讀寫寄存器;RS為1,讀寫數(shù)據(jù)RAM;
先來(lái)看前兩個(gè)問(wèn)題,大家找到STM32的FSMC手冊(cè),在FSMC手冊(cè)里面,我們很容易找到,F(xiàn)SMC將0x60000000-0x6fffffff的地址用作NOR/PRAM(
共256M地址范圍)。而這個(gè)存儲(chǔ)塊,又被分成了四部分,每部分64M地址范圍。當(dāng)對(duì)其中某個(gè)存儲(chǔ)塊進(jìn)行讀寫時(shí),對(duì)應(yīng)的NEx就會(huì)置低。這里,
就解決了我們兩個(gè)問(wèn)題,
第一,LCD的操作時(shí)序,和NOR/PRAM是一樣的(為什么一樣自己找找NOR/PRAM的時(shí)序看看),所以我們選擇0x6xxxxxxx
這個(gè)地址范圍(選擇這個(gè)地址范圍,操作這個(gè)地址時(shí),F(xiàn)SMC就會(huì)呈現(xiàn)出NOR/PRAM的時(shí)序)。
第二,我們可以將NEx連接到LCD的CS,只要我們操作
的地址是第一個(gè)存儲(chǔ)塊內(nèi)即可(即0-0x3ffffff地址范圍)。
第三個(gè)問(wèn)題再來(lái)看一看FSMC手冊(cè)關(guān)于存儲(chǔ)器字寬的描述,我們發(fā)現(xiàn),當(dāng)外部存儲(chǔ)器是16位時(shí),硬件管腳A0-A24表示的是地址線A1-A25的值,所以
我們要位移一下,Bit17的值,實(shí)際會(huì)被反應(yīng)到A16這根IO來(lái)。關(guān)于數(shù)據(jù)寬度及位移的問(wèn)題,初學(xué)的朋友可能會(huì)比較疑惑,當(dāng)你接觸了多NOR/PRAM
這樣的器件后,你會(huì)發(fā)現(xiàn),很多芯片的總線,都是這樣設(shè)計(jì)的,為的是節(jié)省地址線。
第二個(gè)角度理解:
FSMC總線上看,LCD只有2個(gè)地址。
Bank1_LCD_C是寫寄存器,此時(shí)RS=1,告訴LCD我在總線上輸出數(shù)據(jù)的是寄存器的地址
Bank1_LCD_D是寫數(shù)據(jù),此時(shí)RS=0,告訴LCD我在總線上輸出地?cái)?shù)據(jù)是寄存器的數(shù)據(jù)或者GRAM的數(shù)據(jù)。
寫寄存器數(shù)據(jù)按2步來(lái):
第一步先往Bank1_LCD_C (對(duì)應(yīng)RS=1),送寄存器的地址:*(__IO uint16_t *) (Bank1_LCD_C)= index; 接著在Bank1_LCD_D這個(gè)地址(對(duì)應(yīng)RS=0),寫入剛指向的寄存器的數(shù)據(jù): *(__IO uint16_t *) (Bank1_LCD_D)= val;
為什么*(__IO uint16_t *) (Bank1_LCD_C)= index; 就是往 LCD 寫寄存器呢?
這是一個(gè)16位的IO賦值操作,地址是Bank1_LCD_C,這個(gè)地址就是指向FSMC的 Bank1的NE1對(duì)應(yīng)的地址空間。而LCD片選正是連接到NE1,具體地址要看RS接到哪一根地址線上。當(dāng)CPU執(zhí)行到這一條的時(shí)候,就會(huì)通過(guò)FSMC總線控制器在數(shù)據(jù)總線上進(jìn)行一個(gè)地址為 Bank1_LCD_C的數(shù)據(jù)寫操作,此操作自動(dòng)完成CS信號(hào),
RD信號(hào),WR信號(hào),以及地址總線數(shù)據(jù)(RS信號(hào))的輸出以及數(shù)據(jù)總線數(shù)據(jù)的輸出。
其他的操作都是這兩個(gè)操作組合完成。也就是我上面所說(shuō)的,
“所有的寄存器地址和寄存器數(shù)據(jù),以及 GRAM數(shù)據(jù)都是通過(guò) IO0-IO15完成傳輸?shù)模皇荈SMC的地址。這是容易搞混的一個(gè)地方.LCD的FSMC地址只有一根 ,就是RS.”
第三個(gè)角度理解:
把TFT看做類似SRAM的存儲(chǔ)器,只能接在 BANK1上。對(duì)應(yīng)基地址是0x60000000.
而BANK1又有劃分為四個(gè)片選,分別對(duì)應(yīng)基地址:
NE1 0x600000000
NE2 0x640000000
NE3 0x680000000
NE4 0x6C0000000
所以每個(gè)NEx能尋址的空間大小為64M,也就是對(duì)應(yīng)了FSMC的A0到A25 共26根地址線。
假如使用NE4接到為L(zhǎng)CD的片選CS上,那么就對(duì)應(yīng)基地址 0x6C000000,
如果RS接到地址線的 A0上,那么當(dāng) RS為0時(shí)對(duì)應(yīng)的地址就是 LCD_REG = 0x6C000000,(其實(shí)你用0x6CFFFFF0是一樣的,因?yàn)橹挥玫揭桓刂肪€)。
RS為1時(shí)對(duì)應(yīng)的地址就是 LCD_RAM =0x6C000001,(0x6CFFFFF1一樣對(duì)應(yīng) LCD_RAM,因?yàn)樗粯訉?duì)應(yīng) RS=1)。
如果 RS接到 其他地址線上,情況是類似的。
比如接到 An上,那么
LCD_REG= 0x6C000000,
LCD_RAM= 0x6C000000 | (1《《n)
注意這個(gè)地址不是唯一的,只要這個(gè)地址能尋址到 BANK1 的 NE4上而且使 RS=0,那么就是 LCD_REG,使 RS=1,就是LCD_RAM.
對(duì)應(yīng)Bank1_LCD_C 的地址,F(xiàn)SMC總線控制器在RS接的那根地址線輸出的是 1,而對(duì)應(yīng)Bank1_LCD_D,輸出的0.
RS接的可不是GPIO,是FSMC地址總線的一根.FSMC進(jìn)行讀寫操作的時(shí)候會(huì)在地址總線根據(jù)要讀寫的地址輸出電平的。
RS接哪一根地址線雖然沒(méi)有固定要求,但是一旦你確定要接哪一根,那么Bank_LCD_C和Bank_LCD_D也要隨之確定,這可不是“自動(dòng)的“。
雖然沒(méi)有手動(dòng)操作GPIO來(lái)操作RS,但是你敲代碼的時(shí)候可是手動(dòng)指定 Bank1_LCD_C 或者 Bank1_LCD_D ,從而確定 RS的電平。
所謂的“自動(dòng)”是指:不是通過(guò)操作GPIO來(lái)操作RS,而是直接根據(jù)地址總線地址的不同來(lái)完成操作RS,這兩種方法的速度差別是非常大的。
如果是GPIO方式,先要通過(guò)操作GPIO 分別 輸出 RS,CS,等的電平,然后再通過(guò)過(guò)GPIO操作輸出數(shù)據(jù),然后還要通過(guò)GPIO 再操作RD,WR,CS等的電平。
每操作一個(gè)GPIO都要好幾個(gè)周期,加起來(lái)就非常慢了。
而FSMC是在一個(gè)FSMC寫周期內(nèi)就完成了這所有的動(dòng)作。
評(píng)論