调试SDRAM-MT48LC

参考

https://mculover666.blog.csdn.net/article/details/108221735
https://www.waveshare.net/study/article-660-1.html

1.新建STM32CUBEMX工程

2.添加FMC模块

3.配置参数

 

 

 1.根据硬件设计选择SDCKE0(PC2\PC3)还是SDCKE1(PH6\PH7)

 2.根据芯片手册选择

 3.芯片决定9bits,列地址:A0~A8(9bits)

 4.芯片决定13bits,行地址:A0~A12(13bits)

 5.

 

 

 6.根据【配置1】默认选择

 7.根据芯片手册

 8.根据芯片手册

 

 9.根据芯片手册选择(因为芯片的最高速度为167,所以我们将180M进行2分频以后是90M)

 10.禁止写保护

 11.2分频

 12.使能突发模式提高读效率

 13.读延时配置

 14.根据芯片手册配置,因为2分频以后SDRAM主频90Mhz 所以1个时钟周期1/90M=11.11ns  

 

15.根据芯片手册配置

 

16.根据芯片手册配置

 

17.根据芯片手册配置

18.根据芯片手册配置

19.根据芯片手册配置

20.根据芯片手册配置

 

 

SDRAM初始化过程:

SDRAM初始化过程,图片来源于《高手进阶,终极内存技术指南——完整》(这个初始化过程SDRAM通用)

 

 

初始化过程分为五步:
① 上电
此步,给SDRAM供电,使能CLK时钟,并发送NOP(No Operation命令)等待最少200us。
② 发送预充电命令
第二步,就是发送预充电命令,给所有Bank预充电。
③ 发送自动刷新命令
这一步,至少要发送发送8次自刷新命令。
④ 设置模式寄存器
这一步,发送模式寄存器的值,配置SDRAM的工作参数。

 

最后一步设置:SDRAM刷新定时器(图片来源于STM32F4XX中文参考手册)

 

 

SDRAM 行地址:A0~A12(13bits),即有8192(2^13)行,F439的SDRAM时钟是90MHz。

刷新速率 = 64ms / 8192行 = 7.81us。

SDRAM 的刷新周期 = 7.81us * 90Mhz  - 20 = 682.9,取683

减20是为了有足够的时钟周期留个刷新。

 

复制代码
#define SDRAM_MODEREG_BURST_LENGTH_1             ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_LENGTH_2             ((uint16_t)0x0001)
#define SDRAM_MODEREG_BURST_LENGTH_4             ((uint16_t)0x0002)
#define SDRAM_MODEREG_BURST_LENGTH_8             ((uint16_t)0x0004)
#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL      ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED     ((uint16_t)0x0008)
#define SDRAM_MODEREG_CAS_LATENCY_2              ((uint16_t)0x0020)
#define SDRAM_MODEREG_CAS_LATENCY_3              ((uint16_t)0x0030)
#define SDRAM_MODEREG_OPERATING_MODE_STANDARD    ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE     ((uint16_t)0x0200)
 
/**
  * @brief  Perform the SDRAM exernal memory inialization sequence
  * @param  hsdram: SDRAM handle
  * @param  Command: Pointer to SDRAM command structure
  * @retval None
  */
static void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram)
{
    __IO uint32_t tmpmrd = 0;
    FMC_SDRAM_CommandTypeDef Command;
 
    /* Configure a clock configuration enable command */
    Command.CommandMode          = FMC_SDRAM_CMD_CLK_ENABLE;
    Command.CommandTarget          = FMC_SDRAM_CMD_TARGET_BANK2;
    Command.AutoRefreshNumber      = 1;
    Command.ModeRegisterDefinition = 0;
 
    /* Send the command */
    HAL_SDRAM_SendCommand(hsdram, &Command, 0x1000);
 
    /* Insert 10 ms delay */
    HAL_Delay(10);
 
    /* Configure a PALL (precharge all) command */
    Command.CommandMode          = FMC_SDRAM_CMD_PALL;
    Command.CommandTarget          = FMC_SDRAM_CMD_TARGET_BANK2;
    Command.AutoRefreshNumber      = 1;
    Command.ModeRegisterDefinition = 0;
 
    /* Send the command */
    HAL_SDRAM_SendCommand(hsdram, &Command, 0x1000);
 
    /* Configure a Auto-Refresh command */
    Command.CommandMode          = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
    Command.CommandTarget          = FMC_SDRAM_CMD_TARGET_BANK2;
    Command.AutoRefreshNumber      = 8;
    Command.ModeRegisterDefinition = 0;
 
    /* Send the command */
    HAL_SDRAM_SendCommand(hsdram, &Command, 0x1000);
 
    /* Program the external memory mode register */
    tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_8|
             SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   |
             SDRAM_MODEREG_CAS_LATENCY_3           |
             SDRAM_MODEREG_OPERATING_MODE_STANDARD |
             SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
 
    Command.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
    Command.CommandTarget          = FMC_SDRAM_CMD_TARGET_BANK2;
    Command.AutoRefreshNumber      = 1;
    Command.ModeRegisterDefinition = tmpmrd;
 
    /* Send the command */
    HAL_SDRAM_SendCommand(hsdram, &Command, 0x1000);
 
    /* Set the refresh rate counter */
    /* (7.81us x Freq) - 20 */
    /* Set the device refresh counter */
    HAL_SDRAM_ProgramRefreshRate(hsdram, 683);
}



复制代码
复制代码
int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_FMC_Init();
    MX_USART1_UART_Init();
 
    SDRAM_Initialization_Sequence(&hsdram1);
    printf("sudaroot\r\n");
 
    //使用SDRAM方法1
    uint32_t i = 0;
    uint16_t sdramtest[10] __attribute__((at(0XD0000000)));
    for(i = 0; i < 10; i++)
    {
        sdramtest[i] = i; 
    }
 
    for(i = 0; i < 10; i++)
    {
        printf("sdramtest[%d]:%d\r\n", i, sdramtest[i]);
    }
    
    //使用SDRAM方法2
    uint32_t temp = 100;
    *(__IO uint32_t*)(0XD0000400) = temp;
    temp = 0;
    temp = *(__IO uint32_t*)(0XD0000400);
    printf("temp = %u\r\n", temp);
 
    while (1)
    {
 
    }
}
复制代码

 最后说一下STM32 FMC地址映射关系,我使用的是SDRAM挂载在SDRAM Bank 2,所以开始地址是0xD0000000.

 

posted @   会编程的数组  阅读(416)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示