022 - STM32学习笔记 - 扩展外部SDRAM(一) - 初识SDRAM和FMC

022 - STM32学习笔记 - 扩展外部SDRAM(一) - 初识SDRAM和FMC

之前学习了I2C读写EEPROM和SPI读写FLASH,学完之后在学习一种新的存储介质–SDRAM。

一、初识SDRAM

我们知道在stm32内部是有一定大小的SRAM(256Kb)和FLASH(1M)作为内存和程序存储空间,但是如果我们内建的程序体量比较大的时候,Stm32内部的存储空间就不够用了,这时候就需要在外部进行扩展。

在Stm32扩展内存时,可选的有SRAM和SDRAM,但是相对来说,SDRAM的性价比更高一些,所以这里就采用SDRAM来对Stm32进行扩容。给Stm32扩容的方式与PC扩展内存的原理是一样的,PC上扩容只需要增加内存条即可,而内存条则是集成了很多颗SDRAM颗粒从而组成内存单元,在STM32上,则是直接将Stm32与SDRAM直接相连。

野火F429开发板上的SDRAM使用的是IS42-45S16400J芯片,其存储大小为64Mbit,即为8Mb存储空间。

在这里插入图片描述

在这里插入图片描述

根据官方手册,可以看到IS42的芯片内部结构框图可分为5部分:

1、信号线与地址控制

芯片框图中,①部分为信号线,主要由下表所列出的组成。

信号线类型说明
CLKI(输入)同步时钟信号,所有输入信号都在 CLK 为上升沿的时候被采集
CKEI(输入)时钟使能信号,禁止时钟信号时 SDRAM 会启动自刷新操作
CS#I(输入)片选信号,低电平有效
CAS#I(输入)列地址选通,为低电平时地址线表示的是列地址
RAS#I(输入)行地址选通,为低电平时地址线表示的是行地址
WE#I(输入)写入使能,低电平有效
DQM[0:1]I(输入)数据输入/输出掩码信号,表示 DQ 信号线的有效部分
BA[0:1]I(输入)Bank 地址输入,选择要控制的 Bank
A[0:11]I(输入)地址输入
DQ[0:15]I/O(输入/输出)数据输入输出信号
2、逻辑控制单元

通过内部的逻辑控制单元控制整个芯片,外部通过片选信号(CS)、写使能(WE)、列选通(CAS)、行选通(RAS)以及地址线向内部逻辑单元输入命令。输入的命令经过命令译码器译码,同时将控制参数保存到模式寄存器中。内部结构框图②部分即为逻辑控制单元。

3、地址控制

在SDRAM中,地址线分为“A”类与“BA”类两种地址线,其中A类地址线是包含行(Row)和列(Column)共用的地址总线,而BA类地址线则是用于指定SDRAM内部存储阵列号(BANK)。并且在命令模式下,A类地址线还用于输入一些命令参数。内部结构框图③部分为地址控制单元。

4、存储阵列

与我们常用的Excel一样,当我们要读取Excel内的数据时,只需要根据列、行号就可以直接定位到对应的单元格,SDRAM将内部包含四个BANK,类似于Excel中的sheet一样,所以我们寻址时只需要指定BANK号+列地址+行地址,就可以找到指定的存储单元。

在这里插入图片描述

在SDRAM中,向外提供了独立的BA线用于BANK寻址,行列地址则复用A类地址线。在IS42芯片内部结构框图中,④部分就是内部的存储阵列结构,当RAS为低电平时,行地址选通,地址线A[11:0]表示的地址会被送到行地址译码及锁存器中,同时BA[1:0]地址线选中的BANK也会被选中锁存,当控制线CAS为低电平时,列地址选通,地址线A[11:0]表示的地址将送到列地址译码器及锁存器中,从而完成寻址操作。

5、数据输入与输出

上述寻址完成后,DQ[15:0]表示的数据会通过IS42芯片内部结构框图中⑤标记的输入数据寄存器,将输入数据传输到存储阵列中保存;数据的输出与之相反。

在野火F429开发板中使用的SDRAM芯片,存储整列的数据宽度为16位,当与SDRAM进行数据通讯时,16位的数据时同步传输的,但是根据野火官方资料中提到的,实际使用中可能会采用8位、16位宽进行存取数据,16位数据线并不是所有时候都是同时使用。比:如传输8位数据的时候,只需要使用DQ[7:0]这8位数据线即可,而DQ[15:8]这8位数据线必须忽略,否则会修改我们期望存储位置之外的内容。因此在实际使用中,还会使用DQM[1:0]线来配合,没跟DQM线对应8位数据,DQM:0为低电平,DQM:1为高电平时,数据线DQ[7:0]有效,而DQ[15:8]无效;当DQM[1:0]都为低电平时,表示数据线[15:0]均有效。

6、SDRAM命令

控制SDRAM需要用到一些命令,通过不同的信号线状态组合可以合成不同的命令。表格中,H表示高电平,L表示低电平,X表示任意电平。

命令CS#RAS#CAS#WE#DQMADDRDQ
命令禁止HXXXXXX
空操作LHHHXXX
行有效LLHHXBank/rowX
读命令LHLHL/HBank/colX
写命令LHLLL/HBank/colValid
预充电LLHLXCodeX
自动/自我刷新LLLHXXX
加载模式寄存器LLLLXOp-codeX
突发停止LHHLXXactive
a、命令禁止:

当CS#为高电平时,表示命令禁止(COMMAND INHBIT)将禁止SDRAM执行新的操作,但是不能停止当前正在执行的命令。

b、空操作:

“ 空操作” (NO OPERATION), “命令禁止”的反操作, 用于选中 SDRAM,以便接下来发送命令,也就是说当我们要对SDRAM进行后续操作时,首先需要下发空操作命令。

c、行有效:

进行存储单元寻址时,需要先选中要访问的 Bank 和行,使它处于激活状态。该操作通过“行有效” (ACTIVE)命令实现,发送行有效命令时, RAS 线为低电平,同时通过 BA 线以及 A 线发送 Bank 地址和行地址。

d、列读写:

当行有效命令确定后,紧接着就需要进行列寻址,读命令与写命令的时序基本一致,通过共用地址线A[11:0]发送列地址,同时WE#引脚表示读/写方向,WE#为低电平时,表示写,高电平时表示读。同时读写数据时,用DQM#线来确定有效的数据线。在野火F429中仅使用A[7:0]来表示列地址,A10线用于控制是否自动预充电,A10为高电平时使能预充电,低电平时关闭。

e、预充电

在SDRAM中,寻址必须要在读写进行操作完成后,如果要对同一个BANK的另一行进行寻址,就需要将原来有效的行先关闭,重新发送行/列地址。BANK关闭当前工作行,准备打开新行的操作就是预充电(Precharge)。

预充电可以通过每次发送读写命令时同时使用A10线控制自动进行预充电,也可以通过独立的命令控制。按照官方的解释,预充电是对工作行中所有存储整列进行数据重写,并对行地址进行复位,以准备新行的工作。就是说当前一个时序的读写操作完成后,需要对新行进行寻址时,需要先将原来的地址线复位,然后再重新下发行地址以及列地址。

f、刷新

SDRAM需要不断刷新才能保留住数据,刷新与预充电中读写的操作本质是一样的,也是SDRAM中比较重要的一项操作。但是预充电是对一个或者所有的BANK的工作行进行操作,操作周期不定,而刷新是固定周期对所有行进行操作,从而保证在SDRAM中很久没使用到的存储单元的数据正确性。

刷新分为两种:自动刷新与自我刷新,发送命令后,CKE时钟为低电平时,使用自动刷新,否则为自我刷新操作。自动刷新是SDRAM按照周期性(时钟周期)对SDRAM中所有BANK的工作行进行刷新。而自我刷新则是当时钟线关闭时,SDRAM启动内部刷新的操作,不需要依靠外部时钟工作。所以这里两者的区别在于是否存在时钟线是否存在周期信号。

e、加载模式寄存器

SDRAM的控制逻辑是根据它的模式寄存器来管理整个系统,这个模式寄存器就是通过“加载模式寄存器”来进行配置,发送该命令时,需要通过地址线表示要存入模式寄存器的参数“OP-Code”,关于每条地址线表示的参数如下:

在这里插入图片描述

突发长度配置(Burst Length):ADDR[2:0]

突发我们在之前学习DMA的时候接触过了,这里在复习一下,突发主要是指在同一行中相邻的的存储单元连续进行数据传输的方式,连续传输所涉及到的存储单元的数量就是突发长度。

在实际对SDRAM的读写中,我们一般不会对存储器一个一个存储单元的去读写,这样有耗时又耗力,需要不停的发送列地址与读写命令,虽然读写延迟相同可以让数据的传输在I/O端是连续的,但是会消耗大量的内存/控制资源,而且数据在传输过程中,也无法接收新的命令,因此效率比较低下。

要解决上面的问题,需要用到突发传输技术,只需要指定起始列地址和突发长度,内存会自动从起始位置到后面突发长度的存储单元进行读写,不需要控制器连续的提供地址。

在上图中,可以看到突发长度可选为1、2、4、8,当设定为1时,相当于不采用突发模式,常见的突发传输长度设定为4或者8。

这里需要注意的是,当传输的实际数据长度小于设定的突发长度时,可下发突发停止命令结束传输。

突发模式设置(Burst Type):ADDR[3]

突发模式分为顺序模式间隔模式两种,在顺序模式中,操作会按照地址的顺序连续执行;如果时间隔模式,则是操作地址是跳跃的。这里野火的资料中没有过多介绍间隔模式,等到后面学习到了,再做补充。顺序模式访问时,地址顺序时按照“0-1-2-3-4-5-6-7“的地址序列进行访问。

列地址选通延迟(CASLatency):ADDR[6:4]

字面意思,当发送读命令(命令中会包含列地址)时,列地址选通延迟就是在命令下发后,延迟多久后数据线DQ才会输出有效数据,可选的延迟周期有1、2、3个时钟周期,一般设置为2或者3个时钟周期。

这个配置只针对于读命令,写命令时不需要,当发出写命令时,可以同时发送要写入的数据。

工作模式(Operating Mode):ADDR[8:7]

这一项需要注意,在实际使用时必须配置为**“00”**(正常模式),其他值是测试模式或者被保留的设定。

写突发模式(Write Burst Mode):ADDR[9]

WB用于配置写操作时的突发特性,可选择使用BL设置的突发长度或非突发模式。

配置为0时,表示使用BL设置的突发长度,配置为1时,则使用非突发模式。

剩余的三位ADDR[11:10]被保留,不需要进行设置。

二、SDRAM的读写流程

上面再初步认识了SDRAM以及相关的命令后,我们再看一下SDRAM的读写流程

1、初始化流程

在这里插入图片描述

流程如下:

1)、SDRAM上电,并提供至少100us稳定时钟;

2)、发送“空操作”命令(NOP);

3)、发送“预充电”命令(PRECHARGE),控制所有BANK进行预充电,并等待tRP时间,tRP表示预充电与其他命令之间的延迟;

4)、发送至少2个“自动刷新”命令(AUTO REFRESH),每个命令后需等待tRC时间,tRC表示自动刷新时间;注:野火在这里标记的为tRFC

5)、发送“加载模式寄存器”命令(LOAD MODE REGISTER),配置SDRAM的工作参数,并等待tMRD时间,tMRD表示加载模式寄存器命令与行或者刷新命令之间的延迟;

6)、初始化流程完毕,到这里就可以开始读写数据了。

2、读写流程

读时序和写时序过程基本一致,如下时序图:

在这里插入图片描述

读时序

在这里插入图片描述

写时序

1)、发送行有效(ACTIVE)命令,发送的同时需要下发BANK地址和行地址,发送后等待tRCD时间,tRCD表示行有效命令与读/写命令之间的延迟;

2)、发送读/写(READ/WRITE)命令,在发送命令的同时发送列地址,完成寻址的地址输入。这里需要注意下发读命令后,根据模式寄存器的CL定义,延迟CL个时钟周期后,数据线 DQ 才输出有效数据,写命令则是没有CL延迟,下发写命令时,同时就可以将要写入的数据通过DQ写入SDRAM。另外,读/写命令需要通过A[10]地址线进行自动预充电,当SDRAM收到带预充电点的读/写命令后,需要等待tWR时间后才会开始,tWR表示写命令与预充电之间的延迟;

3)、执行预充电(auto precharge)命令后,需要等待tRP时间,tRP表示预充电与其它命令之间的延迟;

4)、本次读写完成后,发送第二次“行有效”(ACTIVE)命令准备读写下一个数据;

在上图中,标号为④的 tRAS,表示自刷新周期,即在前一个“行有效”与 “预充电” 命令之间的时间;标号⑤处的 tRC,表示两个行有效命令或两个刷新命令之间的延迟。

关于上面tRP、tRC、tMRD、tRCD、tWR、tRP时间周期,是跟具体SDRAM相关,具体可查阅数据手册获知,这里我截图出来一部分,各位先看一下,后面在FMC配置的时候再去说怎么看。

在这里插入图片描述

三、可变存储控制器(FMC)

在最开始学习STM32时,我们遇到加入固件库后,加入FSMC的文件后,会报错,这里是因为在STM32中为了驱动SRAM、SDRAM、NOR FLASH以及NAND FLASH等类型的存储器,需要用到存储控制器,即FMC/FSMC。在429中采用的时FMC(Flexible Memory Controller),即为可变存储控制器,在其他STM32控制器中,可能只有FSMC控制器(Flexible Static Memory Controller)可变静态存储控制器,两者的区别是,在驱动SDRAM时需要定时刷新,而这项功能只有FMC才支持,FSMC不支持,因此FSMC只能支持普通的SDRAM,不能支持DDR类型的SDRAM。

1、FMC结构

下图即为FMC外设的结构框图:

在这里插入图片描述

a、通讯引脚

图中标号为①的即为我们在控制SDRAM中需要用到的引脚,虽然看着FMC框图中引脚很多,特别时有一部分信号线都是共用的,比如其中地址线FMC_A和FMC_D时所有控制器共用,具体哪些引脚对应哪些GPIO端口,可以在STM32的官方手册中查到,这里直接看一下野火F429核心板原理图就知道如何对应的了。

在这里插入图片描述

这里需要注意,FMC_SDCKE线和FMC_SDNE都各有两条,FMC_SDCKE用于控制SDRAM的时钟使能,FMC_SDNE用于控制SDRAM芯片的片选使能,这两条线用于控制STM32使用不同的存储区域驱动SDRAM,使用编号为0的信号线组会使用STM32的存储器区域1,使用编号为1的信号线组会使用存储器区域2。

b、存储控器控制器

在FMC的外设图中,可以看到NOR/PSRAM/SRAM设备使用的是相同的控制器,NAND/PC卡用的是相同的控制器,而SDRAM存储器使用独立的控制器。不同的控制器有专用寄存器用于配置器工作模式。

SDRAM控制寄存器及时序寄存器各有两个,分别对应SDRAM存储区域1和存储区域2的配置。

FMC_SDCR 控制寄存器可配置 SDCLK 的同步时钟频率、突发读使能、写保护、 CAS延迟、行列地址位数以及数据总线宽度等。

FMC_SDTR 时序寄存器用于配置 SDRAM 访问时的各种时间延迟,如 TRP 行预充电
延迟、 TMRD 加载模式寄存器激活延迟等。

FMC_SDCMR 命令模式寄存器用于存储要发送到 SDRAM 模式寄存器的配置,以及要向 SDRAM 芯片发送的命令。

FMC_SDRTR 用于配置 SDRAM 的自动刷新周期

c、时钟逻辑控制

在这里插入图片描述

FMC外设是挂载在AHB3总线上,时钟信号有HCLK提供,控制器的时钟输出由其分频而得。用于与SDRAM芯片进行时钟同步的引脚为FMC_SDCLK,他的时钟频率可通过FMC_SDCR1寄存器的SDCLK位配置,可配置为HCLK的1/2或者1/3,我们之前学习RCC时钟树时知道F429的HCLK时钟频率一般配置为180MHz,因此与SDRAM通讯的时钟最高频率为90MHz。

2、FMC地址映射

当FMC连接好外部存储器并初始化后,可以通过直接访问地址来读取数据,之前学习I2C读写EEPROM和SPI读写FLASH时,我们需要通过I2C或SPI总线下发地址,才能接收到由存储器返回的数据。地址和数据都要通过不同的变量存储,并且还得使用代码控制发送读写命令。

当使用FMC访问外部存储器时,存储单元是映射到STM32的内存存储空间,访问某个地址的数据时,可以通过映射的地址指针直接去读写该地址的内容,至于底层的事情,就交给FMC自动完成即可。

在这里插入图片描述

上图中FMC区域中Block3和4为External RAM地址空间,主要映射的为NOR/PSRAM/SRAM/NAND FLASH以及PC卡的地址;Block5和6为External device区域,映射的为SDRAM的地址,因此访问挂载在FMC上的存储器时,就可以通过直接访问映射的地址直接访问了。

a、存储区域

FMC把SDRAM的存储区域划分为BNAK1和BANK2两块,这里只是FMC的地址区域划分,并不是SDRAM片内的BANK划分,需要注意。FMC的每个BANK都有不一样的其实地址,而且有独立的FMC_SDCR控制寄存器、FMC_SDTR时序寄存器、FMC_SDCKE时钟使能信号线和FMC_SDCLK信号线。FMCSDCKE0和FMC_SDCLJ0对应的存储区域1的地址范围是0xC000 0000 ~ 0xCFFF FFFF,而FMC_SDCKE1和FMC_SDCLK1对应的存储区域2地址范围是0xD000 0000 ~ 0xDFFF FFFF。

b、SDRAM时序结构体

FMC使用SDRAM存储器时主要是配置时序寄存器以及控制寄存器,利用标准库的SDRAM时序结构体以及初始化结构体可以写入参数。

SDRAM时序结构体FMC_SDRAMTimingInitTypeDef

/** 
  * @brief  控制SDRAM的时序参数,单位为周期,每个参数的值范围为1-16个周期
  */
typedef struct
{
  uint32_t FMC_LoadToActiveDelay;      /* TMRD:加载模式寄存器命令后的延迟 */
  uint32_t FMC_ExitSelfRefreshDelay;   /* TXSR:自刷新后的延迟 */
  uint32_t FMC_SelfRefreshTime;        /* TRAS:自刷新时间 */
  uint32_t FMC_RowCycleDelay;          /* TRC:行循环延迟 */
  uint32_t FMC_WriteRecoveryTime;      /* TWR:恢复延迟 */
  uint32_t FMC_RPDelay;                /* TRP:行预充电延迟 */
  uint32_t FMC_RCDDelay;               /* TRCD:行到列延迟 */
}FMC_SDRAMTimingInitTypeDef;

FMC_LoadToActiveDelay:本成员设置TMRD延迟,即为发送加载模式寄存器命令后要等待的时间,之后才可以再发送行有效或者刷新命令。

FMC_ExitSelfRefreshDelay:设置推出TXRS延迟,即退出自我刷新命令后要等待的时间,之后才可以发送行有效命令。

FMC_SelfRefreshTime:设置自我刷新时间TRAS,即发送行有效命令后需要等待的时间,之后才能执行预充电命令。

FMC_RowCycleDelay:设置TRC延迟,两个行有效命令之间的延迟,以及两个相邻刷新命令之间的延迟。

FMC_WriteRecoveryTime:设置TWR延迟,即写命令和预充电命令之间的延迟,之后才可以执行预充电命令。

FMC_RPDelay:设置TRP延迟,即预充电命令与其他命令之间的延迟。

FMC_RCDDelay:设置TRCD延迟,即行有效命令到列读写命令之间的延迟。

c、SDRAM初始化结构体
/* @brief FMC SDRAM 初始化结构体类型定义 */
typedef struct
{
    uint32_t FMC_Bank; 					/*选择 FMC 的 SDRAM 存储区域*/
    uint32_t FMC_ColumnBitsNumber; 		 /*定义 SDRAM 的列地址宽度 */
    uint32_t FMC_RowBitsNumber;			 /*定义 SDRAM 的行地址宽度 */
    uint32_t FMC_SDMemoryDataWidth;		 /*定义 SDRAM 的数据宽度 */
    uint32_t FMC_InternalBankNumber;	 /*定义 SDRAM 内部的 Bank 数目 */
    uint32_t FMC_CASLatency;			/*定义 CASLatency 的时钟个数*/
    uint32_t FMC_WriteProtection;		 /*定义是否使能写保护模式 */
    uint32_t FMC_SDClockPeriod;			 /*配置同步时钟 SDCLK 的参数*/
    uint32_t FMC_ReadBurst;				 /*是否使能突发读模式*/
    uint32_t FMC_ReadPipeDelay;			  /*定义在 CAS 个延迟后再等待多少个 HCLK 时钟才读取数据 */
    FMC_SDRAMTimingInitTypeDef* FMC_SDRAMTimingStruct; /*定义 SDRAM 的时序参数*/
} FMC_SDRAMInitTypeDef;

FMC_Bank:选择 FMC 映射的 SDRAM 存储区域,可选择存储区域 1 或 2 (FMC_Bank1/2_SDRAM)。

FMC_ColumnBitsNumber:设置要控制的 SDRAM 的列地址宽度,可选择 8-11 (FMC_ColumnBits_Number_8/9/10/11b)。

FMC_RowBitsNumber:设置要控制的 SDRAM 的行地址宽度,可选择设置成 11-13 (FMC_RowBits_Number_11/12/13b)。

FMC_SDMemoryDataWidth:设置要控制的 SDRAM 的数据宽度,可选择设置成 8、 16 或 32 位(FMC_SDMemory_Width_8/16/32b)。

FMC_InternalBankNumber:设置要控制的 SDRAM 的内部 Bank 数目,可选择设置成 2 或 4 个 Bank 数目(FMC_InternalBank_Number_2/4),请注意区分这个结构体成员与 FMC_Bank 的区别。

FMC_CASLatency:设置 CASLatency 即 CL 的时钟数目,可选择设置为 1、 2 或 3 个时钟周期(FMC_CAS_Latency_1/2/3)。

FMC_WriteProtection:设置是否使能写保护模式,如果使能了写保护则不能向 SDRAM 写入数据,正常使用都是禁止写保护的。

FMC_SDClockPeriod:设置 FMC 与外部 SDRAM 通讯时的同步时钟参数,可以设置成 STM32 的HCLK 时 钟 频 率 的 1/2 、 1/3 或 禁 止 输 出 时 钟 (FMC_SDClock_Period_2/3 或FMC_SDClock_Disable)。

FMC_ReadBurst:设置是否使能突发读取模式,禁止时等效于 BL=1,使能时 BL 的值等于模式寄存器中的配置。

FMC_ReadPipeDelay:配置在 CASLatency 个时钟周期后,再等待多少个 HCLK 时钟周期才进行数据采样,在确保正确的前提下,这个值设置为越短越好,可选择设置的参数值为 0、1 或 2 个 HCLK 时钟周期(FMC_ReadPipe_Delay_0/1/2)。

FMC_SDRAMTimingStruct:上面已经学习过了,这里不做赘述。

c、SDRAM命令结构体

了解了SDRAM的时序结构体和初始化结构体后,还有一个比较重要的结构体需要了解,在控制SDRAM时,需要发送各种命令,通过向FMC的命令模式寄存器FMC_SDCMR写入控制参数,就可以向外发送命令,这里了解一下FMC_SDRAMCommandTypeDef结构体

typedef struct
{
	uint32_t FMC_CommandMode;				/*要发送的命令 */
	uint32_t FMC_CommandTarget;				/*目标存储器区域 */
	uint32_t FMC_AutoRefreshNumber;			 /*若发送的是自动刷新命令,此处为发送的刷新次数,其它命令时无效 */
	uint32_t FMC_ModeRegisterDefinition;	 /*若发送的是加载模式寄存器命令,此处为要写入 SDRAM 模式寄存器的参数 */
} FMC_SDRAMCommandTypeDef;

FMC_CommandMode:配置将要发送的命令,具体命令参数如下表:

命令说明
FMC_Command_Mode_normal正常模式命令
FMC_Command_Mode_CLK_Enabled使能 CLK 命令
FMC_Command_Mode_PALL对所有 Bank 预充电命令
FMC_Command_Mode_AutoRefresh自动刷新命令
FMC_Command_Mode_LoadMode加载模式寄存器命令
FMC_Command_Mode_Selfrefresh自我刷新命令
FMC_Command_Mode_PowerDown掉电命令

FMC_CommandTarget:选择需要控制的FMC存储区域,可选为存储区1或者2(FMC_Command_Target_bank1/2)。

FMC_AutoRefreshNumber:当需要连续多次发送“自动刷新”命令时,配置此项可控制发送次数,可选参数值为1-16。如果发送的是其他命令时,此项无效。

FMC_ModeRegisterDefinition:此项对应的是SDRAM的模式寄存器,发送加载模式寄存器命令时,此项会通过地址线发送到SDRAM的模式寄存器中。

以上三个结构体成员配置完成后,就可以调用库函数FMC_SDRAMCmdConfig把这些参数写入到FMC_SDCMR寄存器中,之后FMC会自动发送响应的命令了。

OK,关于SDRAM和FMC的相关内容就先学习到这里,下节就开始实战了,相关的参数配置等到实战的时候在做总结。
或者2(FMC_Command_Target_bank1/2)。

FMC_AutoRefreshNumber:当需要连续多次发送“自动刷新”命令时,配置此项可控制发送次数,可选参数值为1-16。如果发送的是其他命令时,此项无效。

FMC_ModeRegisterDefinition:此项对应的是SDRAM的模式寄存器,发送加载模式寄存器命令时,此项会通过地址线发送到SDRAM的模式寄存器中。

以上三个结构体成员配置完成后,就可以调用库函数FMC_SDRAMCmdConfig把这些参数写入到FMC_SDCMR寄存器中,之后FMC会自动发送响应的命令了。

OK,关于SDRAM和FMC的相关内容就先学习到这里,下节就开始实战了,相关的参数配置等到实战的时候在做总结。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(5)将固件加载到没有ArduPilot固件的主板上

文章目录 前言 5.1 下载驱动程序和烧录工具 5.2 下载ArduPilot固件 5.3 使用测试版和开发版 5.3.1 测试版 5.3.2 最新开发版本 5.4 将固件上传到自动驾驶仪 5.5 替代方法 5.6 将固件加载到带有外部闪存的主板上 前言 ArduPilot 的最新版本(Copter-3.6, Pl…

使用JavaScript实现页面滑动切换效果

使用JavaScript实现页面滑动切换效果 在现代Web页面设计中,页面滑动切换效果已经成为了一种常见的设计要求,能够提升用户体验,增加页面的交互性。本文将通过JavaScript来实现这一效果。 首先,我们需要在HTML中添加一些基础结构和…

Object.assign详解

一、Object.assign是什么? Object.assign( )方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。 二、用法 Object.assign(target, ...sources) 参数:target ——>目标对象 source ——>源对象 返回值:…

HCIP VRRP技术

一、VRRP概述 VRRP(Virtual Router Pedundancy Protocol)虚拟路由器冗余协议,既能够实现网关的备份,又能够解决多个网关之间互相冲突的问题,从而提高网络可靠性。 局域网中的用户的终端通常采用配置一个默认网关的形…

【枚举+推式子】牛客小白月赛 63 E

登录—专业IT笔试面试备考平台_牛客网 题意: 思路: 首先是个计数问题,考虑组合数学 组合数学就是在考虑枚举所有包含1和n的区间 这个典中典就是枚举1和n的位置然后算贡献 双指针超时,考虑推式子: Code&#xff1a…

【Rust】Rust学习 第七章使用包、Crate和模块管理不断增长的项目

目前为止,我们编写的程序都在一个文件的一个模块中。伴随着项目的增长,你可以通过将代码分解为多个模块和多个文件来组织代码。一个包可以包含多个二进制 crate 项和一个可选的 crate 库。伴随着包的增长,你可以将包中的部分代码提取出来&…

目标检测YOLOv3基于DarkNet53模型测试-笔记

目标检测YOLOv3基于DarkNet53模型测试-笔记 预测和试测结果: 预测代码如下所示: testInsects.py #YOLOv3网模型测试-单图片文件测试并显示测试结果 import time import os import paddle import numpy as np import cv2 import random from PIL impor…

拓扑布局和建立小型网络

练习 2.6.1:拓扑布局和建立小型网络 地址表 本实验不包括地址表。 拓扑图 学习目标 正确识别网络中使用的电缆物理连接点对点交换网络验证每个网络的基本连通性 简介: 许多网络问题都可以在网络的物理层解决。因此,必须清楚了解网络连接…

光致发光二极管光源——荧光效率检测系统

发光二极管(LED)光源已经逐步地取代传统光源,并在生产和生活中得以广泛应用。荧光粉在LED照明设备中起到了至关重要的作用,其功能为将转换芯片所产生的紫外或者蓝光,发射出目标颜色的光。近年来,人们为了提…

分布式 - 消息队列Kafka:Kafka消费者分区再均衡(Rebalance)

文章目录 01. Kafka 消费者分区再均衡是什么?02. Kafka 消费者分区再均衡的触发条件?03. Kafka 消费者分区再均衡的过程?04. Kafka 如何判定消费者已经死亡?05. Kafka 如何避免消费者的分区再均衡?06. Kafka 消费者分区再均衡有什…

解决MySQL与Redis缓存一致性的问题

背景 考试系统中,教师会在后台发布一场考试,考试会存储在MySQL和Redis里面,考试有时候是会出错的,我们需要后台修改,如果多个教师在后台并发修改(概率不大),可能会出现数据库缓存不…

企业中商业智能BI,常见的工具和技术

商业智能(Business Intelligence,简称BI)数据可视化是通过使用图表、图形和其他可视化工具来呈现和解释商业数据的过程。它旨在帮助组织更好地理解和分析他们的数据,从而做出更明智的商业决策。 常见的商业智能数据可视化工具和技…

【二分+贪心】CF1622 C

Problem - 1622C - Codeforces 题意: 思路: 首先,观察样例可知,肯定是把原本的最小值减到某个值,然后再复制几次 复制的时候肯定是从大到小复制 那把最小值减到哪个值是不确定的,考虑枚举这个值&#x…

预测知识 | 神经网络、机器学习、深度学习

预测知识 | 预测技术流程及模型评价 目录 预测知识 | 预测技术流程及模型评价神经网络机器学习深度学习参考资料 神经网络 神经网络(neural network)是机器学习的一个重要分支,也是深度学习的核心算法。神经网络的名字和结构,源自…

实例036 使窗体标题栏文字右对齐

实例说明 窗口标题栏中的文字是窗口的重要说明,该文字可以标示窗口的功能、状态或名称等信息,一般该文字是居左显示的,在本例中设计一个标题栏文字右对齐的窗口。本实例运行结果如图1.36所示。 技术要点 在C# 2.0中实现这一功能非常容易&am…

Qt应用开发(基础篇)——拆分器窗口 QSplitter QSplitterHandle

一、前言 QSplitter继承于QFrame,QFrame继承于QWidget,是Qt的一个部件容器工具类。 框架类QFrame介绍 QSplitter拆分器,用户通过拖动子部件之间的边界来控制子部件的大小,在应用开发中数据分模块展示、图片展示等场景下使用。 二、…

第三节:在WORD为应用主窗口下关闭EXCEL的操作(1)

【分享成果,随喜正能量】夏日里的遗憾,一定都会被秋风温柔化解。吃素不难,难于不肯捨贪口腹之心。若不贪口腹,有何吃素之不便乎。虽吃华素,不吃素日,亦须少吃。以一切物类,皆是贪生怕死&#xf…

最强自动化测试框架Playwright(11)- 录制视频

视频 使用playwright,您可以录制测试视频。 录制视频 视频在测试结束时在浏览器上下文关闭时保存。如果手动创建浏览器上下文,请确保等待 browser_context.close()。 context browser.new_context(record_video_dir"vid…

机器学习基础08-回归算法矩阵分析(基于波士顿房价(Boston House Price)数据集)

回归算法通常涉及到使用矩阵来表示数据和模型参数。线性回归是最常见的回归算法之一,它可以用矩阵形式来表示。 考虑一个简单的线性回归模型: y m x b y mx b ymxb,其中 y y y 是因变量, x x x 是自变量, m m m 是…

基于 JMeter API 开发性能测试平台

目录 背景: 常用的 JMeter 类和功能的解释: JMeter 编写性能测试脚本的大致流程示意图: 源码实现方式: (1) 环境初始化 (2) 环境初始化 (3) 创建测试计划 (4) 创建 ThreadGroup (5) 创建循环控制器 (6) 创建 Sampler (…