完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
使用ST的HAL库进行开发,SDRAM使用的是W9825G6KH-6。
W9825G6KH-6共有4个Bank,13位行地址,9位列地址,位宽是16位, 所以芯片的容量是:4x8192x512x16=256Mbits=32MBytes。 W9825G6KH-6的原理图如下: FMC_D0~15:16位数据线; FMC_A0~12:13位地址线,行地址与列地址是公用的,作为行地址时使用了0~12位,作为列地址时使用了0~8位; FMC_SDNWE:低电平时写,高电平时读; FMC_SDNCAS:列地址选通信号,低电平有效; FMC_SDNRAS:行地址选通信号,低电平有效; FMC_SDNE0:片选信号,低电平有效; FMC_BA0~1:Bank选择信号; FMC_SDCKE0:时钟使能信号; FMC_SDCLK:时钟信号; FMC_NBL0~1:写访问的输出字节屏蔽。 STM32F429自带FMC外设,可以对多种外部存储器进行控制,存储区域对应如下: 我们使用的是Bank5,也就是SDRAM Bank1。 我们要做的就是对SDRAM进行初始化配置,初始化成功后即可对指定的内存进行访问,单片机和外部SDRAM之间的读写时序 是由外设自动产生的,不需要程序进行控制,非常方便。 STM32F4xx参考手册中对SDRAM的初始化过程如下: 使用STM32CubeMx生成FMC的初始化代码,如下: void MX_FMC_Init(void) { FMC_SDRAM_TimingTypeDef SdramTiming; /** Perform the SDRAM1 memory initialization sequence */ hsdram1.Instance = FMC_SDRAM_DEVICE; /* hsdram1.Init */ hsdram1.Init.SDBank = FMC_SDRAM_BANK1; //使用SDRAM Bank1 hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9; //列宽度9位 hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13; //行宽度13位 hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16; //数据总线为16位 hsdram1.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4; //SDRAM内部Bank数为4个 hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_3; //CAS为3,表示发送完读时序后延迟3个时钟周期返回数据 hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE; //忽略写保护 hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2; //SDRAM时钟SDCLK = HCLK/2 = 180MHz / 2 = 90MHz hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_ENABLE; //失能突然读模式 hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_1; //读通道延时1个时钟周期,在CAS延时后延时读取数据的时钟个数 /* SdramTiming */ SdramTiming.LoadToActiveDelay = 2; //TMRD/TRSC,2个时钟周期 SdramTiming.ExitSelfRefreshDelay = 8; //TXSR,8个时钟周期 SdramTiming.SelfRefreshTime = 6; //TRAS,6个时钟周期 SdramTiming.RowCycleDelay = 6; //TRC,6个时钟周期 SdramTiming.WriteRecoveryTime = 4; //TWR,4个时钟周期 SdramTiming.RPDelay = 2; //TRP,2个时钟周期 SdramTiming.RCDDelay = 2; //TRCD,2个时钟周期 if (HAL_SDRAM_Init(&hsdram1, &SdramTiming) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } } 上述FMC的初始化代码完成了SDRAM初始化中的1、2两个步骤; 接下来添加SDRAM初始化中的步骤3~8: uint8_t SDRAM_SendCommand(uint32_t CommandMode, uint32_t Bank, uint32_t RefreshNum, uint32_t RegVal) { uint32_t CommandTarget; FMC_SDRAM_CommandTypeDef Command; if(Bank == 1) CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1; else if(Bank == 2) CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2; Command.CommandMode = CommandMode; Command.CommandTarget = CommandTarget; Command.AutoRefreshNumber = RefreshNum; Command.ModeRegisterDefinition = RegVal; if(HAL_SDRAM_SendCommand(&hsdram1, &Command, 0x1000) == HAL_OK) return 1; else return 0; } void SDRAM_Init(void) { uint32_t temp; SDRAM_SendCommand(FMC_SDRAM_CMD_CLK_ENABLE, 1, 1, 0); //步骤3:使能时钟信号,SDCKE0 = 1 Delay_us(500); //步骤4:至少延时200us SDRAM_SendCommand(FMC_SDRAM_CMD_PALL, 1, 1, 0); //步骤5:发送全部预充电命令 SDRAM_SendCommand(FMC_SDRAM_CMD_AUTOREFRESH_MODE, 1, 8, 0); //步骤6:设置自动刷新次数 temp = SDRAM_MODEREG_BURST_LENGTH_1 | //设置突发长度:1 SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL | //设置突发类型:连续 SDRAM_MODEREG_CAS_LATENCY_3 | //设置CAS值:3 SDRAM_MODEREG_OPERATING_MODE_STANDARD | //设置操作模式:标准 SDRAM_MODEREG_WRITEBURST_MODE_SINGLE; //设置突发写模式:单点访问 SDRAM_SendCommand(FMC_SDRAM_CMD_LOAD_MODE, 1, 1, temp); //步骤7:装载模式寄存器的值 //SDRAM刷新周期是64ms,行数是8192行,时钟频率是180MHz/2=90MHz //所有COUNT = (64ms/8192)/(1/90us)-20 = 64000*90/8192-20 = 683 HAL_SDRAM_ProgramRefreshRate(&hsdram1, 683); //步骤8:设置刷新速率 } 函数SDRAM_SendCommand()用来发送命令,内部调用了HAL的库函数HAL_SDRAM_SendCommand()发送配置命令; 函数SDRAM_Init()完成了SDRAM初始化中的步骤3~8。 至此,我们就完成了对SDRAM的初始化操作,此时外部SDRAM已经被映射到了相应的内存地址;需要注意的是, SDRAM Bank1的地址是从0xC0000000~0xCFFFFFFF,SDRAM Bank2的地址是从0xD0000000~0xDFFFFFFF, 我们使用的是SDRAM Bank1,并且外部SDRAM的大小是32M字节,所以对应的内存地址范围是0xC0000000~0xC1FFFFFF。 接下来就测试一下SDRAM的读写: #define SDRAM_BANK1_BASE_ADDRESS 0xC0000000 //SDRAM Bank1起始地址 #define SDRAM_HALF_WORD_SIZE 0x1000000 //定义16M个的16bits数据,共32M字节 __no_init uint16_t uhSdramArray[SDRAM_HALF_WORD_SIZE] @SDRAM_BANK1_BASE_ADDRESS; //强制定义数组在SDRAM的内存中 void SDRAM_Test(void) { uint32_t i; for(i = 0; i 《 SDRAM_HALF_WORD_SIZE; i++) { uhSdramArray[i] = i; //对整个数组进行赋值 } for(i = 0; i 《 SDRAM_HALF_WORD_SIZE; i += 4096) { printf(“uhSdramArray[%d] = %drn”, i, uhSdramArray[i]); //对数组中的数据间隔4096个进行串口打印 } } 串口打印结果如下,数据太多,没有全部显示, SDRAM测试结束。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1771 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1619 浏览 1 评论
1070 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
724 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1673 浏览 2 评论
1936浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
729浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
569浏览 3评论
594浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
552浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 21:55 , Processed in 0.757585 second(s), Total 46, Slave 39 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号