用户工具

站点工具


sdram实验_读写sdram
银杏科技有限公司旗下技术文档发布平台
技术支持电话0379-69926675-801
技术支持邮件Gingko@vip.163.com
版本 日期 作者 修改内容
V1.0 2020-07-12 gingko 初次建立

实验三十七:SDRAM实验——读写SDRAM

一、 实验目的与意义

  1. 了解STM32 SDRAM结构。
  2. 了解STM32 SDRAM特征。
  3. 掌握SDRAM的使用方法。
  4. 掌握STM32 HAL库中SDRAM属性的配置方法。
  5. 掌握KEILMDK 集成开发环境使用方法。

二、 实验设备及平台

  1. iCore4 双核心板点击购买
  2. JLINK(或相同功能)仿真器点击购买
  3. Micro USB线缆。
  4. Keil MDK 开发平台。
  5. STM32CubeMX开发平台。
  6. 装有WIN XP(及更高版本)系统的计算机。

三、 实验原理

1、SDRAM简介

  • SDRAM,英文名是:Synchronous Dynamic Random Access Memory,即同步动态随机存储器,相较于SRAM(静态存储器),SDRAM具有:容量大和价格便宜的特点。STM32F767支持SDRAM,因此,我们可以外挂SDRAM,从而大大降低外扩内存的成本。
  • 同步动态随机存取内存(SDRAM)是有一个同步接口的动态随机存取内存(DRAM)。通常DRAM是有一个异步接口的,这样它可以随时响应控制输入的变化。而SDRAM有一个同步接口,在响应控制输入前会等待一个时钟信号,这样就能和计算机的系统总线同步。时钟被用来驱动一个有限状态机,对进入的指令进行管线(Pipeline)操作。这使得SDRAM与没有同步接口的异DRAM(asynchronous DRAM)相比,可以有一个更复杂的操作模式。管线意味着芯片可以在处理完之前的指令前,接受一个新的指令。在一个写入的管线中,写入命令在另一个指令执行完之后可以立刻执行,而不需要等待数据写入存储队列的时间。在一个读取的流水线中,需要的数据在读取指令发出之后固定数量的时钟频率后到达,而这个等待的过程可以发出其它附加指令。
  • SDRAM是多Bank结构,例如在一个具有两个Bank的SDRAM的模组中,其中一个Bank在进行预充电期间,另一个Bank却马上可以被读取,这样当进行一次读取后,又马上去读取已经预充电Bank的数据时,就无需等待而是可以直接读取了,这也就大大提高了存储器的访问速度。为了实现这个功能,SDRAM需要增加对多个Bank的管理,实现控制其中的Bank进行预充电。在一个具有2个以上Bank的SDRAM中,一般会多一根叫做BAn的引脚,用来实现在多个Bank之间的选择。
  • SDRAM具有多种工作模式,内部操作是一个复杂的状态机。SDRAM器件的引脚分为以下几类。
    • (1)控制信号:包括片选、时钟、时钟使能、行列地址选择、读写有效及数据有效。
    • (2)地址信号:时分复用引脚,根据行列地址选择引脚,控制输入的地址为行地址或列地址。
    • (3)数据信号:双向引脚,受数据有效控制。
  • SDRAM的所有操作都同步于时钟。根据时钟上升沿控制管脚和地址输入的状态,可以产生多种输入命令:
    • 模式寄存器设置命令
    • 激活命令
    • 预充命令
    • 读命令
    • 写命令
    • 带预充的读命令
    • 带预充的写命令
    • 自动刷新命令
    • 自我刷新命令
    • 突发停命令
    • 空操作命令
  • 根据输入命令,SDRAM状态在内部状态间转移。内部状态包括模式寄存器设置状态、激活状态、预充状态、写状态、读状态、预充读状态、预充写状态、自动刷新状态及自我刷新状态。
  • SDRAM支持的操作命令有初始化配置、预充电、行激活、读操作、写操作、自动刷新、自刷新等。所有的操作命令通过控制线CS#、RAS#、CAS#、WE#和地址线、体选地址BA输入。

2、SDRAM信号线

  • SDRAM的信号线如图所示:

3、SDRAM存储单元

  • SDRAM的存储单元(称之为:BANK)是以阵列的形式排列的,每个存储单元的结构示意图,如图所示:

  • 对于这个存储阵列,我们可以将其看成是一个表格,只需要给定行地址和列地址,就可以确定其唯一位置,这就是SDRAM寻址的基本原理。而一个SDRAM芯片内部,一般又有4个这样的存储单元(BANK),所以,在SDRAM内部寻址的时候,先指定BANK号和行地址,然后再指定列地址,就可以查找到目标地址。
  • SDRAM的存储结构示意图,如图下所示,寻址的时候,首先RAS信号为低电平,选通行地址,地址线A0~A12所表示的地址,会被传输并锁存到行地址译码器里面,最为行地址,同时BANK地址线上面的BS0,BS1所表示的BANK地址,也会被锁存,选中对应的BANK,然后,CAS信号为低电平,选通列地址,地址线A0~A12所表示的地址,会被传输并锁存到列地址译码器里面,作为列地址,这样,就完成了一次寻址。

4、数据传输

  • 在完成寻址以后,数据线DQ0~DQ15上面的数据会通过数据控制逻辑写入(或读出)存储阵列。特别注意:因为SDRAM的位宽,可以达到32位,也就是最多有32条数据线,在实际使用的时候,我们可能会以:8位、16位、24位和32位等宽度来读写数据,这样的话,并不是每条数据线,都会被使用到,未被用到的数据线上面的数据,必须被忽略,这个时候就需要用到数据掩码(DQM)线来控制了,每一个数据掩码线,对应8个位的数据,低电平表示对应数据位有效,高电平表示对应数据位无效。
  • SDRAM的驱动需要用到一些命令,常用的命令如图所示:

5、原理图

四、 实验程序

1、主函数

int main(void)
{
  int i,j;
  /* MCU 配置*/
  /* 重置所有外设, 初始化Flash 接口和Systick. */
  HAL_Init();
  /* 系统时钟配置 */
  SystemClock_Config();
  /* 初始化所有已配置的外设 */
  MX_GPIO_Init();
    //SDRAM初始化
  BSP_SDRAM_Init();       
  LED_BLUE_ON;
  //向SDRAM中写入0x5555并读取校验
  for(i = 0;i < SDRAM_SIZE;i++){ 
      write_sdram(i,0x5555);
    }
    for(i = 0;i < SDRAM_SIZE;i++){
        if(0x5555 != read_sdram(i)){
            while(1){
                LED_RED_ON;
                HAL_Delay(500);
                LED_RED_OFF;
                HAL_Delay(500);
            }
        }
    }
    //向SDRAM中写入0xAAAA并读取校验
    for(i = 0;i < SDRAM_SIZE;i++){ 
        write_sdram(i,0xAAAA);
    }
    for(i = 0;i < SDRAM_SIZE;i++){
        if(0xAAAA != read_sdram(i)){
            while(1){
                LED_RED_ON;
                HAL_Delay(500);
                LED_RED_OFF;
                HAL_Delay(500);
            }
        }
    }   
    //向SDRAM中写入0x0000~0xFFFF并读取校验
    for(j = 0; j < 256; j++){
        for(i = 0;i < 65536;i++){
            write_sdram((65536 * j + i),i);
        }
    }
    for(j = 0; j < 256; j ++){
        for(i = 0;i < 65536;i++){
            if(i != read_sdram((65536 * j + i))){
                while(1){
                    LED_RED_ON;
                    HAL_Delay(500);
                    LED_RED_OFF;
                    HAL_Delay(500);
                }
            }
        }
    }   
 
    //测试成功
    LED_BLUE_OFF;
    LED_GREEN_ON;
  while (1)
  {
  }
}

2、SDRAM初始化

uint8_t BSP_SDRAM_Init(void)
{ 
  static uint8_t sdramstatus = SDRAM_ERROR;
  /* SDRAM设备配置 */
  /* SDRAM时钟频率为100Mhz的定时配置(系统时钟最高为200Mhz) */
  Timing.LoadToActiveDelay    = 2;
  Timing.ExitSelfRefreshDelay = 7;
  Timing.SelfRefreshTime      = 4;
  Timing.RowCycleDelay        = 7;
  Timing.WriteRecoveryTime    = 2;
  Timing.RPDelay              = 2;
  Timing.RCDDelay             = 2;
 
  sdramHandle.Init.SDBank             = FMC_SDRAM_BANK1;
  sdramHandle.Init.ColumnBitsNumber   = FMC_SDRAM_COLUMN_BITS_NUM_9;
  sdramHandle.Init.RowBitsNumber      = FMC_SDRAM_ROW_BITS_NUM_13;
  sdramHandle.Init.MemoryDataWidth    = SDRAM_MEMORY_WIDTH;
  sdramHandle.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
  sdramHandle.Init.CASLatency         = FMC_SDRAM_CAS_LATENCY_3;
  sdramHandle.Init.WriteProtection    = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
  sdramHandle.Init.SDClockPeriod      = SDCLOCK_PERIOD;
  sdramHandle.Init.ReadBurst          = FMC_SDRAM_RBURST_ENABLE;
  sdramHandle.Init.ReadPipeDelay      = FMC_SDRAM_RPIPE_DELAY_1;
  /* SDRAM控制器初始化 */
  BSP_SDRAM_MspInit(&sdramHandle, NULL); /* __weak函数可以被应用程序重写*/
  if(HAL_SDRAM_Init(&sdramHandle, &Timing) != HAL_OK)
  {
    sdramstatus = SDRAM_ERROR;
  }
  else
  {
    sdramstatus = SDRAM_OK;
  }
  /* SDRAM初始化顺序 */
  BSP_SDRAM_Initialization_sequence(REFRESH_COUNT);
  return sdramstatus;
}
 
 

3、SDRAM读写函数

#define SDRAM_SIZE SDRAM_DEVICE_SIZE
#define write_sdram(offset,data) *(volatile unsigned short int *)(SDRAM_DEVICE_ADDR + (offset << 1)) = data
#define read_sdram(offset) *(volatile unsigned short int *)(SDRAM_DEVICE_ADDR + (offset << 1))

五、 实验步骤

  1. 把仿真器与iCore4的SWD调试口相连(直接相连或者通过转接器相连);
  2. 把iCore4通过Micro USB线与计算机相连,为iCore4供电;
  3. 打开Keil MDK 开发环境,并打开本实验工程;
  4. 烧写程序到iCore4上;
  5. 也可以进入Debug模式,单步运行或设置断点验证程序逻辑。

六、 实验现象

  • 上电即开始读写SDRAM测试,测试过程中,蓝色LED点亮,如果出现错误,红色LED闪烁,测试成功,绿色LED点亮。
sdram实验_读写sdram.txt · 最后更改: 2022/03/22 10:26 由 sean