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;
相关推荐
星辰pid6 小时前
STM32控制四自由度机械臂(SG90舵机)(硬件篇)(简单易复刻)
stm32·单片机·嵌入式硬件·机械臂
威桑8 小时前
STM32 专有名词缩写整合
stm32·单片机·嵌入式硬件
星源~8 小时前
tree 命令集成到 Git Bash:可视化目录结构的指南
git·单片机·物联网·嵌入式·项目开发
SKYDROID云卓小助手9 小时前
无人设备遥控器之自动调整编码技术篇
人工智能·嵌入式硬件·算法·自动化·信号处理
所念皆星海9119 小时前
图灵完备之路(数电学习三分钟)----数据选择器与总线
嵌入式硬件·通信·数电
智者知已应修善业11 小时前
【51单片机节日彩灯控制器设计】2022-6-11
c语言·经验分享·笔记·单片机·嵌入式硬件·51单片机
开-悟11 小时前
嵌入式编程-使用AI查找BUG的启发
c语言·人工智能·嵌入式硬件·bug
Wangshanjie_9813 小时前
【STM32】-串口通讯
stm32
许白掰13 小时前
【stm32】HAL库开发——CubeMX配置RTC,单片机工作模式和看门狗
stm32·单片机·嵌入式硬件·学习·实时音视频
DIY机器人工房14 小时前
0.96寸OLED显示屏 江协科技学习笔记(36个知识点)
笔记·科技·stm32·单片机·嵌入式硬件·学习·江协科技