你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32心得:外部SRAM原理及实验代码解读

[复制链接]
STMCU小助手 发布时间:2022-11-22 14:06
主要内容:
1) IS62WV51216简介;
2) FSMC简介及相关寄存器介绍;
3) 相关实验代码解读。
硬件连接:
IS62WV51216原理图如下所示,具体连接关系为:
A[0:18]接FMSC_A[0:18];D[0:15]接FSMC_D[0:15];UB接FSMC_NBL1;LB接FSMC_NBL0;OE接FSMC_OE;WE接FSMC_WE;CS接FSMC_NE3。

20201008125059590.png

实验功能:程序开启后,按下KEY0键,测试外部SRAM容量大小并发送至串口端;按下KEY1键,显示预存在外部SRAM的数据。DS0指示程序运行状态。

1. IS62WV51216简介
1.1 IS62WV51216是ISSI(Integrated Silicon Solution, Inc)公司生产的一颗16位宽512K(512*16,即1M字节)容量的CMOS静态内存(SRAM)芯片。

1.2 特点
1) 高速。具有45ns/55ns访问速度(开发版采用55ns型号);
2) 低功耗。操作时:36mW;待机时:12uW;
3) 兼容TTL电平,兼容5V电压;
4) 全静态操作,不需要刷新和时钟电路;
5) 三态输出;
6) 字节控制功能。支持高/低字节控制。

1.3 框图
图中A0~18为地址线,总共19根地址线(即2^19=512K,1K=1024);
I/O0~15为数据线,总共16根数据线;
CS2和CS1都是片选信号,CS2是高电平有效,CS1是低电平有效(开发板采用CS1);
OE是输出使能信号(读信号);
WE为写使能信号;
UB和LB分别是高字节控制和低字节控制信号(设0有效,设1无效)。

202010081255406.png

1.4 IS62WV51216读时序
IS62WV51216芯片的8080并口读时序如下图所示:
重点时序:读周期时间(tRC);地址建立时间(tAA);OE建立时间(tDOE)。
开发板使用55ns的IS62WV51216,tRC=55ns,tAA=55ns(Max),tDOE=25ns(Max)。

20201008125617523.png

1.5 IS62WV51216写时序
IS62WV51216芯片的8080并口写时序如下图所示:
重点时序:写周期时间(tWC),地址建立时间(tSA),WE脉宽(tPWE)。
开发板使用55ns的IS62WV51216,tWC=55ns,tSA=0ns,tPWE=45ns(min)。

2020100813350694.png

2. FSMC简介
FSMC,即灵活的静态存储控制器,能够与同步或异步存储器和16位PC存储器卡连接,STM32的FSMC接口支持包括SRAM、NAND FLASH、NOR FLASH和PSRAM等存储器(不支持SDRAM)。FSMC的框图如下图所示:

20201008133556352.png

2.1 FSMC驱动IS62WV51216原理
FSMC驱动外部SRAM时,外部SRAM的控制一般有:
1) 地址线(如A0~A25);
2) 数据线(如D0~D15);
3) 写信号(WE,即WR);
4) 读信号(OE,即RD);
5) 片选信号(CS);
6) 如果SRAM支持字节控制,还有UB/LB信号。
IS62WV51216的信号包括:
1) 地址线A0~A18;
2) 数据线I/O0~I/O15;
3) 写信号WE;
4) 读信号OE;
5) 片选信号CS;
6) 字节控制UB、LB等。
将这些信号依次连接STM32 FSMC接口的A0-A18、D0-D15、WE、OE、CS、UB、LB等信号即可。

2.2 NOR / PSRAM外设接口
STM32的FSMC支持8/16位数据宽度,我们这里用到的SRAM是16位宽度的,所以在设置的时候,选择16位宽就OK了。FSMC的外部设备地址映像,STM32的FSMC将外部存储器划分为固定大小为256M字节的四个存储块(注意每个块的起始地址!)。

20201008133847927.png

2.3 NOR / PSRAM存储块1 操作简介
STM32的FSMC存储块1(Bank1)用于驱动NOR FLASH/SRAM/PSRAM,被分为4个区,每个区管理64M字节空间,每个区都有独立的寄存器对所连接的存储器进行配置。Bank1的256M字节空间由28根地址线(HADDR[27:0])寻址。
这里HADDR,是内部AHB地址总线,其中,HADDR[25:0]来自外部存储器地址FSMC_A[25:0],而HADDR[26:27]对4个区进行寻址(不能直接设置,只能选择片选间接设置)。如下表所示:

20201008133950591.png

注意!
当Bank1接的是16位宽度存储器的时候:HADDR[25:1]——FSMC_A[24:0](右移一位对齐),
当Bank1接的是8位宽度存储器的时候:HADDR[25:0]——FSMC_A[25:0],
不论外部接8位/16位宽设备,FSMC_A[0]永远接在外部设备地址A[0]。

2.4 NOR PSRAM存储块1 访问模式
STM32的FSMC存储块1 支持的异步突发访问模式包括:模式1、模式A~D等多种时序模型,驱动SRAM时一般使用模式1或者模式 A,这里使用模式A来驱动SRAM,其他模式说明详见:STM32中文参考手册-FSMC章节。

20201008134139391.jpg

模式A支持读写时序分开设置!(可针对一些读写时序不一样的设备分开设置),
对STM32F4仅写时序DATAST需要+1(F1按上图要求即可)。

2.5 FSMC寄存器介绍
对于NOR FLASH/PSRAM控制器(存储块1),通过FSMC_BCRx、FSMC_BTRx和FSMC_BWTRx(仅读写时序不一致时才设置)寄存器设置(其中x=1~4,对应4个区)。通过这3个寄存器,可以设置FSMC访问外部存储器的时序参数,拓宽了可选用的外部存储器的速度范围。
2.5.1 SRAM/NOR闪存片选控制寄存器(FSMC_BCRx)

2020100813433667.png

EXTMOD:扩展模式使能位,控制是否允许读写不同的时序,设置为0(读写相同时序);
WREN:写使能位。我们需要向SRAM写数据,故该位必须设置为1;
MWID[1:0]:存储器数据总线宽度。00,表示8位数据模式,01表示16位数据模式,10和11保留。我们的SRAM是16位数据线,所以设置WMID[1:0]=01;
MTYP[1:0]:存储器类型。00表示SRAM、ROM,01表示PSRAM,10表示NOR FLASH,11保留。我们驱动的芯片为SRAM,所以需要设置MTYP[1:0]=00;
MBKEN:存储块使能位。需设置为1,使能相应的存储块。

2.5.2 SRAM/NOR闪存片选时序寄存器(FSMC_BTRx)

20201008134437936.png

ACCMOD[1:0]:访问模式。00:模式A,01:模式B,10:模式C,11:模式D。
DATAST[7:0]:数据保持时间,等于: DATAST(+1)个HCLK时钟周期(F4只有写的时候要+1),DATAST最大为255。对IS62WV51216来说,其实就是OE/WE低电平持续时间,最大为55ns。对STM32F1,一个HCLK=13.8ns (1/72M),设置为3(13.8×(3+1)≈55.2ns)。对STM32F4,一个HCLK=6ns(1/168M),设置为8(有点超频)。
ADDSET[3:0]:地址建立时间。表示:ADDSET (+1)个HCLK周期(F1不需要+1),ADDSET最大为15。对IS62WV51216来说,访问周期最快为55ns,之前的设置,已经可以保证访问周期不小于55ns,因此这个地址建立时间,直接设置为0即可。
本实验因为EXTMOD位设置为0,所以读写时序共用这个时序寄存器!

2.5.3 SRAM/NOR闪存写时序寄存器(FSMC_BWTRx)
若EXTMOD位设置为1,读写时序分开,则用该寄存器设置写时序。

2020100813455846.png

ACCMOD[1:0]:访问模式。00:模式A;01:模式B;10:模式C;11:模式D。
DATAST[7:0]:数据保持时间,等于:
DATAST(+1)个HCLK时钟周期,DATAST最大为255。
ADDSET[3:0]:地址建立时间。表示:ADDSET+1个HCLK周期,ADDSET最大为15。
本实验因为EXTMOD位设置为0,所以用不到该寄存器!

2.5.4 SRAM/NOR闪存片选寄存器组合说明
在ST官方库提供的的寄存器定义里面,并没有定义FSMC_BCRx、FSMC_BTRx、FSMC_BWTRx等这些单独的寄存器,而是将他们进行了一些组合。规律如下:
1)FSMC_BCRx和FSMC_BTRx,组合成BTCR[8]寄存器组,对应关系如下:
BTCR[0]对应FSMC_BCR1,BTCR[1]对应FSMC_BTR1;
BTCR[2]对应FSMC_BCR2,BTCR[3]对应FSMC_BTR2;
BTCR[4]对应FSMC_BCR3,BTCR[5]对应FSMC_BTR3;
BTCR[6]对应FSMC_BCR4,BTCR[7]对应FSMC_BTR4。
2)FSMC_BWTRx则组合成BWTR[7],对应关系如下:
BWTR[0]对应FSMC_BWTR1,BWTR[2]对应FSMC_BWTR2,
BWTR[4]对应FSMC_BWTR3,BWTR[6]对应FSMC_BWTR4,
BWTR[1]、BWTR[3]和BWTR[5]保留,没有用到。

3. 相关代码解读
3.1 sram.h头文件代码解读

  1. /**
  2. ********************************  STM32F10x  *********************************
  3. * @文件名称: sram.h
  4. * @作者名称: Aaron
  5. * @库版本号: V3.5.0
  6. * @工程版本: V1.0.0
  7. * @开发日期: 2020年10月7日
  8. * @摘要简述: SRAM头文件
  9. ******************************************************************************/
  10. /*----------------------------------------------------------------------------
  11. * @更新日志:
  12. * @无
  13. * ---------------------------------------------------------------------------*/
  14. #ifndef __SRAM_H
  15. #define __SRAM_H
  16. /* 包含的头文件 ---------------------------------------------------------------*/
  17. #include "sys.h"
  18. /* 函数申明 -------------------------------------------------------------------*/            
  19. void FSMC_SRAM_Init(void);
  20. void FSMC_SRAM_WriteBuffer(u8* pBuffer,u32 WriteAddr,u32 NumHalfwordToWrite);
  21. void FSMC_SRAM_ReadBuffer(u8* pBuffer,u32 ReadAddr,u32 NumHalfwordToRead);
  22. #endif /* __SRAM_H */
  23. /****** Copyright (C)2020 Aaron. All Rights Reserved ****** END OF FILE *******/
复制代码

3.2 sram.c文件代码解读

  1. /**
  2. ********************************  STM32F10x  *********************************
  3. * @文件名称: sram.c
  4. * @作者名称: Aaron
  5. * @库版本号: V3.5.0
  6. * @工程版本: V1.0.0
  7. * @开发日期: 2020年10月7日
  8. * @摘要简述: SRAM源文件,使用NOR/SRAM的 Bank1.sector3,地址位HADDR[27,26]=10,
  9. *            对IS62WV51216,地址线范围为A0~A18
  10. ******************************************************************************/
  11. /*----------------------------------------------------------------------------
  12. * @更新日志:
  13. * @无
  14. * ---------------------------------------------------------------------------*/
  15.   /* 包含的头文件 --------------------------------------------------------------*/
  16. #include "sram.h"   
  17. #include "usart.h"
  18. /* 定义常量 ------------------------------------------------------------------*/     
  19. #define Bank1_SRAM3_ADDR    ((u32)(0x68000000))  
  20. /************************************************
  21. 函数名称:FSMC_SRAM_Init()
  22. 函数功能:初始化外部SRAM
  23. 入口参数:无
  24. 返回参数:无
  25. 开发作者:Aaron
  26. *************************************************/
  27. void FSMC_SRAM_Init(void)
  28. {
  29. /* 定义结构体 */
  30. FSMC_NORSRAMInitTypeDef        FSMC_NORSRAMInitStructure;
  31. FSMC_NORSRAMTimingInitTypeDef  readWriteTiming;
  32. GPIO_InitTypeDef               GPIO_InitStructure;
  33. /* 使能相关IO口 */
  34. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOF|RCC_APB2Periph_GPIOG,ENABLE);
  35. RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC,ENABLE);
  36. GPIO_InitStructure.GPIO_Pin = 0xFF33;              /* PD0-1,PD4-5,PD8-15 */
  37. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    /* 复用推挽输出 */
  38. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  39. GPIO_Init(GPIOD, &GPIO_InitStructure);
  40. GPIO_InitStructure.GPIO_Pin = 0xFF83;              /* PE0-1,PE7-15 */
  41. GPIO_Init(GPIOE, &GPIO_InitStructure);
  42. GPIO_InitStructure.GPIO_Pin = 0xF03F;              /* PF0-5,PF12-15 */
  43. GPIO_Init(GPIOF, &GPIO_InitStructure);
  44. GPIO_InitStructure.GPIO_Pin = 0x043F;              /* PG0-5,PG10 */
  45. GPIO_Init(GPIOG, &GPIO_InitStructure);
  46. /* 读写时序结构体初始化 */        
  47. readWriteTiming.FSMC_AddressSetupTime = 0x00;        /* 地址建立时间(ADDSET)为1个HCLK 1/36M=27ns */
  48. readWriteTiming.FSMC_AddressHoldTime = 0x00;         /* 地址保持时间(ADDHLD)模式A未用到 */
  49. readWriteTiming.FSMC_DataSetupTime = 0x03;           /* 数据保持时间(DATAST)为3个HCLK 4/72M≈55ns(对EM的SRAM芯片) */  
  50. readWriteTiming.FSMC_BusTurnAroundDuration = 0x00;
  51. readWriteTiming.FSMC_CLKDivision = 0x00;
  52. readWriteTiming.FSMC_DataLatency = 0x00;
  53. readWriteTiming.FSMC_AccessMode = FSMC_AccessMode_A; /* 模式A */  
  54. FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM3;                                /* 使用NE3,对应BTCR[4],[5] */
  55. FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;              /* 地址复用未用 */
  56. FSMC_NORSRAMInitStructure.FSMC_MemoryType =FSMC_MemoryType_SRAM;                          /* 存储器类型SRAM */   
  57. FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;                /* 存储器数据宽度为16bit */  
  58. FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode =FSMC_BurstAccessMode_Disable;             /* 禁止突发访问模式 */
  59. FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
  60. FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait=FSMC_AsynchronousWait_Disable;
  61. FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;   
  62. FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;  
  63. FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;               /* 存储器写使能 */
  64. FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;  
  65. FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;                  /* 不使用扩展模式,读写使用相同的时序 */
  66. FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;  
  67. FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &readWriteTiming;                  /* 读写同样时序 */
  68. FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &readWriteTiming;                      /* 读写同样时序 */
  69. FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);                                             /* 初始化FSMC配置 */
  70. FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM3, ENABLE);                                             /* 使能BANK3 */            
  71. }
  72. /**********************************************************************
  73. 函数名称:FSMC_SRAM_WriteBuffer(u8* pBuffer,u32 WriteAddr,u32 n)
  74. 函数功能:在指定地址开始,连续写入n个字节
  75. 入口参数:pBuffer:字节指针,首地址;WriteAddr:要写入的地址;n:要写入的字节数
  76. 返回参数:无
  77. 开发作者:Aaron
  78. ***********************************************************************/
  79. void FSMC_SRAM_WriteBuffer(u8* pBuffer,u32 WriteAddr,u32 n)
  80. {
  81. for(;n!=0;n--)  
  82. {              
  83.   *(vu8*)(Bank1_SRAM3_ADDR+WriteAddr)=*pBuffer;   /* Bank1_SRAM3_ADDR ((u32)(0x68000000)) */
  84.   WriteAddr++;
  85.   pBuffer++;
  86. }   
  87. }
  88. /**********************************************************************
  89. 函数名称:FSMC_SRAM_ReadBuffer(u8* pBuffer,u32 ReadAddr,u32 n)
  90. 函数功能:在指定地址开始,连续读出n个字节
  91. 入口参数:pBuffer:字节指针,首地址;ReadAddr:要写入的地址;n:要读出的字节数
  92. 返回参数:无
  93. 开发作者:Aaron
  94. ***********************************************************************/
  95. void FSMC_SRAM_ReadBuffer(u8* pBuffer,u32 ReadAddr,u32 n)
  96. {
  97. for(;n!=0;n--)  
  98. {               
  99.   *pBuffer++=*(vu8*)(Bank1_SRAM3_ADDR+ReadAddr);   
  100.   ReadAddr++;
  101. }  
  102. }
  103. /****** Copyright (C)2020 Aaron. All Rights Reserved ****** END OF FILE *******/
复制代码

3.3 main.c文件代码解读

  1. /**
  2. ********************************  STM32F10x  *********************************
  3. * @文件名称: main.c
  4. * @作者名称: Aaron
  5. * @库版本号: V3.5.0
  6. * @工程版本: V1.0.0
  7. * @开发日期: 2020年10月7日
  8. * @摘要简述: 主函数
  9. ******************************************************************************/
  10. /*----------------------------------------------------------------------------
  11. * @更新日志:
  12. * @无
  13. * ---------------------------------------------------------------------------*/
  14. /* 包含的头文件 --------------------------------------------------------------*/
  15. #include "sram.h"
  16. #include "led.h"
  17. #include "key.h"
  18. #include "sys.h"
  19. #include "delay.h"
  20. #include "usart.h"
  21. /* 定义一个数组testsram[],u32表示每个数占4个字节,数组包含250000个值,*/
  22. /* 采用绝对地址定义,数组的起始地址在0x68000000 */
  23. u32 testsram[250000] __attribute__((at(0X68000000)));
  24. /**********************************************************************
  25. 函数名称:fsmc_sram_test()
  26. 函数功能:外部内存测试(最大支持1M字节内存测试)
  27. 入口参数:无
  28. 返回参数:无
  29. 开发作者:Aaron
  30. ***********************************************************************/
  31. void fsmc_sram_test(void)
  32. {  
  33. u32 i=0;     
  34. u8 temp=0;                        /* 0≤temp≤255 */
  35. u8 sval=0;                        /* 在地址0读到的数据 */
  36. printf("外部内存测试:0KB\r\n");
  37. /* 每隔4K个字节,写入一个数据,总共写入256个数据,刚好是1M字节 */
  38. for(i=0;i<1024*1024;i+=4096)
  39. {
  40.   FSMC_SRAM_WriteBuffer(&temp,i,1);
  41.   temp++;                          /* for循环运行完后,temp值为0 */
  42. }
  43. /* 依次读出之前写入的数据,进行校验 */   
  44. for(i=0;i<1024*1024;i+=4096)
  45. {
  46.   FSMC_SRAM_ReadBuffer(&temp,i,1);
  47.   if(i==0)                         /* 将第一次的temp值赋给sval,即sval=temp=0 */
  48.   sval=temp;
  49.   else if(temp<=sval)
  50.   break;                         /* 本程序设计思路,后面读出的数据一定比第一次读到的数据大 */  
  51.   printf("内存容量为:%dKB\r\n",(temp-sval+1)*4);  
  52. }      
  53. }
  54. /**********************************************************************
  55. 函数名称:main()
  56. 函数功能:主函数
  57. 入口参数:无
  58. 返回参数:无
  59. 开发作者:Aaron
  60. ***********************************************************************/
  61. int main(void)
  62. {  
  63. u8 key;   
  64. u8 i=0;      
  65. u32 ts=0;
  66. delay_init();        
  67. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  68. uart_init(115200);   
  69. LED_Init();      
  70. KEY_Init();     
  71. FSMC_SRAM_Init();
  72. for(ts=0;ts<250000;ts++)testsram[ts]=ts;       /* 预存测试数据 */
  73. while(1)
  74. {
  75.   key=KEY_Scan(0);                              /* 不支持连按 */
  76.   if(key==KEY0_PRES)
  77.    fsmc_sram_test();                           /* 测试SRAM容量 */
  78.   else if(key==KEY1_PRES)                       /* 打印预存测试数据 */
  79.   {
  80.    for(ts=0;ts<250000;ts++)
  81.     printf("显示测试数据testsram[%d]=%d\r\n",ts,testsram[ts]);
  82.   }
  83.   else
  84.    delay_ms(10);   
  85.   i++;
  86.   if(i==20)
  87.   {
  88.    i=0;
  89.    LED0=!LED0;
  90.    }
  91. }      
  92. }
  93. /****** Copyright (C)2020 Aaron. All Rights Reserved ****** END OF FILE *******/

复制代码

4. 实验结果
按KEY0键:

20201008140144330.jpg

20201008140221491.jpg

按KEY1键:

20201008140243147.jpg

————————————————
版权声明:天亮继续睡


收藏 评论0 发布时间:2022-11-22 14:06

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版