扩展外部SRAM
擴展外部SRAM
一、SRAM控制原理
STM32控制器芯片內部有一定大小的SRAM及FLASH作為內存和程序存儲空間,但當程序較大,內存和程序空間不足時,就需要在STM32芯片的外部擴展存儲器了。SRAM中的數據斷電即失(屬于易失性存儲器),因此只適用于存儲經常改變的變量。擴展內存時一般使用SRAM和SDRAM存儲器,但STM32F407系列的芯片不支持擴展SDRAM(STM32F429系列支持),它僅支持使用FSMC外設擴展SRAM。給STM32芯片擴展內存與給PC擴展內存的原理是一樣的,只是PC上一般以內存條的形式擴展, 內存條實質是由多個內存顆粒(即SRAM芯片)組成的通用標準模塊,而STM32直接與SRAM芯片連接。
在STM32中,數組等變量的使用會在SRAM中進行,而程序編譯后,整個程序中的代碼、指令不會再進行修改了,存儲再FLASH中。如果使用的變量較多時,就需要使用擴展外部SRAM(相當于電腦加擴展內存條)。
STM32擴展外部SRAM管腳
SRAM芯片內部功能框架,其中A0-A18即指上圖中的A0-A18引腳
UB、LB兩根線代表的是讀取數據的高八位/低八位
CS線是片選信號線
WE/OE是讀使能/寫使能信號線
信號A0-A18信號線到地址譯碼器,得到應該訪問哪個相應的單元格(讀或寫都可)
都與上圖引腳對應
下圖為SRAM信號線控制的引腳說明
儲存矩陣
SRAM內部包含的存儲陣列,按行地址與列地址儲存,可以把它理解成一張表格,數據就填在這張表格上。和表格查找一樣,指定一個行地址和列地址,就可以精確地找到目標單元格, 這是SRAM芯片尋址的基本原理。這樣的每個單元格被稱為存儲單元,而這樣的表則被稱為存儲矩陣。
地址譯碼器把N根地址線轉換為2的N次方根信號線,每根信號線對應一行或一列存儲單元,每個存儲單元都有其獨立行列地址,通過此來尋址。
訪問時, 使用UB或LB線控制數據寬度,例如,當要訪問寬度為16位的數據時,使用行地址線指出地址,然后把UB和LB線都設置為低電平(使能), 那么I/O0-I/O15線都有效,它們一起輸出該地址的16位數據(或者接收16位數據到該地址);當要訪問寬度為8位的數據時,使用行地址線指出地址, 然后把UB或LB其中一個設置為低電平,I/O會對應輸出該地址的高8位和低8位數據,因此它們被稱為數據掩碼信號。(推測)
二、SRAM的讀寫流程
(1) 主機使用地址信號線發出要訪問的存儲器目標地址;
(2) 控制片選信號CS1#及CS2#使能存儲器芯片;
(3) 若是要進行讀操作,則控制讀使能信號OE#表示要讀數據,若進行寫操作則控制寫使能信號WE#表示要寫數據;
(4) 使用掩碼信號LB#與UB#指示要訪問目標地址的高、低字節部分;
(5) 若是讀取過程,存儲器會通過數據線向主機輸出目標數據,若是寫入過程,主要使用數據線向存儲器傳輸目標數據。
在讀寫時序中,有幾個比較重要的時間參數,在使用STM32 控制的時候需要參考。
tRC:讀操作周期 最短時間:55ns
tAA:地址訪問時間 最短時間:0ns
tWC:寫操作周期 最短時間:55ns
rSA:地址建立時間 最短時間:0ns
tSD:數據建立至寫結束的時間 最短時間:25ns
tHD:數據寫結束后的保持時間 最短時間:0ns
三、FSMC簡介
STM32F407系列芯片使用FSMC外設來管理擴展的存儲器, FSMC即Flexible Static Memory Controlle。 它可以用于驅動包括SRAM、NOR FLASH以及NAND FLSAH類型的存儲器,(FSMC是靜態的)不能驅動如SDRAM這種動態的存儲器。而在STM32F429系列的控制器中, 它具有FMC(Flexible Memory Controlle)外設,支持控制SDRAM存儲器。
1.FSMC框圖
FSCM不是掛載在APBx總線上,而是掛載在AHB高速總線上(具體為AHB3),原因是FSMC要求較快的驅動速度,直接當內存訪問,相應應該使用AHB時鐘。地址線FSMC_A和數據線FSMC_D是所有控制器都共用的。
通訊引腳:
其中比較特殊的FSMC_NE是用于控制SRAM芯片的片選控制信號線,STM32具有FSMC_NE1/2/3/4號引腳,不同的引腳對應STM32內部不同的地址區域。 例如,當STM32訪問0x6C000000-0x6FFFFFFF地址空間時,FSMC_NE3引腳會自動設置為低電平,由于它連接到SRAM的CE#引腳, 所以SRAM的片選被使能,而訪問0x60000000-0x63FFFFFF地址時,FSMC_NE1會輸出低電平。當使用不同的FSMC_NE引腳連接外部存儲器時, STM32訪問SRAM的地址不一樣,從而達到控制多塊SRAM芯片的目的。也就是說,連接到哪個相應的地址與之相對的引腳就會被設置為低電平。
存儲器控制器
上面不同類型的引腳是連接到FSMC內部對應的存儲控制器中的。NOR/PSRAM/SRAM設備使用相同的控制器,NAND/PC卡設備使用相同的控制器,不同的控制器有專用的寄存器用于配置其工作模式。
控制SRAM的有FSMC_BCR1/2/3/4控制寄存器、FSMC_BTR1/2/3/4片選時序寄存器以及FSMC_BWTR1/2/3/4寫時序寄存器。每種寄存器都有4個,分別對應于4個不同的存儲區域,各種寄存器介紹如下:
FSMC_BCR控制寄存器可配置要控制的存儲器類型、數據線寬度以及信號有效極性能參數。
模式A-SRAM的FSMC_BCR
模式B-NOR FLASH的FSMC_BCR
FMC_BTR時序寄存器用于配置SRAM訪問時的各種時間延遲,如數據保持時間、地址保持時間等。
模式A-SRAM的FSMC_BTR
模式B-NOR FLASH的FSMC_BTR
FSMC_BWTR寫時序寄存器與FMC_BTR寄存器控制的參數類似,它專門用于控制寫時序的時間參數。
時鐘控制邏輯
FSMC外設掛載在AHB總線上,時鐘信號來自于HCLK(默認168MHz),控制器的同步時鐘輸出就是由它分頻得到。例如,NOR控制器的FSMC_CLK引腳輸出的時鐘,它可用于與同步類型的SRAM芯片進行同步通訊,它的時鐘頻率可通過FSMC_BTR寄存器的CLKDIV位配置,可以配置為HCLK的1/2或 1/3,也就是說,若它與同步類型的SRAM通訊時,同步時鐘最高頻率為84MHz。本示例中的SRAM為異步類型的存儲器,不使用同步時鐘信號,所以時鐘分頻配置不起作用。SRAM是異步的,NOR FLASH有些是同步的需要用到時鐘同步邏輯。
地址映射
FSMC連接好外部的存儲器并初始化后,就可以直接通過訪問地址來讀寫數據,這種地址訪問與I2C EEPROM、SPI FLASH的不一樣, 后兩種方式都需要控制I2C或SPI總線給存儲器發送地址,然后獲取數據;在程序里,這個地址和數據都需要分開使用不同的變量存儲, 并且訪問時還需要使用代碼控制發送讀寫命令。而使用FSMC外接存儲器時,其存儲單元是映射到STM32的內部尋址空間的;在程序里, 定義一個指向這些地址的指針,然后就可以通過指針直接修改該存儲單元的內容,FSMC外設會自動完成數據訪問過程, 讀寫命令之類的操作不需要程序控制。(代碼段自動儲存)
通過指針直接訪問后面的地址
注:SRAM和NOR FLASH只能用Bank1就算STM32擴展到最大1G,也只能訪問Bank1.Bank區域自動分配過。
SRAM時序結構體
控制FSMC使用SRAM存儲器時主要是配置時序寄存器以及控制寄存器,利用ST標準庫的SRAM時序結構體以及初始化結構體可以很方便地寫入參數。
FSMC的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;舉例定義宏
#define FSMC_GPIO_AF GPIO_AF_FSMC/*A地址信號線*/ #define FSMC_A0_GPIO_PORT GPIOF #define FSMC_A0_GPIO_CLK RCC_AHB1Periph_GPIOF #define FSMC_A0_GPIO_PIN GPIO_Pin_0 #define FSMC_A0_GPIO_PinSource GPIO_PinSource0 /*……省略A1-A18地址線*//*D 數據信號線*/ #define FSMC_D0_GPIO_PORT GPIOD #define FSMC_D0_GPIO_CLK RCC_AHB1Periph_GPIOD #define FSMC_D0_GPIO_PIN GPIO_Pin_14 #define FSMC_D0_GPIO_PinSource GPIO_PinSource14 /*……省略D1-D15地址線*//*控制信號線*/ /*CS片選*/ /*NE4 ,對應的基地址0x6C000000*/ #define FSMC_CS_GPIO_PORT GPIOG #define FSMC_CS_GPIO_CLK RCC_AHB1Periph_GPIOG #define FSMC_CS_GPIO_PIN GPIO_Pin_12 #define FSMC_CS_GPIO_PinSource GPIO_PinSource12/*WE寫使能*/ #define FSMC_WE_GPIO_PORT GPIOD #define FSMC_WE_GPIO_CLK RCC_AHB1Periph_GPIOD #define FSMC_WE_GPIO_PIN GPIO_Pin_5 #define FSMC_WE_GPIO_PinSource GPIO_PinSource5/*OE讀使能*/ #define FSMC_OE_GPIO_PORT GPIOD #define FSMC_OE_GPIO_CLK RCC_AHB1Periph_GPIOD #define FSMC_OE_GPIO_PIN GPIO_Pin_4 #define FSMC_OE_GPIO_PinSource GPIO_PinSource4/*UB數據掩碼*/ #define FSMC_UDQM_GPIO_PORT GPIOE #define FSMC_UDQM_GPIO_CLK RCC_AHB1Periph_GPIOE #define FSMC_UDQM_GPIO_PIN GPIO_Pin_1 #define FSMC_UDQM_GPIO_PinSource GPIO_PinSource1/*LB數據掩碼*/ #define FSMC_LDQM_GPIO_PORT GPIOE #define FSMC_LDQM_GPIO_CLK RCC_AHB1Periph_GPIOE #define FSMC_LDQM_GPIO_PIN GPIO_Pin_0 #define FSMC_LDQM_GPIO_PinSource GPIO_PinSource0初始化FSMC的 GPIO
利用上面的宏,編寫FSMC的GPIO引腳初始化函數
使用指針的方式訪問SRAM
/*SRAM起始地址 存儲空間4的起始地址*/ #define Bank1_SRAM4_ADDR ((uint32_t)0x6C000000) /*SRAM大小,1M字節*/ #define IS62WV51216_SIZE 0x100000uint32_t temp;/*向SRAM寫入8位數據*/ *( uint8_t*) (Bank1_SRAM4_ADDR ) = (uint8_t)0xAA; /*從SRAM讀取數據*/ temp = *( uint8_t*) (Bank1_SRAM4_ADDR );/*寫/讀 16位數據*/ *( uint16_t*) (Bank1_ SRAM4_ADDR +10 ) = (uint16_t)0xBBBB; temp = *( uint16_t*) (Bank1_SRAM4_ADDR+10 );/*寫/讀 32位數據*/ *( uint32_t*) (Bank1_SRAM4_ADDR +20 ) = (uint32_t)0xCCCCCCCC; temp = *( uint32_t*) (Bank1_SRAM4_ADDR+20 );配置FSMC的模式
void FSMC_SRAM_Init(void) {FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;FSMC_NORSRAMTimingInitTypeDef readWriteTiming;/*初始化SRAM相關的GPIO*/SRAM_GPIO_Config();/*使能FSMC外設時鐘*/RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC,ENABLE);/*********************時序**************************///地址建立時間(ADDSET)為1個HCLKreadWriteTiming.FSMC_AddressSetupTime = 0x00;//地址保持時間(ADDHLD)模式A未用到readWriteTiming.FSMC_AddressHoldTime = 0x00;//數據保持時間(DATAST)+ 1個HCLK = 9/168M=54ns(對EM的SRAM芯片)readWriteTiming.FSMC_DataSetupTime = 0x08;//設置總線轉換周期,僅用于復用模式的NOR操作readWriteTiming.FSMC_BusTurnAroundDuration = 0x00;//設置時鐘分頻,僅用于同步類型的存儲器readWriteTiming.FSMC_CLKDivision = 0x00;//數據保持時間,僅用于同步型的NORreadWriteTiming.FSMC_DataLatency = 0x00;//選擇匹配SRAM的模式readWriteTiming.FSMC_AccessMode = FSMC_AccessMode_A;/**************************控制************************************/// 選擇FSMC映射的存儲區域: Bank1 sram4FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;//設置地址總線與數據總線是否復用,僅用于NORFSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;//設置要控制的存儲器類型:SRAM類型FSMC_NORSRAMInitStructure.FSMC_MemoryType =FSMC_MemoryType_SRAM;//存儲器數據寬度:16位FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;//設置是否使用突發訪問模式,僅用于同步類型的存儲器FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode =FSMC_BurstAccessMode_Disable;//設置是否使能等待信號,僅用于同步類型的存儲器FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait=FSMC_AsynchronousWait_Disable;//設置等待信號的有效極性,僅用于同步類型的存儲器FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;//設置是否支持把非對齊的突發操作,僅用于同步類型的存儲器FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;//設置等待信號插入的時間,僅用于同步類型的存儲器FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;//存儲器寫使能FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;//不使用等待信號FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;// 不使用擴展模式,讀寫使用相同的時序FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;//突發寫操作FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;//讀寫時序配置FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &readWriteTiming;//讀寫同樣時序,使用擴展模式時這個配置才有效FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &readWriteTiming;FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); //初始化FSMC配置FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE); // 使能BANK}總結
- 上一篇: arduino控制声音传感器
- 下一篇: 电池上的PHP是什么,一次电池与二次电池