存储技术
本次操作的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中的数据。
全部0条评论
快来发表一下你的评论吧 !