文章目录
一、sdram介绍
SDRAM,英文名是: Synchronous Dynamic Random Access Memory,即同步动态随机存储器,相较于 SRAM(静态存储器), SDRAM 具有:容量大和价格便宜的特点。
二、W9825G6KH芯片介绍
2.1 芯片内部结构
芯片内部结构如下图
2.2 芯片引脚说明
- CLK:时钟信号,在该时钟的上升沿采集输入信号
- CKE:时钟使能,禁止时钟时, SDRAM 会进入自刷新模式
- CS:片选信号,低电平有效
- RAS:行地址选通信号,低电平时,表示行地址
- CAS:列地址选通信号,低电平时,表示列地址
- WE:写使能信号,低电平有效
- A0~A12:地址线(行/列)
- BS0, BS1:BANK 地址线
- DQ0~15:数据线
- LDQM,UDQM:数据掩码,表示 DQ 的有效部分
2.3 芯片工作原理
2.3.1 寻址
- 首先 RAS 信号为低电平,选通行地址,地址线 A0~A12 所表示的地址,会被传输并锁存到行地址译码器里面,作为行地址,同时 BANK 地址线上面的 BS0, BS1 所表示的 BANK 地址,也会被锁存,选中对应的 BANK。
- 然后, CAS 信号为低电平,选通列地址,地址线 A0~A12 所表示的地址,会被传输并锁存到列地址译码器里面,作为列地址,这样,就完成了一次寻址。
总结:RAS低电平期间,选择BANK和行地址;CAS低电平期间,选择列地址。
2.3.2 数据传输
寻址过后,就可以读写sdram中的数据。
三、cubemx配置
W9825G6KH地址线A0~A12共13位,内部有4个bank,数据从DQ0到DQ15共16位,这里使用两片W9825G6KH组成32位,每片提供32M字节的sdram,两片可提供64M字节的sdram。
列地址A0-A8共9个位,行地址A0-A12共13个位。
配置W9825G6KH的延时参数如下:
四、sdram的使用
初始化时序
//SDRAM配置参数
#define SDRAM_MODEREG_BURST_LENGTH_1 ((u16)0x0000)
#define SDRAM_MODEREG_BURST_LENGTH_2 ((u16)0x0001)
#define SDRAM_MODEREG_BURST_LENGTH_4 ((u16)0x0002)
#define SDRAM_MODEREG_BURST_LENGTH_8 ((u16)0x0004)
#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((u16)0x0000)
#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((u16)0x0008)
#define SDRAM_MODEREG_CAS_LATENCY_2 ((u16)0x0020)
#define SDRAM_MODEREG_CAS_LATENCY_3 ((u16)0x0030)
#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((u16)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((u16)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((u16)0x0200)
//发送命令函数,下面的初始化时序需要使用
u8 SDRAM_Send_Cmd(u8 bankx,u8 cmd,u8 refresh,u16 regval)
{
u32 target_bank=0;
FMC_SDRAM_CommandTypeDef Command;
if(bankx==0) target_bank=FMC_SDRAM_CMD_TARGET_BANK1;
else if(bankx==1) target_bank=FMC_SDRAM_CMD_TARGET_BANK2;
Command.CommandMode=cmd; //命令
Command.CommandTarget=target_bank; //目标SDRAM存储区域
Command.AutoRefreshNumber=refresh; //自刷新次数
Command.ModeRegisterDefinition=regval; //要写入模式寄存器的值
if(HAL_SDRAM_SendCommand(&hsdram1,&Command,0XFFFF)==HAL_OK) //向SDRAM发送命令
{
return 0;
}
else return 1;
}
//发送SDRAM初始化序列
void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram)
{
u32 temp=0;
//SDRAM控制器初始化完成以后还需要按照如下顺序初始化SDRAM
SDRAM_Send_Cmd(0,FMC_SDRAM_CMD_CLK_ENABLE,1,0); //时钟配置使能
HAL_Delay(1); //至少延时200us
SDRAM_Send_Cmd(0,FMC_SDRAM_CMD_PALL,1,0); //对所有存储区预充电
SDRAM_Send_Cmd(0,FMC_SDRAM_CMD_AUTOREFRESH_MODE,8,0);//设置自刷新次数
//配置模式寄存器,SDRAM的bit0~bit2为指定突发访问的长度,
//bit3为指定突发访问的类型,bit4~bit6为CAS值,bit7和bit8为运行模式
//bit9为指定的写突发模式,bit10和bit11位保留位
temp=(u32)SDRAM_MODEREG_BURST_LENGTH_4 | //设置突发长度:1(可以是1/2/4/8)
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL | //设置突发类型:连续(可以是连续/交错)
SDRAM_MODEREG_CAS_LATENCY_2 | //设置CAS值:2(可以是2/3)
SDRAM_MODEREG_OPERATING_MODE_STANDARD | //设置操作模式:0,标准模式
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE; //设置突发写模式:1,单点访问
SDRAM_Send_Cmd(0,FMC_SDRAM_CMD_LOAD_MODE,1,temp); //设置SDRAM的模式寄存器
//刷新频率计数器(以SDCLK频率计数),计算方法:
//COUNT=SDRAM刷新周期/行数-20=SDRAM刷新周期(us)*SDCLK频率(Mhz)/行数
//我们使用的SDRAM刷新周期为64ms,SDCLK=200/2=100Mhz,行数为8192(2^13).
//所以,COUNT=64*1000*100/8192-20=677
HAL_SDRAM_ProgramRefreshRate(hsdram,677);
}
测试函数
#define Bank5_SDRAM_ADDR ((uint32_t)(0XC0000000)) //SDRAM开始地址
u16 testsram[250000] __attribute__((at(0XC0000000)));//测试用数组
//SDRAM内存测试
for(cnt=0;cnt<250000;cnt++)
{
testsram[cnt]=cnt;
}
for(ts=0;ts<250000;ts++)
{
printf("testsram[%d]:%d\r\n",cnt,testsram[cnt]);
}
输出结果
将存储在sdram中的数组的数据打印出来,我们可以将数据通过__attribute__定义在sdram里,这就是sdram的用法。
参考例程
我的码云地址:cubemx配置sdram例程