FMC扩展SDRAM
程序员文章站
2024-02-25 14:30:03
...
开发平台
- F429
- 标准库
SDARM
如何控制SDRAM
- 控制线:控制SDRAM需要命令去控制,控制线在不同状态下形成不同的命令
- 地址线:用来选取地址的,分成A类线和BA类,A是行和列的地址总线,BA是用来选取BANK的独立地线(一般的SDRAM都有4个BANK)。
如何选取地址:首先选择BANK的序号,然后再选行和列 - 数据线:用来输入输出数据(一共有16位),这个型号的SDRAM,数据线宽位16,当我们写入数据的时候不一定会写入16位,这个时候就会用到DQM来控制,8位有效还是16位有效
SDRAM的命令
- 禁止命令
- 空操作
- 行有效
- 列读写
- 预充电:重新发送行列地址,A10这条线可以进行单独控制,A10高电平时对所有BANK进行预充电,为低电平时对BA线选定的BANK进行预充电。(所有的BANK都要预充电)
- 自动刷新和自我刷新:CKE时钟线为低电平时,使用自动刷新,否者使用自我刷新。一般进入低功耗时,才会使用自我刷新(刷新周期为64ms)
- 加载模式寄存器:在SDRAM启动时需要配置(寄存器如下图)
(A0-A2)BL突发长度:在同一行中连续读写的存储单元,一般长度有1、2、4、8
(A3)BT突发类型:顺序突发和间隔突发(一般选择顺序突发)
(A4-A6):CL列选通后的延迟时间:一般是2、3个周期
(A7-A8):00正常模式
(A9):选择突发模式还是非突发模式
FMC
- FMC引脚:MCU上的引脚与SDRAM上面对应的引脚相连
- FMC寄存器的配置
- 设置SDRAM通讯的频率(SDRAM通讯最高频率为90MHZ)
SDRAM启动
- 开启时钟 等待至少100us
- 对所有的BANK进行预充电
- 自动刷新
- 设置加载模式寄存器(如何配置,根据实际情况填写寄存器的值)
- 设置刷新计数器的值:SDRAM的刷新周期为64ms、行数为4096
计算公式:
static void SDARM_Init(void)
{
uint32_t tmpr=0;
FMC_SDRAMCommandTypeDef FMC_SDRAMCommandStruct;
/*开启芯片时钟*/
FMC_SDRAMCommandStruct.FMC_CommandMode=FMC_Command_Mode_CLK_Enabled;
FMC_SDRAMCommandStruct.FMC_CommandTarget=FMC_Command_Target_bank2;
FMC_SDRAMCommandStruct.FMC_AutoRefreshNumber=0;
FMC_SDRAMCommandStruct.FMC_ModeRegisterDefinition=0;
while(FMC_GetFlagStatus(FMC_Bank2_SDRAM,FMC_FLAG_Busy)!=RESET)
{
}
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStruct);
DELAY_us(1000);
/*对所有bank预充电*/
FMC_SDRAMCommandStruct.FMC_CommandMode=FMC_Command_Mode_PALL;
FMC_SDRAMCommandStruct.FMC_CommandTarget=FMC_Command_Target_bank2;
FMC_SDRAMCommandStruct.FMC_AutoRefreshNumber=0;
FMC_SDRAMCommandStruct.FMC_ModeRegisterDefinition=0;
while(FMC_GetFlagStatus(FMC_Bank2_SDRAM,FMC_FLAG_Busy)!=RESET)
{
}
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStruct);
/*自动刷新*/
FMC_SDRAMCommandStruct.FMC_CommandMode=FMC_Command_Mode_AutoRefresh;
FMC_SDRAMCommandStruct.FMC_CommandTarget=FMC_Command_Target_bank2;
FMC_SDRAMCommandStruct.FMC_AutoRefreshNumber=2;
FMC_SDRAMCommandStruct.FMC_ModeRegisterDefinition=0;
while(FMC_GetFlagStatus(FMC_Bank2_SDRAM,FMC_FLAG_Busy)!=RESET)
{
}
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStruct);
/*设置SDRAM寄存器*/
tmpr=(uint32_t)SDRAM_MODEREG_BURST_LENGTH_4 |
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
SDRAM_MODEREG_CAS_LATENCY_2 |
SDRAM_MODEREG_OPERATING_MODE_STANDARD|
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ;
FMC_SDRAMCommandStruct.FMC_CommandMode=FMC_Command_Mode_LoadMode;
FMC_SDRAMCommandStruct.FMC_CommandTarget=FMC_Command_Target_bank2;
FMC_SDRAMCommandStruct.FMC_AutoRefreshNumber=1;
FMC_SDRAMCommandStruct.FMC_ModeRegisterDefinition=tmpr;
while(FMC_GetFlagStatus(FMC_Bank2_SDRAM,FMC_FLAG_Busy)!=RESET)
{
}
FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStruct);
/*设置刷新计数器*/
FMC_SetRefreshCount(1386);
while(FMC_GetFlagStatus(FMC_Bank2_SDRAM,FMC_FLAG_Busy)!=RESET)
{
}
}
FMC初始化
- SDRAM的时序参数,需要看手册去配置
一个时钟周期为1/90M=11.11ns
- 配置FMC_SDRAM的参数
void FMC_Init(void)
{
FMC_SDRAMTimingInitTypeDef FMC_SDRAMTimingStruct;
FMC_SDRAMInitTypeDef FMC_SDRAMInitStruct;
FMC_GPIO_Init();
RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FMC,ENABLE);
FMC_SDRAMTimingStruct.FMC_ExitSelfRefreshDelay=7;
FMC_SDRAMTimingStruct.FMC_LoadToActiveDelay=2;
FMC_SDRAMTimingStruct.FMC_RCDDelay=2;
FMC_SDRAMTimingStruct.FMC_RowCycleDelay=7;
FMC_SDRAMTimingStruct.FMC_RPDelay=2;
FMC_SDRAMTimingStruct.FMC_SelfRefreshTime=4;
FMC_SDRAMTimingStruct.FMC_WriteRecoveryTime=2;
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_InternalBankNumber=FMC_InternalBank_Number_4;
FMC_SDRAMInitStruct.FMC_ReadBurst=FMC_Read_Burst_Enable;
FMC_SDRAMInitStruct.FMC_ReadPipeDelay=FMC_ReadPipe_Delay_0;
FMC_SDRAMInitStruct.FMC_RowBitsNumber=FMC_RowBits_Number_12b;
FMC_SDRAMInitStruct.FMC_SDClockPeriod=FMC_SDClock_Period_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);
DELAY_us(50000);
/*SDRAM初始化*/
SDARM_Init();
}