STM32F429IGT6驱动FMC_SDRAM——W9825G6KH-6
参考文档:
https://zhuanlan.zhihu.com/p/657819569
https://blog.csdn.net/weixin_41613969/article/details/126822480
https://blog.csdn.net/m0_69169562/article/details/143217380
https://blog.csdn.net/qq_42039294/article/details/112221396
https://blog.csdn.net/qq_45467083/article/details/109425825
https://blog.51cto.com/u_15262460/3243123
https://blog.51cto.com/u_15830484/5761618
https://blog.csdn.net/Simon223/article/details/107819310
https://blog.csdn.net/Ningjianwen/article/details/90940570
https://blog.csdn.net/chen18221987993/article/details/128970443
https://www.bilibili.com/video/BV13a411c7UK/?vd_source=2a185775b9481ebf3be36db7d3ece99a
一、配置STM32CUBEMX
配置信息安装芯片要求配置,这里使用的是W9825G6KH-6,配置在SDRAM1,起始地址为0xC0000000。


按照下列配置,配置相关数据:


二、初始化函数
sdram_fmc.h :
#ifndef __SDRAM_FMC_H__
#define __SDRAM_FMC_H__
#include "main.h"
#define EXT_SDRAM_ADDR ((uint32_t)0xC0000000) // BANK1 0XC000 0000 BANK2 0XD000 0000
#define EXT_SDRAM_SIZE (32 * 1024 * 1024) // 内存大小 32MB = 256Mbit
#define SDRAM_TEST_SIZE (4 * 16 * 1024) // 单次读写间隔
#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)
void SDRAM_Init(void);
void fsmc_sdram_test(void);
void sdram_test(void);
#endif
sdram_fmc.c :
#include "sdram_fmc.h"
#include "fmc.h"
#include "usart.h"
static int 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;
}
return 0;
}
void SDRAM_Init(void)
{
uint32_t temp;
/* 1. 时钟使能命令 */
SDRAM_SendCommand(FMC_SDRAM_CMD_CLK_ENABLE, 1, 1, 0);
/* 2. 延时,至少100us */
HAL_Delay(1);
/* 3. SDRAM全部预充电命令 */
SDRAM_SendCommand(FMC_SDRAM_CMD_PALL, 1, 1, 0);
/* 4. 自动刷新命令 */
SDRAM_SendCommand(FMC_SDRAM_CMD_AUTOREFRESH_MODE, 1, 8, 0);
/* 5. 配置SDRAM模式寄存器 */
temp = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1 | //设置突发长度:1
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL | //设置突发类型:连续
SDRAM_MODEREG_CAS_LATENCY_3 | //设置CL值:3
SDRAM_MODEREG_OPERATING_MODE_STANDARD | //设置操作模式:标准
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE; //设置突发写模式:单点访问
SDRAM_SendCommand(FMC_SDRAM_CMD_LOAD_MODE, 1, 1, temp);
/* 6. 设置自刷新频率 */
/*
SDRAM refresh period / Number of rows)*SDRAM时钟速度 – 20
= 64000(64 ms) / 2^13 *84MHz - 20
*/
HAL_SDRAM_ProgramRefreshRate(&hsdram1, 636);
}
//uint16_t testsdram[250000] __attribute__((at(0XC0000000))); /* 测试用数组 */
//SDRAM内存测试
void fsmc_sdram_test(void)
{
__IO uint32_t i=0;
__IO uint32_t temp=0;
__IO uint32_t sval=0;//在地址0读到的数据
//每隔16K字节,写入一个数据,总共写入2048个数据,刚好是32M字节
for(i=0; i<EXT_SDRAM_SIZE; i+=SDRAM_TEST_SIZE)
{
HAL_SDRAM_Write_32b(&hsdram1, (uint32_t *)(EXT_SDRAM_ADDR+i), (uint32_t *)&temp, 1);
// *(__IO uint32_t *)(EXT_SDRAM_ADDR+i) = temp;
temp++;
}
printf("write over temp:%d \r\n", temp);
//依次读出之前写入的数据,进行校验
for(i=0; i<EXT_SDRAM_SIZE; i+=SDRAM_TEST_SIZE)
{
HAL_SDRAM_Read_32b(&hsdram1, (uint32_t *)(EXT_SDRAM_ADDR+i), (uint32_t *)&temp, 1);
printf("[%d] addr:%04x temp:%d \r\n",i/(SDRAM_TEST_SIZE) ,EXT_SDRAM_ADDR+i, temp);
}
}
注:
绘制PCB,sdram的布线需要考虑等长和阻抗匹配,随便连接的导线可能导致数据传输错乱。
更多推荐
所有评论(0)