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;
相关推荐
金戈鐡馬15 分钟前
定时器+中断优化单总线通信
stm32·单片机·嵌入式硬件
cici1587419 分钟前
STM32 + VS1003/VS1053 MP3播放器SD卡读取程序
stm32·单片机·嵌入式硬件
念一不念二1 小时前
[SSD]SSD主控
嵌入式硬件
xiangw@GZ1 小时前
DDR3 颗粒信号定义解析
单片机·嵌入式硬件
小+不通文墨1 小时前
在树莓派中部署emqx
经验分享·笔记·单片机·学习
Deitymoon1 小时前
STM32——oled显示字符串和数字
stm32·单片机·嵌入式硬件
深圳市晨芯阳科技有限公司2 小时前
带延时功能的电压检测系列晨芯阳HC809
单片机·嵌入式硬件·电源芯片·深圳市晨芯阳科技有限公司
xiangw@GZ2 小时前
DDR2 / DDR3 / DDR4 颗粒信号差异对照表
单片机·嵌入式硬件
科芯创展2 小时前
1A,60VIN,1MHz,XZ4116,降压恒流LED驱动芯片 输入电压:5V-60V
stm32·单片机·嵌入式硬件
振浩微433射频芯片3 小时前
工业环境下的“硬核”选择:如何科学评估国产433芯片的可靠性?
网络·人工智能·科技·单片机·物联网·学习