STM32外擴SRAM


這兩天調試STM32F103外擴SRAM,將調試過程中遇到的問題記錄下,SRAM的規格是256K*16的異步SRAM,地址總線為18,數據線寬度為16.

在調試過程中遇到一些小問題,希望讀者能少走些彎路。

先看一下FSMC內存映射圖:

由圖可知,stm32的FSMC模塊分為四個bank,每個bank的大小事64M。

 下面這張圖是FSMC各個塊的信號分配圖。

 

由上圖可知,bank1 NOR/PSRAM可以分為4個子塊,由FSMC_NE[4:1]來選擇使能哪個子塊。

例如:每小塊NOR/PSRAM的64M地址范圍如下:

 第一塊:6000 0000h--63ff ffffh

 第二塊:6400 0000h--67ff ffffh

 第二塊:6800 0000h--6bff ffffh

 第三塊:6c00 0000h--6fff ffffh

我們可以通過選擇HADDR[27:26]來確定當前使用的是哪個64M的分地址塊,如下圖所示:

這里我使用的是100腳的stm32,只有NE1引腳可用,也就是說只能用Bank1的存儲塊1,即FSMC_Bank1_NORSRAM1。

我用的STM32是100腳的,地址和數據總線是復用的,那么需要用到鎖存器來區分地址和數據,而鎖存信號是NADV輸出的,注意看圖173和圖174的NADV信號在輸出地址時是低電平,輸出數據時是高電平,所以鎖存器要選擇一個高電平鎖存或者加個反向器。

在配置STM32的FSMC的寄存器時要注意下面兩句話:

//使能復用模式 
FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Enable;
//注意這里不是FSMC_MemoryType_SRAM而是FSMC_MemoryType_NOR,手冊上說要想輸出NADV信號只能設置成FSMC_MemoryType_NOR。
 FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_NOR

SRAM參考原理圖如下圖:

stm32的FSMC功能用到的復用IO口比較多,配置時需要細點心:

/*
 *PD14(DA0) PD15(DA1) PD0(DA2) PD1(DA3) PE7~PE15(DA4~DA12) PD8~PD10(DA13~DA15) PD11(A16) PD12(A17)
 *PD5(WE) PD7(NE1) PD4(OE)
 *PE0(BL0) PE1(BL1) NADV(PB7)
 */
void sram_gpio_configration(void)
{
 GPIO_InitTypeDef GPIO_InitStructure;

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 |
                               GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | 
                               GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_14 | GPIO_Pin_15; 
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
 GPIO_Init(GPIOD, &GPIO_InitStructure);

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_7 | GPIO_Pin_8 |
          GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 |
          GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_Init(GPIOE, &GPIO_InitStructure);

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_Init(GPIOB, &GPIO_InitStructure);
}

下面是具體的FSMC寄存器配置:

void fsmc_for_sram_configration(void)
{
 FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
 FSMC_NORSRAMTimingInitTypeDef  FSMC_NORSRAMTimingInitStructure;
 
 FSMC_NORSRAMTimingInitStructure.FSMC_AddressSetupTime = 15;
 FSMC_NORSRAMTimingInitStructure.FSMC_AddressHoldTime = 15;
 FSMC_NORSRAMTimingInitStructure.FSMC_DataSetupTime = 255
FSMC_NORSRAMTimingInitStructure.FSMC_BusTurnAroundDuration = 15;//以上這四個參數在調試的時候可以先設置為最大值,程序調通后在根據器件手冊和STM32手冊計算出合適的值 FSMC_NORSRAMTimingInitStructure.FSMC_CLKDivision = 0;//synchronize memory下面這兩個參數是為同步器件准備的 FSMC_NORSRAMTimingInitStructure.FSMC_DataLatency = 0; FSMC_NORSRAMTimingInitStructure.FSMC_AccessMode = FSMC_AccessMode_B;//復用總線模式下,訪問模式設置為ModeB FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;
FSMC_NORSRAMInitStructure.FSMC_DataAddressMux
= FSMC_DataAddressMux_Enable; FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_NOR;//注意這里要設置成NOR,因為只有設置為NOR,才能輸出NADV信號
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 = &FSMC_NORSRAMTimingInitStructure; FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &FSMC_NORSRAMTimingInitStructure; FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); /* - BANK 1 (of NOR/SRAM Bank 0~3) is enabled */ FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE); }

 

 外部SRAM的訪問: 

在訪問SRAM時糾結了許久,最后終於弄明白了。網上看了很多資料,有說在訪問時要先將地址偏移,有說直接訪問就行。最后經過測試發現訪問片外SRAM時跟訪問內部RAM一樣,直接訪問就可以了,FSMC都幫我們做好了。

當訪問字節數據時:*((u8*)(BANK1_SRAM_BASE+offset))。1.讀取SRAM數據時,將offset設為0x00,用示波器測試SRAM的A0地址信號是低,當offset為0x01時,用示波器測試SRAM的A0地址信號也是低,當offset為0x02和0x03時SRAM的A0地址信號是高,這說明當字節訪問時地址確實是偏移了1位,原因是SRAM是16位器件(SRAM的1個地址存儲16位數據),一次可以訪問2個字節的數據,這個時候FSMC將根據offset值判斷,訪問的是高8位還是低8位,即如果offset的最低位是0則訪問的是16位數據的低8位,如果offset的最低位是1則訪問的是16位數據的高8位。2. 向SRAM寫數據時,道理也是一樣的,只是寫的時候通過BL[1:0]兩個管腳控制寫高字節還是低字節。

當訪問半字數據時:*((u16*)(BANK1_SRAM_BASE+offset))。1.讀取SRAM數據時,這個時候要注意了,FSMC在訪問的時候要看offset的值是不是半字對齊的。如果offset是0x00,則直接訪問的是SRAM的0x00地址處的16位數據,當offset是0x01時,FSMC是分兩次訪問的,第一次是訪問SRAM的0x00地址的高字節,第二次是訪問SRAM的0x01地址處的低字節(SRAM的1個地址存儲16位數據),通過用示波器測量SRAM的A0地址信號得到,信號是先低在高的一個脈沖,驗證了前面的說法。2. 向SRAM寫數據時,道理也是一樣的,只是寫的時候通過BL[1:0]兩個管腳控制寫高字節還是低字節。

 當訪問字數據時:訪問字時,FSMC分為2個半字訪問。

總結:外部SRAM就跟片內SRAM一樣用就行了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM