STM32 FSMC操作SRAM的步骤简析

发布时间:2024-03-05  

本次操作的SRAM的型号是IS62WV51216,是高速,8M位静态SRAM。它采用ISSI(Intergrated Silicon Solution, Inc)公司的高性能CMOS技术,按照512K个字(16)位进行组织存储单元。其具有高性能、低功耗特点。为方便用户扩展SRAM的存储空间,为用户有提供了两个片选引脚;此外,含有两个字节控制信号UB和LB,可方便用户按字节访问SRAM或按字访问SRAM。IS62WV51216具有45ns/55ns访问速度,因为是全静态操作,因此无需外部时钟和刷新要求。


IS62WV51216功能框图

图片

IS62WV51216有地址译码器、数据IO、控制逻辑和存储阵列四部分构成。地址译码器将19根地址线上的输入进行译码,将译码值与内部存储阵列的单元地址进行建立映射。数据IO是SRAM是主控制器数据交互的通道,访问数据时,即可字节进行访问也可按字访问,按字节访问功能增强了其与8位机的兼容性。控制逻辑部分包括读和写的选通信号,以及字节访问和片选引脚。

在硬件连接上,SRAM与STM32F4通过FSMC接口进行互连。SRAM的片选信号CE与FSMC的NE3连接在一起。由此可知,SRAM被映射到Bank1的第3个存储区当中,显然,其首地址为0x68000000。由于SRAM的数据口有16根数据线,因此为加快访问速度,提高数据吞吐量,这里仍将数据宽度设置为16位宽。


此时,FSMC接口的一个地址,映射到AHB地址时对应2个地址空间,即u16数据类型所占宽度。但是,当用户按字节AHB地址空间时,如读取的是两个相邻字节地址空间(地址按2个字节对齐),则显然此时映射到FSMC接口时,地址是一个值,此时用户操作AHB地址空间中低地址的字节,即相当于操作了FSMC对应地址的低字节,而当用户操作AHB地址窠中高地址字节时,则相当于操作了FSMC同一地址空间中的高字节,即FSMC地址空间可以不变,但通过SRAM的UB和LB,分别访问了同一地址的不同字节。同理,由于UB和LB的存在,可以按字节操作FSMC接口的外部设备。


SRAM的初始化函数如下


void SRAM_Init()

{

  //1. 开时钟PD/PE/PF/PG

  RCC- >AHB1ENR  |= 0XF< < 3;


    //其他所有引脚复用为FSMC

    /*

      LCD_CS:PG12

      RS:PF12  = >FSMC_A[6]

      WR:PD5

      RD:PD4


      D0-D1:PD14/PD15

      D2-D3:PD0/PD1

      D4-D12:PE7-PE15

      D13-D15:PD8-PD10

    */

    //2. PD(配置为复用)

    GPIOD- >MODER    &= ~(0XF< < 0 | 0XF< < 8 | 0X3F< < 16 | 0xf< < 28);

    GPIOD- >MODER    |=  0X0a< < 0 | 0xa< < 8 | 0x2a < < 16 |0xa< < 28;        //PD口复用


    GPIOD- >OTYPER    &= ~(0X3< < 0 | 0X3< < 4 | 0X7< < 8 | 0X3< < 14);          //推挽

    GPIOD- >OSPEEDR   |= (0XF< < 0 | 0XF< < 8 | 0X3F< < 16 | 0xf< < 28);        //速度100Mhz

    GPIOD- >PUPDR     &= ~(0XF< < 0 | 0XF< < 8 | 0X3F< < 16 | 0xf< < 28);        //无上下拉


    GPIOD- >MODER    &= 0XF03FFFFF;    //PD11-PD13

    GPIOD- >MODER    |= 0X0A800000;    


    GPIOD- >OTYPER    &= ~(0X7< < 11);

    GPIOD- >OSPEEDR  |= 0X3F< < 22;

    GPIOD- >PUPDR    &= ~(0X3F< < 22);



    //PE口配置

    GPIOE- >MODER    &= 0X00003FFF;

    GPIOE- >MODER    |= 0Xaaaa8000;          //PE复用


    GPIOE- >OTYPER    &= 0X007F;              //PE7-15推挽

    GPIOE- >OSPEEDR  |= 0XFFFFC000;          //PE7-15速度为100Mhz

    GPIOE- >PUPDR    &= 0X00003FFF;          //PE7-15无上下拉


    GPIOE- >MODER    &= 0XFFFFFFF0;

    GPIOE- >MODER    |= 0X0000000A;          //PE0/1复用


    GPIOE- >OTYPER    &= 0XFFFFFFFC;        

    GPIOE- >OSPEEDR  |= 0X0000000F;        

    GPIOE- >PUPDR    &= 0XFFFFFFF0;      


    //FP12

    GPIOF- >MODER    &= ~(0X3< < 24);

    GPIOF- >MODER    |= 2< < 24;


    GPIOF- >OTYPER    &= ~(1< < 12);        //推挽

    GPIOF- >OSPEEDR  |= 0X3< < 24;          //100mHZ

    GPIOF- >PUPDR    &=  ~(0X3< < 24);      //无上下拉


//    fsmc_a0~fsmc_a5:PF0~PF5

//    FSMC_A7~FSMC_A9:PF13~PF15

    GPIOF- >MODER    &= 0X03FFF000;

    GPIOF- >MODER    |= 0XA8000AAA;


    GPIOF- >OTYPER    &= ~(0X3F< < 0 | 7< < 13);    //推挽

    GPIOF- >OSPEEDR  |= 0XFC000FFF;            //100mHZ

    GPIOF- >PUPDR    &=  0X03FFF000;          //无上下拉


    //FG10

    GPIOG- >MODER    &= ~(0X3< < 20);

    GPIOG- >MODER    |= 2< < 20;


    GPIOG- >OTYPER    &= ~(1< < 10);        //推挽

    GPIOG- >OSPEEDR  |= 0X3< < 20;          //100mHZ

    GPIOG- >PUPDR    &=  ~(0X3< < 20);      //无上下拉


//  FSMC_A10~FSMC_A15:PG0~PG5

    GPIOG- >MODER    &= 0XFFFFF000;

    GPIOG- >MODER    |= 0X00000AAA;


    GPIOG- >OTYPER    &= ~(0X3F< < 0);          //推挽

    GPIOG- >OSPEEDR  |= 0X00000fff;          //100mHZ

    GPIOG- >PUPDR    &=  0XFFFFF000;          //无上下拉




    //选择复用的功能:复用为FSMC

    //复用功能选择

    //PD:PD0/1/4/5/8-15



    GPIOD- >AFR[0] &= 0XFF00FF00;

    GPIOD- >AFR[0]  |= 0x00cc00cc;        //PD0/1/4/5复用为FSMC


    GPIOD- >AFR[1]  = 0;

    GPIOD- >AFR[1] |= 0XCCCCCCCC;        //PD8-15:复用为FSMC


    //PE:  

    GPIOE- >AFR[0]  &= 0X0FFFFF00;

    GPIOE- >AFR[0] |= 0XC00000CC;          //PE7复用为FSMC


    GPIOE- >AFR[1] &= 0x00000000;

    GPIOE- >AFR[1] |= 0XCCCCCCCC;        //PE8-15复用,可以直接往AFR[1]中赋值


    //PF:0-5 12-15

    GPIOF- >AFR[0] &= 0xff000000;

    GPIOF- >AFR[0] |= 0X00CCCCCC;          //PF0-5复用为FSMC


    GPIOF- >AFR[1] &= 0x0000ffff;

    GPIOF- >AFR[1] |= 0XCCCC0000;          //PF12-15复用为FSMC


    //PG:0-5  10

    GPIOG- >AFR[0] &= 0xff000000;

    GPIOG- >AFR[0] |= 0X00CCCCCC;          //PF0-5复用为FSMC


    GPIOG- >AFR[1] &= 0xfffFf0ff;

    GPIOG- >AFR[1] |= 0X00000C00;          //PG10复用为FSMC


    //配置FSMC


    //3. 开FSMC时钟 

    RCC- >AHB3ENR  |= 1< < 0;

    //4. 配置FSMC寄存器

      //BCR3

    FSMC_Bank1- >BTCR[4] &= ~(1< < 19);      //始终在异步模式下操作

    FSMC_Bank1- >BTCR[4] &= ~(1< < 15);      //不考虑等待信号

    FSMC_Bank1- >BTCR[4] |= 1< < 14;          //使能扩展功能,即读写时序分开

    FSMC_Bank1- >BTCR[4] &= ~(1< < 13);      //禁止等待nWait信号

    FSMC_Bank1- >BTCR[4] |= 1< < 12;          //使能写操作

    FSMC_Bank1- >BTCR[4] &= ~(0x3< < 4);

    FSMC_Bank1- >BTCR[4] |= 1< < 4;        //16位数据宽度 

    FSMC_Bank1- >BTCR[4] &= ~(0x3< < 2);      //存储器类型为:SRAM


  //BTR4:

  //BTR4(读时序)

    FSMC_Bank1- >BTCR[5]  &= ~(0x3< < 28);      //异步模式A

    FSMC_Bank1- >BTCR[5] |= 0xf< < 16;          //总线周转阶段持续时间为默认值

    FSMC_Bank1- >BTCR[5] &= 0xffff00ff;

    FSMC_Bank1- >BTCR[5] |= 5< < 8;            //DATAST为5HCLK

    FSMC_Bank1- >BTCR[5] |= 0x10< < 0;          //ADDSET为10HCLK


    //BWTR(写时序)

    FSMC_Bank1E- >BWTR[4] = 0;

    FSMC_Bank1E- >BWTR[4] &= ~(0x3< < 28);      //异步模式A

    FSMC_Bank1E- >BWTR[4] |= 0xf< < 16;        //总线周转阶段持续时间为默认值

    FSMC_Bank1E- >BWTR[4] |= 8< < 8;            //DATAST为3个HCLK

    FSMC_Bank1E- >BWTR[4] |= 0< < 0;            //ADDSET为3个HCLK  


    //使能存储块

    FSMC_Bank1- >BTCR[4] |= 1< < 0;  

}

在主函数中调用SRAM初始化函数,就可以直接操作SRAM,使用SRAM需要用到C语言中__attribute__ ((at()),绝对定位的应用。


u16 buf[512]   __attribute__((at(SRAM_ADD+0)));//定位到RAM中起始地址为SRAM_ADD处

定位到SRAM中,一般用于数据量比较大的缓存,如串口的接收缓存,再就是某个位置的特定变量。


主函数


#include "usart.h"

#include "stdio.h"

#include "stm32f4xx.h"

#include "stdlib.h"

#include "sram.h"



//注意:SRAM的使用空间为:0x68000000  ~ 0x680fffff

//所以,开辟空间时,要保证开辟的空间在SRAM内

u16 buf[512]   __attribute__((at(SRAM_ADD+0)));



int main()

{

  u32 i=0;

  Usart1_Init(115200);

  SRAM_Init();


  for(i=0;i< 512;i++)

      buf[i]  =  0;


  for(i=0;i< 512;i++)

      buf[i]  =  i;


  while(1)

  {

      for(i=0;i< 512;i++)

        printf("buf[%d] = %drn",i,buf[i]);

  }

}

编译后烧入程序运行,串口助手中可以看到打印出了写入SRAM中的数据。


图片

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>