当前位置: 首页 > news >正文

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中查不到,并且此时强制指定分配地址也会无效。

相关文章:

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

023- STM32学习笔记 - 扩展外部SDRAM&#xff08;一&#xff09; - 扩展外部SDRAM实验 本节内容中要配置的引脚很多&#xff0c;如果你用的开发板跟我的不一样&#xff0c;请详细参照STM32规格书中说明对相关GPIO引脚进行配置。 先提前对本届内容的变成步骤进行总结如下&…...

机器学习 | Python实现XGBoost极限梯度提升树模型答疑

机器学习 | MATLAB实现XGBoost极限梯度提升树模型答疑 目录 机器学习 | MATLAB实现XGBoost极限梯度提升树模型答疑问题系列问题回答问题系列 关于XGBoost有几个问题想请教一下。1.XGBoost的API有哪些种调用方法?2.参数如何调? 问题回答 XGBoost的API有2种调用方法,一种是我们…...

关于使用远程工具连接mysql数据库时,提示:Public Key Retrieval is not allowed

我在使用DBeaver工具连接 数据库时&#xff0c;提示&#xff1a;Public Key Retrieval is not allowed&#xff0c; 我在前一天还是可以连接的&#xff0c;但是今天突然无法连接了&#xff0c; 但是最后捣鼓了一下又可以了。 具体方法&#xff1a;首先先把mysql服务停了&#x…...

leetcode做题笔记​117. 填充每个节点的下一个右侧节点指针 II

给定一个二叉树&#xff1a; struct Node {int val;Node *left;Node *right;Node *next; } 填充它的每个 next 指针&#xff0c;让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点&#xff0c;则将 next 指针设置为 NULL 。 初始状态下&#xff0c;所有 next 指针都…...

解决博客不能解析PHP直接下载源码问题

背景&#xff1a; 在网站设置反向代理后&#xff0c;网站突然不能正常访问&#xff0c;而是会直接下载访问文件的PHP源码 解决办法&#xff1a; 由于在搞完反向代理之后&#xff0c;PHP版本变成了纯静态&#xff0c;所以网站不能正常解析&#xff1b;只需要把PHP版本恢复正常…...

voc 转coco

import os import random import shutil import sys import json import glob import xml.etree.ElementTree as ET""" 修改下面3个参数 1.val_files_num : 验证集的数量 2.test_files_num &#xff1a;测试集的数量 3.voc_annotations : voc的annotations路径 …...

【C语言每日一题】03. 对齐输出

题目来源&#xff1a;http://noi.openjudge.cn/ch0101/03/ 03 对齐输出 总时间限制: 1000ms 内存限制: 65536kB 问题描述 读入三个整数&#xff0c;按每个整数占8个字符的宽度&#xff0c;右对齐输出它们。 输入 只有一行&#xff0c;包含三个整数&#xff0c;整数之间以一…...

七大排序完整版

目录 一、直接插入排序 &#xff08;一&#xff09;单趟直接插入排 1.分析核心代码 2.完整代码 &#xff08;二&#xff09;全部直接插入排 1.分析核心代码 2.完整代码 &#xff08;三&#xff09;时间复杂度和空间复杂度 二、希尔排序 &#xff08;一&#xff09;对…...

C语言的数据类型简介

一、基本类型 &#xff08;1&#xff09;六种基本类型 **字符串常量和字符常量的不同 1&#xff09;‘a’为字符常量&#xff0c;”a”为字符串常量 2&#xff09;每个字符串的结尾&#xff0c;编译器会自动添加一个结束标志位‘\0’ “a”包含两个字符’a’和’\0’ &#x…...

Fei-Fei Li-Lecture 16:3D Vision 【斯坦福大学李飞飞CV课程第16讲:3D Vision】

目录 P1 2D Detection and Segmentation P2 Video 2D time series P3 Focus on Two Problems P4 Many more topics in 3D Vision P5-10 Multi-View CNN P11 Experiments – Classification & Retrieval P12 3D Shape Representations P13--17 3D Shape Represen…...

【计算机视觉】YOLO 入门:训练 COCO128 数据集

一、COCO128 数据集 我们以最近大热的YOLOv8为例&#xff0c;回顾一下之前的安装过程&#xff1a; %pip install ultralytics import ultralytics ultralytics.checks()这里选择训练的数据集为&#xff1a;COCO128 COCO128是一个小型教程数据集&#xff0c;由COCOtrain2017中…...

【数分面试答疑】XX场景如何分析问题的思考

问题&#xff1a; 如何分析消费贷客户的用款活跃度&#xff0c;简单列出分析报告的思路框架 解答 这个问题是一个典型的数据分析类的面试问题&#xff0c;主要考察面试者对于消费贷客户的用款活跃度分析的理解和方法&#xff0c;以及对于数据分析报告的撰写和呈现的能力。回…...

html中如何用vue语法,并使用UI组件库 ,html中引入vue+ant-design-vue或者vue+element-plus

html中如何用vue语法&#xff0c;并使用UI组件库 前言 先说一下本次应用的场景&#xff0c;本次项目中&#xff0c;需要引入github中别人写好的插件&#xff0c;插件比较大&#xff0c;没有方法直接在自己项目中&#xff0c;把别人的项目打包合并生成html&#xff08;类似于前…...

【数据结构】二叉数的存储与基本操作的实现

文章目录 &#x1f340;二叉树的存储&#x1f333;二叉树的基本操作&#x1f431;‍&#x1f464;二叉树的创建&#x1f431;‍&#x1f453;二叉树的遍历&#x1f3a1;前中后序遍历&#x1f4cc;前序遍历&#x1f4cc;中序遍历&#x1f4cc;后续遍历 &#x1f6eb;层序遍历&am…...

使用 Netty 实现群聊功能的步骤和注意事项

文章目录 前言声明功能说明实现步骤WebSocket 服务启动Channel 初始化HTTP 请求处理HTTP 页面内容WebSocket 请求处理 效果展示总结 前言 通过之前的文章介绍&#xff0c;我们可以深刻认识到Netty在网络编程领域的卓越表现和强大实力。这篇文章将介绍如何利用 Netty 框架开发一…...

一篇文章搞定《WebView的优化及封装》

一篇文章搞定《WebView的优化及封装》 前言WebView的过程分析确定优化方案一、预加载&#xff0c;复用缓冲池&#xff08;初始化优化&#xff09;优化的解析说明具体的实现 二、预置模版&#xff08;请求、渲染优化&#xff09;优化的解析说明具体的实现1、离线包2、预获取数据…...

FreeSWITCH 1.10.10 简单图形化界面5 - 使用百度TTS

FreeSWITCH 1.10.10 简单图形化界面5 - 使用百度TTS 0、 界面预览1、注册百度AI开放平台&#xff0c;开通语音识别服务2、获取AppID/API Key/Secret Key3、 安装百度语音合成sdk4、合成代码5、在PBX中使用百度TTS6、音乐文件-TTS7、拨号规则-tts_command 0、 界面预览 http://…...

DP读书:不知道干什么就和我一起读书吧

DP读书&#xff1a;不知道干什么就和我一起读书吧 为啥写博客&#xff1a;好处一&#xff1a;记录自己的学习过程优点二&#xff1a;让自己在各大社群里不那么尴尬推荐三&#xff1a;坚持下去&#xff0c;找到一个能支持自己的伙伴 虽然清楚知识需要靠时间沉淀&#xff0c;但在…...

【Linux】进程通信 — 信号(上篇)

文章目录 &#x1f4d6; 前言1. 什么是信号1.1 认识信号&#xff1a;1.2 信号的产生&#xff1a;1.3 信号的异步&#xff1a;1.4 信号的处理&#xff1a; 2. 前后台进程3. 系统接口3.1 signal&#xff1a;3.1 - 1 不能被捕捉的信号 3.2 kill&#xff1a;3.2 - 1 killall 3.3 ra…...

JS弃之可惜食之无味的代码冷知识

JS代码冷知识大全 1. 变量提升与暂死 在JavaScript中&#xff0c;变量提升是一个有趣且容易让人误解的概念。在代码中&#xff0c;变量和函数声明会在其所在作用域的顶部被提升&#xff0c;但是初始化并不会被提升。这可能导致在声明之前就使用变量&#xff0c;结果为undefin…...

label-studio的使用教程(导入本地路径)

文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...