STM32CUBEMX安富莱STM32-V6开发板使用FMC驱动SDRAM芯片MT48LC4M32B2TG

文章的目的是快速使用SDRAM芯片,没有详细讲解原理。

1、环境:

单片机:STM32F429VIT6

CUBE版本:STM32CUBMX 6.12.1

编译:KEIL MDK

硬件:安富莱STM32-V6开发板

SDRAM芯片:MT48LC4M32B2TG

2、配置步骤

1、系统时钟,我的开发版外部8M晶振有问题了,所以用的是内部16M。主要AHB的时钟频率,因为SDRAM芯片要根据他来计算参数。

2、FMC配置

参数按上面配置,上面的参数具体是根据MT48LC4M32B2TG的规格书与AHB时钟频率计算所得,具体详情请搜索。

3、注意

注意:配置玩FMC的参数后,需要根据硬件实际连接情况,调整引脚配置,安富莱的硬件引脚与FMC的默认引脚有些许变动,需要调整。

引脚使用得比较多,要仔细检查

可以参考下面的使用情况,在cube上引脚重新选择一下即可。

c 复制代码
	/* GPIOD */
	GPIO_Init_Structure.Pin  = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_8| GPIO_PIN_9 | GPIO_PIN_10 |\
							   GPIO_PIN_14 | GPIO_PIN_15;
	HAL_GPIO_Init(GPIOD, &GPIO_Init_Structure);

	/* GPIOE */  
	GPIO_Init_Structure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_7| GPIO_PIN_8 | GPIO_PIN_9 |\
							  GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 |\
							  GPIO_PIN_15;	  
	HAL_GPIO_Init(GPIOE, &GPIO_Init_Structure);

	/* GPIOF */  
	GPIO_Init_Structure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2| GPIO_PIN_3 | GPIO_PIN_4 |\
							  GPIO_PIN_5 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 |\
							  GPIO_PIN_15;
	HAL_GPIO_Init(GPIOF, &GPIO_Init_Structure);

	/* GPIOG */  
	GPIO_Init_Structure.Pin = GPIO_PIN_0 | GPIO_PIN_1 |  
							  GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_15;
	HAL_GPIO_Init(GPIOG, &GPIO_Init_Structure);

	/* GPIOH */  
	GPIO_Init_Structure.Pin = GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_5 | GPIO_PIN_8 | GPIO_PIN_9 |\
							  GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 |\
							  GPIO_PIN_15;	
	HAL_GPIO_Init(GPIOH, &GPIO_Init_Structure); 

	/* GPIOI */  
	GPIO_Init_Structure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 |\
							  GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_9 | GPIO_PIN_10;
	HAL_GPIO_Init(GPIOI, &GPIO_Init_Structure);  

4、驱动编写及使用

1、头文件

上面的配置完成后,可以生成工程文件,然后就开始编写SDRAM的驱动程序。

c 复制代码
/***
* SDRAM型号MT48LC4M32B2TG-7, 32位带宽, 容量16MB, 7ns速度(143MHz)。
* 外部SDRAM使用方法
* 绝对定位方式访问 SDRAM,这种方式必须定义成全局变量 
	1.直接定义变量,分配到外部EXT_SDRAM_ADDR
		uint8_t testValue __attribute__((at(EXT_SDRAM_ADDR)));
	2.函数直接操作引用
		testValue = 0xaa;
**/

#ifndef _SDRAM_FMC_DRV_H_
#define _SDRAM_FMC_DRV_H_

#include "fmc.h"

#define EXT_SDRAM_ADDR  	((uint32_t)0xC0000000)
#define EXT_SDRAM_SIZE		(16 * 1024 * 1024)

void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Command);

#endif /* _SDRAM_FMC_DRV_H_ */
//

2、C文件

c 复制代码
#include "bsp_sdram.h"

/* #define SDRAM_MEMORY_WIDTH            FMC_SDRAM_MEM_BUS_WIDTH_8  */
/* #define SDRAM_MEMORY_WIDTH            FMC_SDRAM_MEM_BUS_WIDTH_16 */
//#define SDRAM_MEMORY_WIDTH               FMC_SDRAM_MEM_BUS_WIDTH_32

//#define SDCLOCK_PERIOD                   FMC_SDRAM_CLOCK_PERIOD_2
/* #define SDCLOCK_PERIOD                FMC_SDRAM_CLOCK_PERIOD_3 */

#define SDRAM_TIMEOUT                    ((uint32_t)0xFFFF)
#define REFRESH_COUNT                    ((uint32_t)1293)    /* SDRAM自刷新计数 */  

/* SDRAM的参数配置 */
#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)


/*
*********************************************************************************************************
*	函 数 名: SDRAM初始化序列
*	功能说明: 完成SDRAM序列初始化
*	形    参: hsdram: SDRAM句柄
*			  Command: 命令结构体指针
*	返 回 值: None
*********************************************************************************************************
*/
void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Command)
{
	__IO uint32_t tmpmrd =0;
 
    /*##-1- 时钟使能命令 ##################################################*/
	Command->CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
	Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;;
	Command->AutoRefreshNumber = 1;
	Command->ModeRegisterDefinition = 0;

	/* 发送命令 */
	HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);

    /*##-2- 插入延迟,至少100us ##################################################*/
	HAL_Delay(1);

    /*##-3- 整个SDRAM预充电命令,PALL(precharge all) #############################*/
	Command->CommandMode = FMC_SDRAM_CMD_PALL;
	Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
	Command->AutoRefreshNumber = 1;
	Command->ModeRegisterDefinition = 0;

	/* 发送命令 */
	HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);

    /*##-4- 自动刷新命令 #######################################################*/
	Command->CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
	Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
	Command->AutoRefreshNumber = 8;
	Command->ModeRegisterDefinition = 0;

	/* 发送命令 */
	HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);

    /*##-5- 配置SDRAM模式寄存器 ###############################################*/
	tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1          |
					 SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   |
					 SDRAM_MODEREG_CAS_LATENCY_3           |
					 SDRAM_MODEREG_OPERATING_MODE_STANDARD |
					 SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;

	Command->CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
	Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
	Command->AutoRefreshNumber = 1;
	Command->ModeRegisterDefinition = tmpmrd;

	/* 发送命令 */
	HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);

    /*##-6- 设置自刷新率 ####################################################*/
    /*
        SDRAM refresh period / Number of rows)*SDRAM时钟速度 -- 20
      = 64ms / 4096 *84MHz - 20
      = 1292.5 取值1293
    */
	HAL_SDRAM_ProgramRefreshRate(hsdram, REFRESH_COUNT); 
}

3、初始化

添加上面的文件到工程目录,打开"fmc.c"文件,找到"void MX_FMC_Init(void)"函数,按如下操作添加内容:

4、编译即可

debug查看内容。注意:SDRAM按如上配置的话,映射的起始地址为:0XC0000000。可以修改、使用了。

  • 外部SDRAM使用方法
  • 绝对定位方式访问 SDRAM,这种方式必须定义成全局变量
    1.直接定义变量,分配到外部EXT_SDRAM_ADDR
    uint8_t testValue attribute ((at(EXT_SDRAM_ADDR)));
    2.函数直接操作引用
    testValue = 0xaa;
相关推荐
MARIN_shen36 分钟前
Marin说PCB之POC电路layout设计仿真案例---06
网络·单片机·嵌入式硬件·硬件工程·pcb工艺
Asa3191 小时前
STM32-按键扫描配置
stm32·单片机·嵌入式硬件
南城花随雪。1 小时前
单片机:实现驱动超声波(附带源码)
单片机·嵌入式硬件
嵌入式科普1 小时前
十三、从0开始卷出一个新项目之瑞萨RZN2L串口DMA接收不定长
c语言·stm32·瑞萨·e2studio·rzn2l
yutian060610 小时前
Keil MDK下载程序后MCU自动重启设置
单片机·嵌入式硬件·keil
析木不会编程13 小时前
【小白51单片机专用教程】protues仿真独立按键控制LED
单片机·嵌入式硬件·51单片机
枯无穷肉17 小时前
stm32制作CAN适配器4--WinUsb的使用
stm32·单片机·嵌入式硬件
不过四级不改名67717 小时前
基于HAL库的stm32的can收发实验
stm32·单片机·嵌入式硬件
嵌入式科普17 小时前
十一、从0开始卷出一个新项目之瑞萨RA6M5串口DTC接收不定长
c语言·stm32·cubeide·e2studio·ra6m5·dma接收不定长
嵌入式大圣17 小时前
单片机UDP数据透传
单片机·嵌入式硬件·udp