上午又犯精神病了,现在来整理一下SRAM:)
STM32F407ZGT6自带了192K的SRAM,好了,习惯性的先来解释一下SRAM拿来干嘛用。
之前的flash章已经阐明了我的F4的代码是存储在flash中的,在keil中也查看了,是从flash主存储器中的扇区0开始存储的(所以若是要将flash模拟成EEPROM存储数据的话,最好是从扇区11,也就是最后一个扇区开始存起,防止将原来的代码段给覆盖了,什么,你要问为什么不能覆盖?覆盖了的话原来的代码段就消失了,原本好好的一整段程序就被截肢了,自行脑补resident evil7里的玛格丽特。。说正经的就是程序会跑到某一步就不走了,嗯:)。好了,bb完flash之后,那么SRAM又是什么呢?
SRAM:Static Random Access Memory,静态随机存取存储寄存器,和flash不同的是,SRAM掉电了的话,之前存储在SRAM里的数据就消失了,保不住。所以SRAM不能用来给我们存储数据用,只能用来当作高速缓存。除了SRAM,还有一种DRAM,同样也是掉电易失,相比于SRAM,DRAM每隔一段时间,要刷新充电一次,否则内部的数据即会消失,SRAM则不需要刷新充电(在系统上电之后SRAM中的数据是不会丢失的,DRAM则是就算系统上电之后还得不一会儿的刷新充电一下数据才得以保存),所以相对来说,SRAM的速度要比DRAM快,但是SRAM的物理体积较大,同容量的RAM,SRAM要比DRAM的物理体积大好多。
有时候系统自带的SRAM可能会出现不够用的情况,比如说跑GUI。。那么就得再外挂一片SRAM,这里以IS62WV51216为例,说一下怎样挂载并使用这片1M的SRAM:)
IS62WV51216:16bit宽512K,16*512K=1M字节,SRAM。功能框图如下:
显然,A0~A18为地址线,共19根地址线,相对应的,就有1M的字节可供寻址了。
沿着图往下看,VDD供电,GND接地,IO07和IO815一共16根数据线,支持16bit数据传输。
CS2为高电平有效的片选端,CS1为低电平有效的片选端,OE为低电平有效的输出使能端,WE为低电平有效的写使能端,UB为低电平有效的高字节控制信号,LB为低电平有效的低字节控制信号。
F4有FSMC模块,可以用FSMC来驱动这片SRAM。
首先查看原子哥F4板子上有关SRAM的原理图:
A0A18被连接到了FSMC的A018(但不是按顺序连接的,原子哥为了排线方便画板时就这么连接了),顺序不一一对应并没有什么影响,init的时候注意改过来就行了。IO的015是按顺序连接到FSMC的D015上的,还算是良心走线。UB,LB,OE,WE,CE也如图所示连接。搞清楚了物理接线顺序之后就可以开始init了。
Init并没有什么内容,按照顺序来就行:
1.初始化GPIO时钟。
2.配置GPIO为上拉推挽输出,复用功能模式。
//
A0->FSMC_A0:PF0=IO0->FSMC_D0:PD14
A1->FSMC_A1:PF1=IO1->FSMC_D1:PD15
A2->FSMC_A2:PF2=IO2->FSMC_D2:PD0
A3->FSMC_A3:PF3=IO3->FSMC_D3:PD1
A4->FSMC_A4:PF4 =IO4->FSMC_D4:PE7
A5->FSMC_A18:PD13=IIO5->FSMC_D5:PE8
A6->FSMC_A17:PD12=IO6->FSMC_D6:PE9
A7->FSMC_A16:PD11===IIO7->FSMC_D7:PE10
A8->FSMC_A13:PG3 ================IO8->FSMC_D8:PE11
A9->FSMC_A14:PG4 ================IO9->FSMC_D9:PE12
A10->FSMC_A15:PG5 ===============IO10->FSMC_D10:PE13
A11->FSMC_A5:PF5 ================IO11->FSMC_D11:PE14
A12->FSMC_A7:PF13 ===============IO12->FSMC_D12:PE15
A13->FSMC_A8:PF14 ===============IO13->FSMC_D13:PD8
A14->FSMC_A9:PF15 =IO14->FSMC_D14:PD9
A15->FSMC_A10:PG0=IO15->FSMC_D15:PD10
A16->FSMC_A11:PG1
A17->FSMC_A6:PF12
A18->FSMC_A12:PG2
/*/
UB->FSMC_NBL1:PE1
LB->FSMC_NBL0:PE0
OE->FSMC_NOE:PD4
WE->FSMC_NWE:PD5
CE->FSMC_NE3:PG10
/***************************************/
相关代码如下:
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD|
RCC_AHB1Periph_GPIOF|
RCC_AHB1Periph_GPIOG, ENABLE);//使能时钟
//GPIOD——Init
GPIO_InitStructure.GPIO_Pin = (3<<0)|(3<<4)|(0XFF<<8);//PD0,1,4,5,8~15 AF OUT
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
GPIO_Init(GPIOD, &GPIO_InitStructure);//初始化有关GPIOD有关的所有IO
。
。期间重复代码不再贴出
。
//复用功能连线
GPIO_PinAFConfig(GPIOD,GPIO_PinSource0,GPIO_AF_FSMC);
。
。期间重复代码不再贴出
。
GPIO初始化的工作完成之后,接着开始配置FSMC,相关代码如下:
readWriteTiming.FSMC_AddressSetupTime = 0x00; //地址建立时间,ADDSET,为1个HCLK 1/36M=27ns
readWriteTiming.FSMC_AddressHoldTime = 0x00; //地址保持时间,ADDHOLD,模式A没有用到
readWriteTiming.FSMC_DataSetupTime = 0x08; //数据保持时间,DATASET,为9个HCLK,6*9=54ns
readWriteTiming.FSMC_BusTurnAroundDuration = 0x00;
readWriteTiming.FSMC_CLKDivision = 0x00;
readWriteTiming.FSMC_DataLatency = 0x00;
readWriteTiming.FSMC_AccessMode = FSMC_AccessMode_A; //模式A
FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM3;//硬件连接的就是NE3,故初始化为NORSRAM3
FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
FSMC_NORSRAMInitStructure.FSMC_MemoryType =FSMC_MemoryType_SRAM;
FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b; //16位数据宽度
FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode =FSMC_BurstAccessMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait=FSMC_AsynchronousWait_Disable;
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; //读写使用相同的时序,这片SRAM读写时序可从其芯片手册中找到,是相同的,所以这么配置。
FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &readWriteTiming;
FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &readWriteTiming; //读写使用相同的时序
FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); //初始化FSMC
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM3, ENABLE); //使能BANK1的区域3
上面两部分的代码合起来就能初始化SRAM了。
初始化SRAM完成之后,我们就可以往SRAM中肆意的烧/读数据啦~:)
FSMC_SRAM写数据部分:
//@func: 在指定地址(WriteAddr+Bank1_SRAM3_ADDR)开始,连续写入n个字节
//@param: pBuffer,字节指针
// WriteAddr,写入的首地址
// n,想要写入的字节数
void FSMC_SRAM_WriteBuffer(u8* pBuffer,u32 WriteAddr,u32 n)
{
for(;n!=0;n--)
{
*(vu8*)(Bank1_SRAM3_ADDR+WriteAddr)=*pBuffer;
WriteAddr++;
pBuffer++;
}
}
FSMC_SRAM读数据部分:
//@func: 在指定地址(WriteAddr+Bank1_SRAM3_ADDR)开始,连续读入n个字节
//@param: pBuffer,字节指针
// ReadAddr,写入的首地址
// n,想要读入的字节数
void FSMC_SRAM_ReadBuffer(u8* pBuffer,u32 ReadAddr,u32 n)
{
for(;n!=0;n--)
{
*pBuffer++=*(vu8*)(Bank1_SRAM3_ADDR+ReadAddr);
ReadAddr++;
}
}