023 - STM32学习笔记 - 扩展外部SDRAM(二) - 扩展外部SDRAM实验

023- STM32学习笔记 - 扩展外部SDRAM(一) - 扩展外部SDRAM实验

本节内容中要配置的引脚很多,如果你用的开发板跟我的不一样,请详细参照STM32规格书中说明对相关GPIO引脚进行配置。

先提前对本届内容的变成步骤进行总结如下:

  1. 初始化通讯使用的目标引脚及端口时钟;(再次强调,只要使用外设,一定要看时钟时候配置正确并开启!)
  2. 是能FMC外设时钟;(再再次强调,只要使用外设,一定要看时钟时候配置正确并开启!)
  3. 配置FMC SDRAM的时序和工作模式;
  4. 根据SDRAM的初始化流程编写初始化函数;
  5. 访问外部SDRAM存储器;
  6. 编写测试程序,校验读写的数据。

OK,参照如上步骤,实战之前先将我用的F429开发板中SDRAM部分贴出来。

在这里插入图片描述

一、相关GPIO宏定义

这次使用到的GPIO相当多,这里我们把FMC SDRAM相关的GPIO配置都宏定义到“bsp_sdram.h”中,相关的配置步骤参考之前的工程配置。这里我把我配置好的贴出来,如果我们使用的开发板不一致,请参考自己开发板的硬件原理图

/* A行列地址信号线 */
/* A0 PF0 */
#define FMC_A0_GPIO_PORT        GPIOF
#define FMC_A0_GPIO_CLK         RCC_AHB1Periph_GPIOF
#define FMC_A0_GPIO_PIN         GPIO_Pin_0
#define FMC_A0_PINSOURCE        GPIO_PinSource0
#define FMC_A0_AF               GPIO_AF_FMC/* A1 PF1 */
#define FMC_A1_GPIO_PORT        GPIOF
#define FMC_A1_GPIO_CLK         RCC_AHB1Periph_GPIOF
#define FMC_A1_GPIO_PIN         GPIO_Pin_1
#define FMC_A1_PINSOURCE        GPIO_PinSource1
#define FMC_A1_AF               GPIO_AF_FMC/* A2 PF2 */
#define FMC_A2_GPIO_PORT        GPIOF
#define FMC_A2_GPIO_CLK         RCC_AHB1Periph_GPIOF
#define FMC_A2_GPIO_PIN         GPIO_Pin_2
#define FMC_A2_PINSOURCE        GPIO_PinSource2
#define FMC_A2_AF               GPIO_AF_FMC/* A3 PF3 */
#define FMC_A3_GPIO_PORT        GPIOF
#define FMC_A3_GPIO_CLK         RCC_AHB1Periph_GPIOF
#define FMC_A3_GPIO_PIN         GPIO_Pin_3
#define FMC_A3_PINSOURCE        GPIO_PinSource3
#define FMC_A3_AF               GPIO_AF_FMC/* A4 PF4 */
#define FMC_A4_GPIO_PORT        GPIOF
#define FMC_A4_GPIO_CLK         RCC_AHB1Periph_GPIOF
#define FMC_A4_GPIO_PIN         GPIO_Pin_4
#define FMC_A4_PINSOURCE        GPIO_PinSource4
#define FMC_A4_AF               GPIO_AF_FMC/* A5 PF5*/
#define FMC_A5_GPIO_PORT        GPIOF
#define FMC_A5_GPIO_CLK         RCC_AHB1Periph_GPIOF
#define FMC_A5_GPIO_PIN         GPIO_Pin_5
#define FMC_A5_PINSOURCE        GPIO_PinSource5
#define FMC_A5_AF               GPIO_AF_FMC/* A6 PF12 */
#define FMC_A6_GPIO_PORT        GPIOF
#define FMC_A6_GPIO_CLK         RCC_AHB1Periph_GPIOF
#define FMC_A6_GPIO_PIN         GPIO_Pin_12
#define FMC_A6_PINSOURCE        GPIO_PinSource12
#define FMC_A6_AF               GPIO_AF_FMC/* A7 PF13 */
#define FMC_A7_GPIO_PORT        GPIOF
#define FMC_A7_GPIO_CLK         RCC_AHB1Periph_GPIOF
#define FMC_A7_GPIO_PIN         GPIO_Pin_13
#define FMC_A7_PINSOURCE        GPIO_PinSource13
#define FMC_A7_AF               GPIO_AF_FMC/* A8 PF14 */
#define FMC_A8_GPIO_PORT        GPIOF
#define FMC_A8_GPIO_CLK         RCC_AHB1Periph_GPIOF
#define FMC_A8_GPIO_PIN         GPIO_Pin_14
#define FMC_A8_PINSOURCE        GPIO_PinSource14
#define FMC_A8_AF               GPIO_AF_FMC/* A9 PF15 */
#define FMC_A9_GPIO_PORT        GPIOF
#define FMC_A9_GPIO_CLK         RCC_AHB1Periph_GPIOF
#define FMC_A9_GPIO_PIN         GPIO_Pin_15
#define FMC_A9_PINSOURCE        GPIO_PinSource15
#define FMC_A9_AF               GPIO_AF_FMC/* A10 PG0 */
#define FMC_A10_GPIO_PORT        GPIOG
#define FMC_A10_GPIO_CLK         RCC_AHB1Periph_GPIOG
#define FMC_A10_GPIO_PIN         GPIO_Pin_0
#define FMC_A10_PINSOURCE        GPIO_PinSource0
#define FMC_A10_AF               GPIO_AF_FMC/* A11 PG1 */
#define FMC_A11_GPIO_PORT        GPIOG
#define FMC_A11_GPIO_CLK         RCC_AHB1Periph_GPIOG
#define FMC_A11_GPIO_PIN         GPIO_Pin_1
#define FMC_A11_PINSOURCE        GPIO_PinSource1
#define FMC_A11_AF               GPIO_AF_FMC/*BA0 地址线 PG4*/
#define FMC_BA0_GPIO_PORT        GPIOG
#define FMC_BA0_GPIO_CLK         RCC_AHB1Periph_GPIOG
#define FMC_BA0_GPIO_PIN         GPIO_Pin_4
#define FMC_BA0_PINSOURCE        GPIO_PinSource4
#define FMC_BA0_AF               GPIO_AF_FMC/*BA1 地址线 PG5 */
#define FMC_BA1_GPIO_PORT        GPIOG
#define FMC_BA1_GPIO_CLK         RCC_AHB1Periph_GPIOG
#define FMC_BA1_GPIO_PIN         GPIO_Pin_5
#define FMC_BA1_PINSOURCE        GPIO_PinSource5
#define FMC_BA1_AF               GPIO_AF_FMC/*DQ 数据信号线*/
/*DQ0 数据线 PD14 */
#define FMC_D0_GPIO_PORT         GPIOD
#define FMC_D0_GPIO_CLK          RCC_AHB1Periph_GPIOD
#define FMC_D0_GPIO_PIN          GPIO_Pin_14
#define FMC_D0_PINSOURCE         GPIO_PinSource14
#define FMC_D0_AF                GPIO_AF_FMC/*DQ1 数据线*/
#define FMC_D1_GPIO_PORT         GPIOD
#define FMC_D1_GPIO_CLK          RCC_AHB1Periph_GPIOD
#define FMC_D1_GPIO_PIN          GPIO_Pin_15
#define FMC_D1_PINSOURCE         GPIO_PinSource15
#define FMC_D1_AF                GPIO_AF_FMC/*DQ2 数据线*/
#define FMC_D2_GPIO_PORT         GPIOD
#define FMC_D2_GPIO_CLK          RCC_AHB1Periph_GPIOD
#define FMC_D2_GPIO_PIN          GPIO_Pin_0
#define FMC_D2_PINSOURCE         GPIO_PinSource0
#define FMC_D2_AF                GPIO_AF_FMC/*DQ3 数据线*/
#define FMC_D3_GPIO_PORT         GPIOD
#define FMC_D3_GPIO_CLK          RCC_AHB1Periph_GPIOD
#define FMC_D3_GPIO_PIN          GPIO_Pin_1
#define FMC_D3_PINSOURCE         GPIO_PinSource1
#define FMC_D3_AF                GPIO_AF_FMC/*DQ4 数据线*/
#define FMC_D4_GPIO_PORT         GPIOE
#define FMC_D4_GPIO_CLK          RCC_AHB1Periph_GPIOE
#define FMC_D4_GPIO_PIN          GPIO_Pin_7
#define FMC_D4_PINSOURCE         GPIO_PinSource7
#define FMC_D4_AF                GPIO_AF_FMC/*DQ5 数据线*/
#define FMC_D5_GPIO_PORT         GPIOE
#define FMC_D5_GPIO_CLK          RCC_AHB1Periph_GPIOE
#define FMC_D5_GPIO_PIN          GPIO_Pin_8
#define FMC_D5_PINSOURCE         GPIO_PinSource8
#define FMC_D5_AF                GPIO_AF_FMC/*DQ6 数据线*/
#define FMC_D6_GPIO_PORT         GPIOE
#define FMC_D6_GPIO_CLK          RCC_AHB1Periph_GPIOE
#define FMC_D6_GPIO_PIN          GPIO_Pin_9
#define FMC_D6_PINSOURCE         GPIO_PinSource9
#define FMC_D6_AF                GPIO_AF_FMC/*DQ7 数据线*/
#define FMC_D7_GPIO_PORT         GPIOE
#define FMC_D7_GPIO_CLK          RCC_AHB1Periph_GPIOE
#define FMC_D7_GPIO_PIN          GPIO_Pin_10
#define FMC_D7_PINSOURCE         GPIO_PinSource10
#define FMC_D7_AF                GPIO_AF_FMC/*DQ8 数据线*/
#define FMC_D8_GPIO_PORT         GPIOE
#define FMC_D8_GPIO_CLK          RCC_AHB1Periph_GPIOE
#define FMC_D8_GPIO_PIN          GPIO_Pin_11
#define FMC_D8_PINSOURCE         GPIO_PinSource11
#define FMC_D8_AF                GPIO_AF_FMC/*DQ9 数据线*/
#define FMC_D9_GPIO_PORT         GPIOE
#define FMC_D9_GPIO_CLK          RCC_AHB1Periph_GPIOE
#define FMC_D9_GPIO_PIN          GPIO_Pin_12
#define FMC_D9_PINSOURCE         GPIO_PinSource12
#define FMC_D9_AF                GPIO_AF_FMC/*DQ10 数据线*/
#define FMC_D10_GPIO_PORT         GPIOE
#define FMC_D10_GPIO_CLK          RCC_AHB1Periph_GPIOE
#define FMC_D10_GPIO_PIN          GPIO_Pin_13
#define FMC_D10_PINSOURCE         GPIO_PinSource13
#define FMC_D10_AF                GPIO_AF_FMC/*DQ11 数据线*/
#define FMC_D11_GPIO_PORT         GPIOE
#define FMC_D11_GPIO_CLK          RCC_AHB1Periph_GPIOE
#define FMC_D11_GPIO_PIN          GPIO_Pin_14
#define FMC_D11_PINSOURCE         GPIO_PinSource14
#define FMC_D11_AF                GPIO_AF_FMC/*DQ12 数据线*/
#define FMC_D12_GPIO_PORT         GPIOE
#define FMC_D12_GPIO_CLK          RCC_AHB1Periph_GPIOE
#define FMC_D12_GPIO_PIN          GPIO_Pin_15
#define FMC_D12_PINSOURCE         GPIO_PinSource15
#define FMC_D12_AF                GPIO_AF_FMC/*DQ13 数据线*/
#define FMC_D13_GPIO_PORT         GPIOD
#define FMC_D13_GPIO_CLK          RCC_AHB1Periph_GPIOD
#define FMC_D13_GPIO_PIN          GPIO_Pin_8
#define FMC_D13_PINSOURCE         GPIO_PinSource8
#define FMC_D13_AF                GPIO_AF_FMC/*DQ14 数据线*/
#define FMC_D14_GPIO_PORT         GPIOD
#define FMC_D14_GPIO_CLK          RCC_AHB1Periph_GPIOD
#define FMC_D14_GPIO_PIN          GPIO_Pin_9
#define FMC_D14_PINSOURCE         GPIO_PinSource9
#define FMC_D14_AF                GPIO_AF_FMC/*DQ15 数据线*/
#define FMC_D15_GPIO_PORT         GPIOD
#define FMC_D15_GPIO_CLK          RCC_AHB1Periph_GPIOD
#define FMC_D15_GPIO_PIN          GPIO_Pin_10
#define FMC_D15_PINSOURCE         GPIO_PinSource10
#define FMC_D15_AF                GPIO_AF_FMC/*控制信号线*/
/*CS 片选*/
#define FMC_CS_GPIO_PORT          GPIOH
#define FMC_CS_GPIO_CLK           RCC_AHB1Periph_GPIOH
#define FMC_CS_GPIO_PIN           GPIO_Pin_6
#define FMC_CS_PINSOURCE          GPIO_PinSource6
#define FMC_CS_AF                 GPIO_AF_FMC/*WE 写使能*/
#define FMC_WE_GPIO_PORT          GPIOC
#define FMC_WE_GPIO_CLK           RCC_AHB1Periph_GPIOC
#define FMC_WE_GPIO_PIN           GPIO_Pin_0
#define FMC_WE_PINSOURCE          GPIO_PinSource0
#define FMC_WE_AF                 GPIO_AF_FMC/*RAS 行选通*/
#define FMC_RAS_GPIO_PORT         GPIOF
#define FMC_RAS_GPIO_CLK          RCC_AHB1Periph_GPIOF
#define FMC_RAS_GPIO_PIN          GPIO_Pin_11
#define FMC_RAS_PINSOURCE         GPIO_PinSource11
#define FMC_RAS_AF                GPIO_AF_FMC/*CAS 列选通*/
#define FMC_CAS_GPIO_PORT         GPIOG
#define FMC_CAS_GPIO_CLK          RCC_AHB1Periph_GPIOG
#define FMC_CAS_GPIO_PIN          GPIO_Pin_15
#define FMC_CAS_PINSOURCE         GPIO_PinSource15
#define FMC_CAS_AF                GPIO_AF_FMC/*CLK 同步时钟,存储区域 2*/
#define FMC_CLK_GPIO_PORT         GPIOG
#define FMC_CLK_GPIO_CLK          RCC_AHB1Periph_GPIOG
#define FMC_CLK_GPIO_PIN          GPIO_Pin_8
#define FMC_CLK_PINSOURCE         GPIO_PinSource8
#define FMC_CLK_AF                GPIO_AF_FMC/*CKE 时钟使能,存储区域 2*/
#define FMC_CKE_GPIO_PORT         GPIOH
#define FMC_CKE_GPIO_CLK          RCC_AHB1Periph_GPIOH
#define FMC_CKE_GPIO_PIN          GPIO_Pin_7
#define FMC_CKE_PINSOURCE         GPIO_PinSource7
#define FMC_CKE_AF                GPIO_AF_FMC/*DQM1 数据掩码*/
#define FMC_UDQM_GPIO_PORT        GPIOE
#define FMC_UDQM_GPIO_CLK         RCC_AHB1Periph_GPIOE
#define FMC_UDQM_GPIO_PIN         GPIO_Pin_1
#define FMC_UDQM_PINSOURCE        GPIO_PinSource1
#define FMC_UDQM_AF               GPIO_AF_FMC/*DQM0 数据掩码*/
#define FMC_LDQM_GPIO_PORT        GPIOE
#define FMC_LDQM_GPIO_CLK         RCC_AHB1Periph_GPIOE
#define FMC_LDQM_GPIO_PIN         GPIO_Pin_0
#define FMC_LDQM_PINSOURCE        GPIO_PinSource0
#define FMC_LDQM_AF               GPIO_AF_FMC

这里需要注意的是,我们在原理图上可以看到,FMC_SDCKE和FMC_SDNE我们都选择的是1,那说明SDRAM在内存中的映射为FMC_Block2,起始地址为0xD000 0000,SDRAM的大小为8M,因此结束地址为0xD080 0000。

二、FMC及SDRAM配置

1、时钟周期配置

关于时钟周期配置,可以看一下SDRAM的数据手册,输入的时钟为HCLK(180MHz)的2分频为90MHz,因此一个时钟周期为1/90MHz≈11.11ns。

a、TMRD:数据手册中参数要求为2个周期;

b、TXSR:最小时间要求为70ns,计算得为约7个周期;

c、TRAS:要求最小时间42ns,最大100000ns,计算得为最小4个周期;

d、TRC:要求最小63ns,计算得最小为6个周期;

e、TWR:CAS Latency选择为2时,周期为2;

f、TRP:要求最小为15ns,计算得为2个周期;

g、TRCD:要求最小为15ns,计算得为2个周期;

/* SDCLK: 90 Mhz (HCLK/2 :180Mhz/2) 1 个时钟周期 Tsdclk =1/90MHz=1/90000000Hz=11.11ns*/
/* TMRD: 2个时钟周期 */
FMC_SDRAMTimingInitStructure.FMC_LoadToActiveDelay = 2;
/* TXSR: min=70ns (70/11.11=6.03个周期) 即为7个周期*/
FMC_SDRAMTimingInitStructure.FMC_ExitSelfRefreshDelay = 7;
/* TRAS: min=42ns (42/11.11=3.7个周期) max=100k (ns)因此最小可配置为4个周期 */
FMC_SDRAMTimingInitStructure.FMC_SelfRefreshTime = 4;
/* TRC: min=63ns (63/11.11=5.67个周期) 即为6个周期 */
FMC_SDRAMTimingInitStructure.FMC_RowCycleDelay = 6;
/* TWR: 最小为2个周期 */
FMC_SDRAMTimingInitStructure.FMC_WriteRecoveryTime = 2;
/* TRP: 15ns (15/11.11=1.35个周期) 即为2个周期 */
FMC_SDRAMTimingInitStructure.FMC_RPDelay = 2;
/* TRCD: 15ns (15/11.11=1.35个周期) 即为2个周期 */
FMC_SDRAMTimingInitStructure.FMC_RCDDelay = 2;
2、FMC控制配置
/* FMC SDRAM 控制配置 */
/* 选择存储区域为FMC_Bank2_SDRAM */
FMC_SDRAMInitStructure.FMC_Bank = FMC_BANK_SDRAM;
/* 行地址线宽度: [7:0]共8位 */
FMC_SDRAMInitStructure.FMC_ColumnBitsNumber = FMC_ColumnBits_Number_8b;
/* 列地址线宽度: [11:0]共12位 */
FMC_SDRAMInitStructure.FMC_RowBitsNumber = FMC_RowBits_Number_12b;
/* 数据线宽度位16 */
FMC_SDRAMInitStructure.FMC_SDMemoryDataWidth = SDRAM_MEMORY_WIDTH;
/* 设置SDRAM 内部bank数量为4 */
FMC_SDRAMInitStructure.FMC_InternalBankNumber = FMC_InternalBank_Number_4;
/* CAS 潜伏期 */
FMC_SDRAMInitStructure.FMC_CASLatency = SDRAM_CAS_LATENCY;
/* 禁止写保护*/
FMC_SDRAMInitStructure.FMC_WriteProtection = FMC_Write_Protection_Disable;
/* SDCLK 时钟分频因子, SDCLK = HCLK/SDCLOCK_PERIOD*/
FMC_SDRAMInitStructure.FMC_SDClockPeriod = SDCLOCK_PERIOD;
/* 突发读模式设置*/
FMC_SDRAMInitStructure.FMC_ReadBurst = SDRAM_READBURST;
/* 读延迟配置 */
FMC_SDRAMInitStructure.FMC_ReadPipeDelay = FMC_ReadPipe_Delay_0;
/* SDRAM 时序参数 */
FMC_SDRAMInitStructure.FMC_SDRAMTimingStruct =&FMC_SDRAMTimingInitStructure;
/* 调用初始化函数,向寄存器写入配置 */
FMC_SDRAMInit(&FMC_SDRAMInitStructure);
/* 执行FMC SDRAM的初始化流程*/
SDRAM_InitSequence();				//函数在下面实现
3、初始化SDRAM
static void SDRAM_InitSequence(void)
{FMC_SDRAMCommandTypeDef FMC_SDRAMCommandStructure;uint32_t tmpr = 0;/* 配置命令:开启提供给 SDRAM 的时钟 *///下发使能 CLK 命令FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_CLK_Enabled;//设置FMC内部存储区域2FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank2;//设置FMC自动刷新次数,前面未下发自动刷新,此项任意值即可。FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 0;//此时不下发加载模式寄存器,配置为任意值即可FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;/* 检查 SDRAM 标志,等待至 SDRAM 空闲 */while (FMC_GetFlagStatus(FMC_BANK_SDRAM, FMC_FLAG_Busy) != RESET);/* 发送上述命令*/FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);/*延时 */SDRAM_delay(10);/* 配置命令:对所有的 bank 预充电 *///发送对所有Bank预充电命令FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_PALL;//设置FMC内部存储区域2FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank2;//设置FMC自动刷新次数,前面未下发自动刷新,此项任意值即可。FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 0;//此时不下发加载模式寄存器,配置为任意值即可FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;/* 检查 SDRAM 标志,等待至 SDRAM 空闲 */while (FMC_GetFlagStatus(FMC_BANK_SDRAM, FMC_FLAG_Busy) != RESET);/* 发送上述命令*/FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);/*延时 */SDRAM_delay(10);/* 配置命令:自动刷新 *///发送自动刷新命令FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_AutoRefresh;//设置FMC内部存储区域2FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank2;//设置FMC自动刷新次数,这里设置为2次FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 2;//此时不下发加载模式寄存器,配置为任意值即可FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;/* 检查 SDRAM 标志,等待至 SDRAM 空闲 */while (FMC_GetFlagStatus(FMC_BANK_SDRAM, FMC_FLAG_Busy) != RESET);/* 发送自动刷新命令*/FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);/*延时 */SDRAM_delay(10);/* 设置 sdram 加载模式寄存器配置 */tmpr = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_4           |   //突发长度设置为4SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL    |   //突发模式为顺序模式SDRAM_MODEREG_CAS_LATENCY_2            |   //列选通延迟为2个周期SDRAM_MODEREG_OPERATING_MODE_STANDARD  |   //工作模式为正常模式SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED;  ///* 配置命令:设置 SDRAM 寄存器 */FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_LoadMode;FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_COMMAND_TARGET_BANK;FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 0;FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = tmpr;/* 检查 SDRAM 标志,等待至 SDRAM 空闲 */while (FMC_GetFlagStatus(FMC_BANK_SDRAM, FMC_FLAG_Busy) != RESET);/* 发送上述命令*/FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);/*延时 */SDRAM_delay(10);/* 设置刷新计数器 *//*刷新速率 = (COUNT + 1) x SDRAM 频率时钟COUNT =( SDRAM 刷新周期/行数) - 20*//* 64ms/4096=15.62us (15.62 us x FSDCLK) - 20 =1386 */FMC_SetRefreshCount(1386);/* 发送上述命令*/while (FMC_GetFlagStatus(FMC_BANK_SDRAM, FMC_FLAG_Busy) != RESET);
}

到这里,已经可以实现SDRAM的读写了,这里我们写个测试程序,来实验一下上面的劳动成果。

三、测试

前面我们将SDRAM映射到FMC_Block2上了,起始地址为0xD0000000,这里我们将要用到的几个参数都做宏定义

#define SDRAM_SIZE 0x800000  //400000*16bits = 0x800000  ,8M字节
/*SDRAM 的bank选择*/
#define FMC_BANK_SDRAM            FMC_Bank2_SDRAM  
#define FMC_COMMAND_TARGET_BANK   FMC_Command_Target_bank2/* 这里将SDRAM挂载在FMC_Block2这里,起始地址为0xD000 0000 */   
#define SDRAM_BANK_ADDR     ((uint32_t)0xD0000000)/* FMC SDRAM 数据宽度 */  
#define SDRAM_MEMORY_WIDTH    FMC_SDMemory_Width_16b /* FMC SDRAM CAS Latency */  
#define SDRAM_CAS_LATENCY   FMC_CAS_Latency_2  /* FMC SDRAM SDCLK时钟分频因子 */  
#define SDCLOCK_PERIOD    FMC_SDClock_Period_2 /* FMC SDRAM 突发读取特性 */  
#define SDRAM_READBURST    FMC_Read_Burst_Enable  

映射之后,向SDRAM中写入读取数据就可以用指针的方式进行操作,如下:

#include "stm32f4xx.h"
#include "bsp_led.h"
#include "bsp_usart_dma.h"
#include "bsp_sdram.h"
#include <stdio.h>
uint16_t read_data;
int main(void)
{DEBUG_USART1_Config();LED_Config();printf("\r\n这是测试扩展外部SDRAM的例程实验\r\n");/*初始化SDRAM模块*/SDRAM_Init();*(uint16_t*)(SDRAM_BANK_ADDR) = 0xFEFE;read_data = *( uint16_t*) SDRAM_BANK_ADDR;printf("\r\n读取到的数据为:0x%x\r\n",read_data);while(1){}
}

这里需要注意,虽然我们通过指针将数据存放到SDRAM中了,但是实际在读取的时候,定义的变量read_data还是存放在sdram中,双击工程名,打开map文件,查看read_data会发现,系统分配的地址还是在内部SRAM中。

在这里插入图片描述

如果想将变量也定义到SDRAM中的话,需要进行强制指定将变量分配到SDRAM中,方法如下:

#include "stm32f4xx.h"
#include "bsp_led.h"
#include "bsp_usart_dma.h"
#include "bsp_sdram.h"
#include <stdio.h>
uint16_t read_data;
uint16_t read_data1 __attribute__((at(SDRAM_BANK_ADDR+0x124)));		/* 强制指定将read_data1定义到SDRAM中 */
int main(void)
{DEBUG_USART1_Config();LED_Config();printf("\r\n这是测试扩展外部SDRAM的例程实验\r\n");/*初始化SDRAM模块*/SDRAM_Init();*(uint16_t*)(SDRAM_BANK_ADDR) = 0xFEFE;read_data = *( uint16_t*) SDRAM_BANK_ADDR;printf("\r\n读取到的数据为:0x%x\r\n",read_data);*(uint16_t*)(SDRAM_BANK_ADDR+0x124) = 0xf9f9;		//这里也可以直接用read_data1来赋值printf("\r\n读取到的数据为:0x%x\r\n",read_data1);while(1){}
}

再看map文件中,read_data1已经被定义到SDRAM中了。

在这里插入图片描述

注意,在map中要查询变量的地址时,一定要将变量定义为全局变量,否则在map中查不到,并且此时强制指定分配地址也会无效。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/100927.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【sgCreateAPI】自定义小工具:敏捷开发→自动化生成API接口脚本(接口代码生成工具)

<template><div :class"$options.name"><div class"sg-head">接口代码生成工具</div><div class"sg-container"><div class"sg-start "><div style"margin-bottom: 10px;">接口地…

Linux密码遗忘?别慌!解锁你的系统小秘籍!

很多朋友经常会忘记Linux系统的root密码&#xff0c;linux系统忘记root密码的情况该怎么办呢&#xff1f;重新安装系统吗&#xff1f;当然不用&#xff01;进入单用户模式更改一下root密码即可。 步骤如下&#xff1a; 重启linux系统 3 秒之内要按一下回车&#xff0c;出现如…

基于减法优化SABO优化ELM(SABO-ELM)负荷预测(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

lv3 嵌入式开发-2 linux软件包管理

目录 1 软件包管理 1.1流行的软件包管理机制 1.2软件包的类型 1.3软件包的命名 2 在线软件包管理 2.1APT工作原理 2.2更新软件源 2.3APT相关命令 3 离线软件包管理 1 软件包管理 1.1流行的软件包管理机制 Debian Linux首先提出“软件包”的管理机制---Deb软件包 …

yolov5运行过程遇到的小问题(随时更新)

1.关于git的问题 解决办法&#xff1a;插入下面代码 import os os.environ["GIT_PYTHON_REFRESH"] "quiet"2.页面太小无法完成操作 解决办法: 如果不好使再考虑降低Batch_Size大小或者调整虚拟内存可用硬盘空间大小&#xff01;&#xff08;调整虚拟内存…

Debian11安装PostgreSQL+PostGIS+pgRouting ,链接Navicat

船新版本&#xff0c;遵循官网教程 1 准备一个Debian11系统2 从官网安装Postgres2.1 安装Postgres2.2 修改Postgres密码2.3 配置Postgres远程访问 3 安装Postgis、pgRouting4 链接Navicat 1 准备一个Debian11系统 2 从官网安装Postgres 2.1 安装Postgres 1 进入Postgre的官网…

05-Redis

1、Redis为什么快&#xff1f; 1、纯内存操作 2、单线程可以省去多线程时CPU上下文会切换的时间 3、渐进式ReHash、缓存时间戳 数组需要扩容的时候&#xff0c;他会维护两张hash表&#xff0c;比如第一张的数组长度为6&#xff0c;另一张的数组长度为12&#xff0c;在set和g…

数据结构--5.0.1图的存储结构

目录 一、邻接矩阵&#xff08;无向图&#xff09; 二、邻接矩阵&#xff08;有向图&#xff09; 三、邻接矩阵&#xff08;网&#xff09; 四、邻接表&#xff08;无向图&#xff09; 五、邻接表&#xff08;有向图&#xff09; ——图的存储结构相比较线性表与树来说就复…

Redis基础特性及应用练习-php

redis持久化&#xff08;persistence&#xff09; redis支持两种方式的持久化&#xff0c;可以单独使用或者结合起来使用。 第一种&#xff1a;RDB方式&#xff08;redis默认的持久化方式&#xff09; rdb方式的持久化是通过快照完成的&#xff0c;当符合一定条件时redis会自…

百度智能云千帆大模型丨未来人手必备的代码助手

文章目录 1. 前言2. 千帆大模型平台3. 十分友好的功能4. comate代码助手5. 总结 1. 前言 我之前给大家推荐过Poe这个网站&#xff0c;它用的人比较少&#xff0c;但一旦接触后会发现它其实挺强大的。 因为它是一个可以同时支持好几个大模型的在线聚合平台。常用的GPT4&#x…

android上架备案公钥和md5获取工具

最近很多公司上架遇到了一个问题&#xff0c;就是要提供app的备案证明&#xff0c;现在android上架都需要备案了&#xff0c;但是我们的证书都是通过工具生成的&#xff0c;哪里知道公钥和md5那些东西呢&#xff1f;无论安卓备案还是ios备案都需要提供公钥和md5。 包括ios的备案…

依赖导入失败场景和解决方案

在使用 Maven 构建项目时&#xff0c;可能会发生依赖项下载错误的情况&#xff0c;主要原因有以下几种&#xff1a; 下载依赖时出现网络故障或仓库服务器宕机等原因&#xff0c;导致无法连接至 Maven 仓库&#xff0c;从而无法下载依赖。 依赖项的版本号或配置文件中的版本号错…