開發平臺
- 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();
}