eric大大好,小弟目前有一个疑问,想请教您:
虽然我没有买过您的开发板(因为之前入门的时候用的是正点原子的。。),但是我觉得您很专注于技术的研讨,十分想和您请教,
我自己做了一个PCB,用的F767IGT6,176管脚,因为项目中需要大容量的SDRAM,因此,我设计挂载了两片SDRAM,管脚连接如下:
第一个 W9825G6DH 与 第二个 W9825G6DH 的 地址线A0-A12 ,BA0-BA1,数据线D0-D15 , 时钟 SDCLK, NBL0 NBL1 , SDNWE, SDNCAS, SDNRAS, 全部共用。
第一个 W9825G6DH 与 第二个 W9825G6DH 的 SDNE 与 SDCKE 分别独立连接 (第一个SDRAM 用 SDNE0 SDCKE0,第二个SDRAM 用 SDNE1 SDCKE1), NE0 和NE1 分别独立连接上拉电阻10K。
对应的,SDNE0 这个 SDRAM 地址是 #define Bank5_SDRAM_ADDR ((u32)(0XC0000000))
SDNE1 这个 SDRAM 地址是 #define Bank6_SDRAM_ADDR ((u32)(0XD0000000))
一下是我的初始化过程:
void SDRAM_Init(void)
{
u32 sdctrlreg=0,sdtimereg=0;
u16 mregval=0;
RCC->AHB3ENR|=1<<0; //使能FMC时钟
RCC->AHB1ENR|=0X1F<<2; //使能PC/PD/PE/PF/PG时钟
RCC->AHB1ENR|=1<<7; //使能PORTH时钟
GPIO_Set(GPIOH,PIN6|PIN7,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU); // 添加 SDNE1 和 SDCKE1管脚
GPIO_Set(GPIOC,PIN0|PIN2|PIN3,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU); //PC0/2/3
GPIO_Set(GPIOD,3<<0|7<<8|3<<14,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU); //PD0/1/8/9/10/14/15
GPIO_Set(GPIOE,3<<0|0X1FF<<7,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU); //PE0/1/7~15
GPIO_Set(GPIOF,0X3F<<0|0X1F<<11,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU); //PG0~5/11~15
GPIO_Set(GPIOG,7<<0|3<<4|PIN8|PIN15,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU); //PF0~2/4/5/8/15
GPIO_AF_Set(GPIOH,6,12);
GPIO_AF_Set(GPIOH,7,12); // 添加 SDNE1 和 SDCKE1管脚
GPIO_AF_Set(GPIOC,0,12); //PC0,AF12
GPIO_AF_Set(GPIOC,2,12); //PC2,AF12
GPIO_AF_Set(GPIOC,3,12); //PC3,AF12
GPIO_AF_Set(GPIOD,0,12); //PD0,AF12
GPIO_AF_Set(GPIOD,1,12); //PD1,AF12
GPIO_AF_Set(GPIOD,8,12); //PD8,AF12
GPIO_AF_Set(GPIOD,9,12); //PD9,AF12
GPIO_AF_Set(GPIOD,10,12); //PD10,AF12
GPIO_AF_Set(GPIOD,14,12); //PD14,AF12
GPIO_AF_Set(GPIOD,15,12); //PD15,AF12
GPIO_AF_Set(GPIOE,0,12); //PE0,AF12
GPIO_AF_Set(GPIOE,1,12); //PE1,AF12
GPIO_AF_Set(GPIOE,7,12); //PE7,AF12
GPIO_AF_Set(GPIOE,8,12); //PE8,AF12
GPIO_AF_Set(GPIOE,9,12); //PE9,AF12
GPIO_AF_Set(GPIOE,10,12); //PE10,AF12
GPIO_AF_Set(GPIOE,11,12); //PE11,AF12
GPIO_AF_Set(GPIOE,12,12); //PE12,AF12
GPIO_AF_Set(GPIOE,13,12); //PE13,AF12
GPIO_AF_Set(GPIOE,14,12); //PE14,AF12
GPIO_AF_Set(GPIOE,15,12); //PE15,AF12
GPIO_AF_Set(GPIOF,0,12); //PF0,AF12
GPIO_AF_Set(GPIOF,1,12); //PF1,AF12
GPIO_AF_Set(GPIOF,2,12); //PF2,AF12
GPIO_AF_Set(GPIOF,3,12); //PF3,AF12
GPIO_AF_Set(GPIOF,4,12); //PF4,AF12
GPIO_AF_Set(GPIOF,5,12); //PF5,AF12
GPIO_AF_Set(GPIOF,11,12); //PF11,AF12
GPIO_AF_Set(GPIOF,12,12); //PF12,AF12
GPIO_AF_Set(GPIOF,13,12); //PF13,AF12
GPIO_AF_Set(GPIOF,14,12); //PF14,AF12
GPIO_AF_Set(GPIOF,15,12); //PF15,AF12
GPIO_AF_Set(GPIOG,0,12); //PG0,AF12
GPIO_AF_Set(GPIOG,1,12); //PG1,AF12
GPIO_AF_Set(GPIOG,2,12); //PG2,AF12
GPIO_AF_Set(GPIOG,4,12); //PG4,AF12
GPIO_AF_Set(GPIOG,5,12); //PG5,AF12
GPIO_AF_Set(GPIOG,8,12); //PG8,AF12
GPIO_AF_Set(GPIOG,15,12); //PG15,AF12
sdctrlreg|=1<<0; //9位列地址 1
sdctrlreg|=2<<2; //13位行地址 2
sdctrlreg|=1<<4; //16位数据位宽 1
sdctrlreg|=1<<6; //4个内部存区(4 BANKS) 1
sdctrlreg|=3<<7; //3个CAS延迟 3
sdctrlreg|=0<<9; //允许写访问 0
sdctrlreg|=2<<10; //SDRAM时钟=HCLK/2=216M/2=108M=9.3ns 2 -- 18.6ns
sdctrlreg|=1<<12; //使能突发访问 1
sdctrlreg|=0<<13; //读通道延迟0个HCLK 0
FMC_Bank5_6->SDCR[0]=sdctrlreg; //设置FMC BANK5 SDRAM控制寄存器(BANK5和6用于管理SDRAM).
FMC_Bank5_6->SDCR[1]=sdctrlreg; //设置FMC BANK5 SDRAM控制寄存器(BANK5和6用于管理SDRAM).
sdtimereg|=5<<0; //加载模式寄存器到激活时间的延迟为2个时钟周期 1
sdtimereg|=12<<4; //退出自刷新延迟为8个时钟周期 7 TXSR
sdtimereg|=11<<8; //自刷新时间为7个时钟周期 6 TRAS
sdtimereg|=11<<12; //行循环延迟为7个时钟周期 6 TRC
sdtimereg|=6<<16; //恢复延迟为2个时钟周期 1 TWR
sdtimereg|=6<<20; //行预充电延迟为2个时钟周期 1 TRP
sdtimereg|=6<<24; //行到列延迟为2个时钟周期 1 TRCD
FMC_Bank5_6->SDTR[0]=sdtimereg; //设置FMC BANK5 SDRAM时序寄存器
FMC_Bank5_6->SDTR[1]=sdtimereg; //设置FMC BANK5 SDRAM时序寄存器
SDRAM_Send_Cmd(0,1,0,0); //时钟配置使能
SDRAM_Send_Cmd(1,1,0,0); //时钟配置使能
delay_us(500); //至少延迟200us.
SDRAM_Send_Cmd(0,2,0,0); //对所有存储区预充电
SDRAM_Send_Cmd(1,2,0,0); //对所有存储区预充电
SDRAM_Send_Cmd(0,3,8,0); //设置自刷新次数
SDRAM_Send_Cmd(1,3,8,0); //设置自刷新次数
mregval|=3<<0; //设置突发长度:8(可以是1/2/4/8)
mregval|=0<<3; //设置突发类型:连续(可以是连续/交错)
mregval|=3<<4; //设置CAS值:3(可以是2/3)
mregval|=0<<7; //设置操作模式:0,标准模式
mregval|=1<<9; //设置突发写模式:1,单点访问
SDRAM_Send_Cmd(0,4,0,mregval); //设置SDRAM的模式寄存器
SDRAM_Send_Cmd(1,4,0,mregval); //设置SDRAM的模式寄存器
//刷新频率计数器(以SDCLK频率计数),计算方法:
//COUNT=SDRAM刷新周期/行数-20=SDRAM刷新周期(us)*SDCLK频率(Mhz)/行数
//我们使用的SDRAM刷新周期为64ms,SDCLK=216/2=108Mhz,行数为8192(2^13).
//所以,COUNT=64*1000*108/8192-20=824
FMC_Bank5_6->SDRTR=824<<1; //设置刷新频率计数器
}
//向SDRAM发送命令
//bankx:0,向BANK5上面的SDRAM发送指令
// 1,向BANK6上面的SDRAM发送指令
//cmd:指令(0,正常模式/1,时钟配置使能/2,预充电所有存储区/3,自动刷新/4,加载模式寄存器/5,自刷新/6,掉电)
//refresh:自刷新次数(cmd=3时有效)
//regval:模式寄存器的定义
//返回值:0,正常;1,失败.
u8 SDRAM_Send_Cmd(u8 bankx,u8 cmd,u8 refresh,u16 regval)
{
u32 retry=0;
u32 tempreg=0;
tempreg|=cmd<<0; //设置指令
tempreg|=1<<(4-bankx); //设置发送指令到bank5还是6
tempreg|=refresh<<5; //设置自刷新次数
tempreg|=regval<<9; //设置模式寄存器的值
FMC_Bank5_6->SDCMR=tempreg; //配置寄存器
while((FMC_Bank5_6->SDSR&(1<<5)))//等待指令发送完成
{
retry++;
if(retry>0X1FFFFF)return 1;
}
return 0;
}
上面的代码中,绿色部分是对 BANK5 SDRAM进行设置, 红色部分是对BANK6 SDRAM进行设置。
现在测试的结果如下:
1. PCB上焊接有两片SDRAM
2. 若代码中对 BANK5进行设置, 注释掉BANK6代码(保留绿色,注释掉红色)。 通过 FOR循环 对 *(vu8*)(Bank5_SDRAM_ADDR+i) 所有地址进行读写操作 均没问题,也挂载了RGB屏进行 测试。
3. 若代码中对 BANK5和BANK6进行设置(绿色和红色代码共存),通过 FOR循环 对 *(vu8*)(Bank5_SDRAM_ADDR+i) 测试没有问题,但是对 *(vu8*)(Bank6_SDRAM_ADDR+i) 测试 有问题,无法正常工作。
4. 若代码中对 BANK6进行设置, 注释掉BANK5代码(注释掉绿色,保留红色)。 *(vu8*)(Bank6_SDRAM_ADDR+i) 测试 有问题,无法正常工作。
请问ERIC大大,同时挂两片SDRAM,是不是有一些特殊地方的设置? 电路焊接基本排除了,芯片也是同一批次买的。
感谢您的指导! |