023 - STM32学习笔记 - 扩展外部SDRAM(二) - 扩展外部SDRAM实验
023- STM32学习笔记 - 扩展外部SDRAM(一) - 扩展外部SDRAM实验
本节内容中要配置的引脚很多,如果你用的开发板跟我的不一样,请详细参照STM32规格书中说明对相关GPIO引脚进行配置。
先提前对本届内容的变成步骤进行总结如下:
- 初始化通讯使用的目标引脚及端口时钟;(再次强调,只要使用外设,一定要看时钟时候配置正确并开启!)
- 是能FMC外设时钟;(再再次强调,只要使用外设,一定要看时钟时候配置正确并开启!)
- 配置FMC SDRAM的时序和工作模式;
- 根据SDRAM的初始化流程编写初始化函数;
- 访问外部SDRAM存储器;
- 编写测试程序,校验读写的数据。
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(一) - 扩展外部SDRAM实验 本节内容中要配置的引脚很多,如果你用的开发板跟我的不一样,请详细参照STM32规格书中说明对相关GPIO引脚进行配置。 先提前对本届内容的变成步骤进行总结如下&…...
机器学习 | Python实现XGBoost极限梯度提升树模型答疑
机器学习 | MATLAB实现XGBoost极限梯度提升树模型答疑 目录 机器学习 | MATLAB实现XGBoost极限梯度提升树模型答疑问题系列问题回答问题系列 关于XGBoost有几个问题想请教一下。1.XGBoost的API有哪些种调用方法?2.参数如何调? 问题回答 XGBoost的API有2种调用方法,一种是我们…...
关于使用远程工具连接mysql数据库时,提示:Public Key Retrieval is not allowed
我在使用DBeaver工具连接 数据库时,提示:Public Key Retrieval is not allowed, 我在前一天还是可以连接的,但是今天突然无法连接了, 但是最后捣鼓了一下又可以了。 具体方法:首先先把mysql服务停了&#x…...
leetcode做题笔记117. 填充每个节点的下一个右侧节点指针 II
给定一个二叉树: struct Node {int val;Node *left;Node *right;Node *next; } 填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL 。 初始状态下,所有 next 指针都…...
解决博客不能解析PHP直接下载源码问题
背景: 在网站设置反向代理后,网站突然不能正常访问,而是会直接下载访问文件的PHP源码 解决办法: 由于在搞完反向代理之后,PHP版本变成了纯静态,所以网站不能正常解析;只需要把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 :测试集的数量 3.voc_annotations : voc的annotations路径 …...
【C语言每日一题】03. 对齐输出
题目来源:http://noi.openjudge.cn/ch0101/03/ 03 对齐输出 总时间限制: 1000ms 内存限制: 65536kB 问题描述 读入三个整数,按每个整数占8个字符的宽度,右对齐输出它们。 输入 只有一行,包含三个整数,整数之间以一…...
七大排序完整版
目录 一、直接插入排序 (一)单趟直接插入排 1.分析核心代码 2.完整代码 (二)全部直接插入排 1.分析核心代码 2.完整代码 (三)时间复杂度和空间复杂度 二、希尔排序 (一)对…...
C语言的数据类型简介
一、基本类型 (1)六种基本类型 **字符串常量和字符常量的不同 1)‘a’为字符常量,”a”为字符串常量 2)每个字符串的结尾,编译器会自动添加一个结束标志位‘\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为例,回顾一下之前的安装过程: %pip install ultralytics import ultralytics ultralytics.checks()这里选择训练的数据集为:COCO128 COCO128是一个小型教程数据集,由COCOtrain2017中…...
【数分面试答疑】XX场景如何分析问题的思考
问题: 如何分析消费贷客户的用款活跃度,简单列出分析报告的思路框架 解答 这个问题是一个典型的数据分析类的面试问题,主要考察面试者对于消费贷客户的用款活跃度分析的理解和方法,以及对于数据分析报告的撰写和呈现的能力。回…...
html中如何用vue语法,并使用UI组件库 ,html中引入vue+ant-design-vue或者vue+element-plus
html中如何用vue语法,并使用UI组件库 前言 先说一下本次应用的场景,本次项目中,需要引入github中别人写好的插件,插件比较大,没有方法直接在自己项目中,把别人的项目打包合并生成html(类似于前…...
【数据结构】二叉数的存储与基本操作的实现
文章目录 🍀二叉树的存储🌳二叉树的基本操作🐱👤二叉树的创建🐱👓二叉树的遍历🎡前中后序遍历📌前序遍历📌中序遍历📌后续遍历 🛫层序遍历&am…...
使用 Netty 实现群聊功能的步骤和注意事项
文章目录 前言声明功能说明实现步骤WebSocket 服务启动Channel 初始化HTTP 请求处理HTTP 页面内容WebSocket 请求处理 效果展示总结 前言 通过之前的文章介绍,我们可以深刻认识到Netty在网络编程领域的卓越表现和强大实力。这篇文章将介绍如何利用 Netty 框架开发一…...
一篇文章搞定《WebView的优化及封装》
一篇文章搞定《WebView的优化及封装》 前言WebView的过程分析确定优化方案一、预加载,复用缓冲池(初始化优化)优化的解析说明具体的实现 二、预置模版(请求、渲染优化)优化的解析说明具体的实现1、离线包2、预获取数据…...
FreeSWITCH 1.10.10 简单图形化界面5 - 使用百度TTS
FreeSWITCH 1.10.10 简单图形化界面5 - 使用百度TTS 0、 界面预览1、注册百度AI开放平台,开通语音识别服务2、获取AppID/API Key/Secret Key3、 安装百度语音合成sdk4、合成代码5、在PBX中使用百度TTS6、音乐文件-TTS7、拨号规则-tts_command 0、 界面预览 http://…...
DP读书:不知道干什么就和我一起读书吧
DP读书:不知道干什么就和我一起读书吧 为啥写博客:好处一:记录自己的学习过程优点二:让自己在各大社群里不那么尴尬推荐三:坚持下去,找到一个能支持自己的伙伴 虽然清楚知识需要靠时间沉淀,但在…...
【Linux】进程通信 — 信号(上篇)
文章目录 📖 前言1. 什么是信号1.1 认识信号:1.2 信号的产生:1.3 信号的异步:1.4 信号的处理: 2. 前后台进程3. 系统接口3.1 signal:3.1 - 1 不能被捕捉的信号 3.2 kill:3.2 - 1 killall 3.3 ra…...
JS弃之可惜食之无味的代码冷知识
JS代码冷知识大全 1. 变量提升与暂死 在JavaScript中,变量提升是一个有趣且容易让人误解的概念。在代码中,变量和函数声明会在其所在作用域的顶部被提升,但是初始化并不会被提升。这可能导致在声明之前就使用变量,结果为undefin…...
数据结构初阶--排序
目录 一.排序的基本概念 1.1.什么是排序 1.2.排序算法的评价指标 1.3.排序的分类 二.插入排序 2.1.直接插入排序 2.2.希尔排序 三.选择排序 3.1.直接选择排序 3.2.堆排序 重建堆 建堆 排序 四.交换排序 4.1.冒泡排序 4.2.快速排序 快速排序的递归实现 法一&a…...
赴日IT 如何提高去日本做程序员的几率?
其实想去日本做IT工作只要满足学历、日语、技术三个必要条件,具备这些条件应聘就好,不具备条件你就想办法具备这些条件,在不具备条件之前不要轻易到日本去,日本IT行业虽然要求技术没有国内那么高,但也不是随便好进入的…...
c# 使用了 await、asnync task.run 三者结合使用
在 C# 异步编程中,await 和 async 关键字结合使用可以让你更方便地编写异步代码,而无需直接使用 Task.Run。然而,有时候你可能仍然需要使用 Task.Run 来在后台线程上执行某些工作,这取决于你的代码逻辑和需求。 await 和 async 关…...
C#获取屏幕缩放比例
现在1920x1080以上分辨率的高分屏电脑渐渐普及了。我们会在Windows的显示设置里看到缩放比例的设置。在Windows桌面客户端的开发中,有时会想要精确计算窗口的面积或位置。然而在默认情况下,无论WinForms的Screen.Bounds.Width属性还是WPF中SystemParamet…...
Rn实现省市区三级联动
省市区三级联动选择是个很频繁的需求,但是查看了市面上很多插件不是太老不维护就是不满足需求,就试着实现一个 这个功能无任何依赖插件 功能略简单,但能实现需求 核心代码也尽力控制在了60行左右 pca-code.json树型数据来源 Administrative-d…...
SpringCloud学习笔记(十)_SpringCloud监控
今天我们来学习一下actuator这个组件,它不是SpringCloud之后才有的,而是SpringBoot的一个starter,Spring Boot Actuator。我们使用SpringCloud的时候需要使用这个组件对应用程序进行监控与管理 在SpringBoot2.0版本中,actuator可以…...
测试理论与方法----测试流程的第二个环节:测试计划
二、软件测试分类与测试计划 1、软件测试的分类(理解掌握) 根绝需求规格说明书,在设计阶段会产出的两个文档: 概要设计(HLD):设计软件的结构,包含软件的组成,模块之间的层次关系,模块与模块之间的调用关系…...
postgresql-子查询
postgresql-子查询 简介派生表IN 操作符ALL 操作符ANY 操作符关联子查询横向子查询EXISTS 操作符 简介 子查询(Subquery)是指嵌套在其他 SELECT、INSERT、UPDATE 以及 DELETE 语句中的 查询语句。 子查询的作用与多表连接查询有点类似,也是为…...
Linux 系统运维工具之 OpenLMI
一、前要 OpenLMI(全称 Open Linux Management Infrastructure)即开放式的 Linux 管理基础架构。OpenLMI 是一个开源项目,用于管理 Linux 系统管理的通用基础架构。它建立在现有工具基础上,充当抽象层,以便向系统管理…...
8天长假快来了,Python分析【去哪儿旅游攻略】数据,制作可视化图表
目录 前言环境使用模块使用数据来源分析 代码实现导入模块请求数据解析保存 数据可视化导入模块、数据年份分布情况月份分布情况出行时间情况费用分布情况人员分布情况 前言 2023年的中秋节和国庆节即将来临,好消息是,它们将连休8天!这个长假…...
【HSPCIE仿真】输入网表文件(5)基本仿真输出
仿真输出 1. 概述1.1 输出变量1.2 输出分析类型 2. 显示仿真结果2.1 .print语句基本语法示例 2.2 .probe 语句基本语法示例 2.3 子电路的输出2.4 打印控制选项.option probe.option post.option list.option ingold 2.5 .model_info打印模型参数 3. 仿真输出参数的选择3.1 直流…...
uni-app中使用iconfont彩色图标
uni-app中使用iconfont彩色图标 大家好,今天我们来学习一下uni-app中使用iconfont彩色图标,好好看,好好学,超详细的 第一步 首先,从iconfont官网(iconfont-阿里巴巴矢量图标库)选择自己需要的图…...
Hystrix: Dashboard流监控
接上两张服务熔断 开始搭建Dashboard流监控 pom依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocat…...
iconfont 图标在vue里的使用
刚好项目需要使用一个iconfont的图标,所以记录一下这个过程 1、iconfont-阿里巴巴矢量图标库 这个注册一个账号,以便后续使用下载代码时需要 2、寻找自己需要的图标 我主要是找两个图标 ,一个加号,一个减号,分别加入到…...
QT登陆注册界面练习
一、界面展示 二、主要功能界面代码 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QMainWindow(parent), ui(new Ui::Widget) {ui->setupUi(this);this->setFixedSize(540,410); //设置固定尺寸th…...
MySQL DATE_SUB的实践
函数简介DATE_SUB()函数从DATE或DATETIME值中减去时间值(或间隔)。 下面说明了DATE_SUB()函数的语法: DATE_SUB(start_date,INTERVAL expr unit); DATE_SUB()函数接受两个参数: start_date是DATE或DATETIME的起始值。 expr是一个字符串,用于确…...
OpenCV最常用的50个函数
Python版:OpenCV提供了众多图像处理算子和函数,涵盖了各种任务和技术。以下是OpenCV中一些常用的50个算子和函数: cv2.imread:用于读取图像文件。cv2.imshow:用于显示图像。cv2.imwrite:用于保存图像。cv2…...
Android AGP8.1.0组件化初探
Android AGP8.1.0组件化初探 前言: 前面两篇完成了从AGP4.2到 AGP8.1.0的升级,本文是由于有哥们留言说在AGP8.0中使用ARouter组件化有问题,于是趁休息时间尝试了一下,写了几个demo,发现都没有问题,跳转和传…...
文件修改时间能改吗?怎么改?
文件修改时间能改吗?怎么改?修改时间是每个电脑文件具备的一个属性,它代表了这个电脑文件最后一次的修改时间,是电脑系统自动赋予文件的,相信大家都应该知道。我们右击鼠标某个文件,然后点击弹出菜单里面的…...
2023年下半年软考报名注意事项!
考试注意事项: 分数线:所有科目成绩全部在45分以上(含45分)通过考试;三科目的话,必须每科目都及格才算通过考试,只有一个不合格的,本次考试其他两个无效。 出成绩时间:预…...
【LeetCode每日一题】——274.H指数
文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时间频度】九【代码实现】十【提交结果】 一【题目类别】 排序 二【题目难度】 中等 三【题目编号】 274.H指数 四【题目描述】 给你一个整数数组 ci…...
网络编程 day 4
1、多进程并发服务器根据流程图重新编写 #include <myhead.h>#define ERR_MSG(msg) do{\fprintf(stderr, "__%d__:", __LINE__); \perror(msg);\ }while(0)#define PORT 8888 //端口号,范围1024~49151 #define IP "192.168.11…...
【Java架构-版本控制】-Git基础
本文摘要 Git作为版本控制工具,使用非常广泛,在此咱们由浅入深,分三篇文章(Git基础、Git进阶、Gitlab搭那家)来深入学习Git 文章目录 本文摘要1.Git仓库基本概念1.1 远程仓库(Remote)1.2 本地库(Repository) 2. Git仓库…...
ubuntu 挂载硬盘操作
1. 查看磁盘 sudo fdisk -l 2. 查看UUID sudo blkid记录下待挂载硬盘的UUID, 后面要使用 ps. 如果报错,检查是否已格式化硬盘 查看新硬盘的盘符,我的是/dev/sda,用下述命令格式化 sudo mkfs -t ext4 /dev/sda3. 创建挂载点 我的是在/mnt…...
关于商品活动的H5页面技术总结
背景 在单个html文件里面使用vue3、jquery等其他第三方js库,实现规定的页面效果,其中主要功能是从商品json数据中读取数据,然后可以通过搜索框、下拉框、左侧菜单来筛选商户信息。 页面布局 技术要点: 1、通过路由来进行页面布…...
前端:横向滚动条,拖动进行左右滚动(含隐藏滚动条)
效果 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width, i…...
Android JNI Bitmap指定颜色值替换
#include <jni.h> #include <string> #include <android/bitmap.h> #include <cmath> #include <android/log.h> //定义TAG之后,我们可以在LogCat通过TAG过滤出NDK打印的日志 #define TAG "BitmapOperationNative" // 定义…...
测试理论与方法----测试流程的第四个步骤:执行测试,提出缺陷
8、执行测试—–>提交缺陷报告 测试流程:执行测试—–>提交缺陷报告 1、缺陷的概述(回顾) 结果角度:实际结果和预期结果不一致 需求角度:所有不满足需求或超出需求的,都是缺陷 2、缺陷的相关属性…...
Stable Diffusion 提示词入门指南
前言 本文主要讲解 Stable Diffusion (下文简称 SD)提示词的用法,帮助大家生成更高质量的图片 本章节主要讲解文生图,其他类型读者可以自行探索。同时本文主要是以 Stable Diffusion Discard 的形式生成图片 如果各位对于图片隐…...
基于鹰栖息算法优化的BP神经网络(预测应用) - 附代码
基于鹰栖息算法优化的BP神经网络(预测应用) - 附代码 文章目录 基于鹰栖息算法优化的BP神经网络(预测应用) - 附代码1.数据介绍2.鹰栖息优化BP神经网络2.1 BP神经网络参数设置2.2 鹰栖息算法应用 4.测试结果:5.Matlab代…...