STM32 FSMC操作SRAM的步骤简析

存储技术

606人已加入

描述

本次操作的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中的数据。

控制器

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分