历史上的今天
今天是:2025年06月29日(星期日)
2019年06月29日 | STM32----SDRAM配置
2019-06-29 来源:eefocus
一、硬件环境
野火stm32F429第一代开发板,主频180。SDRAM为:IS42S16400J,容量8M/byte。
接线如下:

如何接线,需要参考两个文件。一个是stm32参考手册,一个是SDRAM数据手册。
stm32参考手册中关于FMC引脚说明如下:

SDRAM数据手册,太容易找就不贴出来了。
需要注意的是,FMC映射到SDRAM有两个bank可以选择。从上图可知选择不同的bank SDRAM需要接到MCU不同的
SDCKE以及SDNE引脚,且程序中应根据引脚选择驱动对应的bank。
二、初始化程序
程序初始化,只需按照SDRAM DATASHEET提供的时序初始化SDRAM芯片,填充FMC中SDRAM有关结构体的时序参数即可。
FMC控制SDRAM的初始化结构体主要有3个。
(1)初始化参数结构体
FMC_SDRAMInitTypeDef FMC_SDRAMInitStructure;
在此结构体设置FMC映射的SDRAM bank,突发模式,行列长度,ram的bank数量,时钟分频等参数:

(2)时序结构体
这个结构体主要设置SDRAM的读、写、预充电等的时序,具体填充的参数参考SDRAM手册:



需要注意的是,结构体并没有清楚写出tMRD,tRAS等字样,需要自己了解结构体成员的意义,才能从SDRAM
的手册中找到对应的参数填充。
(3)命令结构体
这个结构体主要使用来完成SDRAM的初始化步骤,按照SDRAM手册提供的步骤进行即可:

一个个步骤进行,即可成功初始化SDRAM:

最后切记,要设置刷新计数器,相关计算方法如下:
/* 设置刷新计数器 */
/*刷新速率 = (COUNT + 1) x SDRAM 频率时钟
COUNT =( SDRAM 刷新周期/行数) - 20*/
/* 64ms/4096=15.62us (15.62 us x FSDCLK) - 20 =1386 */
FMC_SetRefreshCount(1386);
/* 发送上述命令*/
while(FMC_GetFlagStatus(FMC_BANK_SDRAM, FMC_FLAG_Busy) != RESET)
{
}
模式寄存器参数解析如下图:

三、SDRAM读写
底层的时序由FMC完成,我们只需要像操控内存一样操控SDRAM即可。而SDRAM映射的地址,则可根据我们选择的bank

因为填充FMC结构体的时候是选择了Bnak2的,所以对应的地址:0xD000 0000 就是SDRAM的起始地址。
结束地址根据SDRAM的容量计算可知是:0xD07F FFFF。
完整的初始化代码如下:
/**
* @brief 初始化配置使用SDRAM的FMC及GPIO接口,
* 本函数在SDRAM读写操作前需要被调用
* @param None
* @retval None
*/
void SDRAM_Init(void)
{
FMC_SDRAMInitTypeDef FMC_SDRAMInitStruct;
FMC_SDRAMTimingInitTypeDef FMC_SDRAMTimingStruct;
FMC_SDRAMCommandTypeDef FMC_SDRAMCommandStruct;
//1、初始化GPIO
SDRAM_GPIO_Config();
//2、开启时钟与配置SDRAM结构体
RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FMC, ENABLE);
FMC_SDRAMTimingStruct.FMC_ExitSelfRefreshDelay = 6; //tXSR
FMC_SDRAMTimingStruct.FMC_LoadToActiveDelay = 2; //tMRD
FMC_SDRAMTimingStruct.FMC_RCDDelay = 2; //tRCD
FMC_SDRAMTimingStruct.FMC_RowCycleDelay = 6; //tRC
FMC_SDRAMTimingStruct.FMC_RPDelay = 2; //tRP
FMC_SDRAMTimingStruct.FMC_SelfRefreshTime = 4; //tRAS
FMC_SDRAMTimingStruct.FMC_WriteRecoveryTime = 2; //tWR
FMC_SDRAMInitStruct.FMC_Bank = FMC_Bank2_SDRAM;
FMC_SDRAMInitStruct.FMC_CASLatency = FMC_CAS_Latency_2;
FMC_SDRAMInitStruct.FMC_ColumnBitsNumber = FMC_ColumnBits_Number_8b;
FMC_SDRAMInitStruct.FMC_RowBitsNumber = FMC_RowBits_Number_12b;
FMC_SDRAMInitStruct.FMC_InternalBankNumber = FMC_InternalBank_Number_4;
FMC_SDRAMInitStruct.FMC_ReadBurst = FMC_Read_Burst_Enable;
FMC_SDRAMInitStruct.FMC_ReadPipeDelay = FMC_ReadPipe_Delay_0; //读延迟
FMC_SDRAMInitStruct.FMC_SDClockPeriod = FMC_SDClock_Period_2; //2分频
FMC_SDRAMInitStruct.FMC_SDMemoryDataWidth = FMC_SDMemory_Width_16b;
FMC_SDRAMInitStruct.FMC_WriteProtection = FMC_Write_Protection_Disable;
FMC_SDRAMInitStruct.FMC_SDRAMTimingStruct = &FMC_SDRAMTimingStruct;
FMC_SDRAMInit(&FMC_SDRAMInitStruct);
//3、按照SDRAM初始化顺序初始化SDRAM
//CLK使能
FMC_SDRAMCommandStruct.FMC_AutoRefreshNumber = 0;
FMC_SDRAMCommandStruct.FMC_CommandMode = FMC_Command_Mode_CLK_Enabled;
FMC_SDRAMCommandStruct.FMC_CommandTarget = FMC_Command_Target_bank2;
FMC_SDRAMCommandStruct.FMC_ModeRegisterDefinition = 0;
while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET);
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStruct);
//所有bank预充电
FMC_SDRAMCommandStruct.FMC_AutoRefreshNumber = 0;
FMC_SDRAMCommandStruct.FMC_CommandMode = FMC_Command_Mode_PALL;
FMC_SDRAMCommandStruct.FMC_CommandTarget = FMC_Command_Target_bank2;
FMC_SDRAMCommandStruct.FMC_ModeRegisterDefinition = 0;
while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET);
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStruct);
//自动刷新2次
FMC_SDRAMCommandStruct.FMC_AutoRefreshNumber = 2;
FMC_SDRAMCommandStruct.FMC_CommandMode = FMC_Command_Mode_AutoRefresh;
FMC_SDRAMCommandStruct.FMC_CommandTarget = FMC_Command_Target_bank2;
FMC_SDRAMCommandStruct.FMC_ModeRegisterDefinition = 0;
while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET);
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStruct);
//设置模式寄存器
FMC_SDRAMCommandStruct.FMC_AutoRefreshNumber = 1; //此处设置为0也能通过测试
FMC_SDRAMCommandStruct.FMC_CommandMode = FMC_Command_Mode_LoadMode;
FMC_SDRAMCommandStruct.FMC_CommandTarget = FMC_Command_Target_bank2;
FMC_SDRAMCommandStruct.FMC_ModeRegisterDefinition =
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL|
SDRAM_MODEREG_OPERATING_MODE_STANDARD|
SDRAM_MODEREG_CAS_LATENCY_2 |
SDRAM_MODEREG_BURST_LENGTH_8|
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET);
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStruct);
/* 设置刷新计数器 */
/*刷新速率 = (COUNT + 1) x SDRAM 频率时钟
COUNT =( SDRAM 刷新周期/行数) - 20*/
/* 64ms/4096=15.62us (15.62 us x FSDCLK) - 20 =1386 */
FMC_SetRefreshCount(1386);
while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET);
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStruct);
}
史海拾趣
|
Nand Flash结构与读写分析 NAND Flash 的数据是以bit 的方式保存在memory cell,一般来说,一个cell 中只能存储一个bit。这些cell 以8 个或者16 个为单位,连成bit line,形成所谓的byte(x8)/word(x16),这就是NAND Device 的位宽。这些Line 会再 ...… 查看全部问答> |
|
#include __CONFIG (INTRC & PROTECT & MCLREN & WDTEN); const unsigned char cs @ 0x1FF; void DelayUs( int x) // 32US {while(--x!=0) { CLRWDT(); NOP(); unsigned ...… 查看全部问答> |
|
现在有一个应用程序,实时性不够,想在windows下加一个实时模块!经过查找资料,目前确定的方案是添加一个实时驱动模块,而这个模块就用一个内核模式驱动程序来实现!该程序通过接管实时定时器的中断,也就是系统时钟中断,然后先将控制权交给实时 ...… 查看全部问答> |
|
在EVC下开发程序,有一个基于MFC Extension的动态库,其中包含有多个对话框架及一个菜单项,现在创建一个MFC应用程序,不知怎么调用此动态库,求助一下大家,谢谢!… 查看全部问答> |
|
请使用英文版 Visual studio 2005/2008的朋友帮个小忙,谢谢! 公司要找其它公司做应用软件,用WINCE生成的SDK还得附加个英文的使用说明,但是我的VS是中文版的,截图全是中文字,公司的人说不行,所以请使用英文版的朋友帮我截个图,非常感谢! 发到我的邮箱里就可以veabolho@126.com 截图的内容就像这张 … 查看全部问答> |
|
最近做项目的时候碰到了一个因为局部变量导致堆栈越界的问题,虽然最后靠扩大堆栈空间暂时解决了,但这也限制了全局变量的定义。有没有一种好的方法来解决这些问题了?看了看编译后的MAP文件,发现MDK将STACK放在了最后一个全局变量的后面。现 ...… 查看全部问答> |




