【STM32】HAL库 STM32CubeMX教程十五---FMC-SDRAM(一)

前言:
本系列教程将HAL库与STM32CubeMX结合在一起讲解,使您可以更快速的学会各个模块的使用

本文 1首先讲解什么是FMC及SDRAM,W9825G6KH芯片原理,2基于CubeMx创建工程 3 对HAL库FMC函数进行讲解,4例程详解

所用工具:

1、芯片: STM32H743II

2、STM32CubeMx软件V6.4.0

3、IDE: MDK-Keil5软件

4、STM3H7xxHAL库

5、W9825G6KH

知识概括:

通过本篇博客您将学到:

SDRAM+FMC的基本原理

STM32CubeMX创建FMC-SDRAM例程

HAL库FMC函数库

【STM32】HAL库 STM32CubeMX教程十五—FMC-SDRAM(二)

在说FMC之前,我们得先了解一下SDRAM,听到SDRAM你可能不知道是什么,但是一说RAM,你就知道了:随机存取存储器(Random Access Memory)就是内存嘛,那SDRAM也就是内存了, 但是多了两个字母,多了那些功能呢,我们下面一一讲解:

RAM

随机存取存储器(英语:Random Access Memory,缩写:RAM),也叫主存,是与CPU直接交换数据的内部存储器。它可以随时读和写数据(刷新时除外),而且速度很快,通常作为操作系统或其他正在运行中的程序的临时数据存储介质。RAM工作时可以随时从任何一个指定的地址写入(存入)或读出(取出)信息。它与ROM的最大区别是数据的易失性,即一旦断电所存储的数据将随之丢失。

RAM在计算机和数字系统中用来暂时存储程序、数据和中间结果。

像我们手机经常说8GB+256GB  这个8 就是8GB的RAM 就是程序数据的存储,
那么RAM越大,能存的东西就越多,你的手机可运行的后台软件就会多一些,
当然实际情况还会受到很多因素的影响。我们要知道的是RAM就是内存

在这里插入图片描述

随机存取

RAM既然叫随机内存存储器,那么随即内存是什么意思呢?

所谓“随机存取”,指的是当存储器中的数据被读取或写入时,所需要的时间与这段信息所在的位置或所写入的位置无关。相对的,读取或写入顺序访问(Sequential Access)存储设备中的信息时,其所需要的时间与位置就会有关系。它主要用来存放操作系统、各种应用程序、数据等。

也就是处理器读写RAM的任意一个地址数据,所用的时间是一样的,这个叫随机存取

DRAM和SRAM

RAM根据存储单元的工作原理不同,分为静态RAM和动态RAM

静态随机存储器(SRAM)

静态存储单元是在静态触发器的基础上附加门控管而构成的。因此,它是靠触发器的自保功能存储数据的。“静态”是指SRAM存放的信息在不停电的情况下能长时间保留,状态稳定,不需外加刷新电路,从而简化了外部电路设计。但由于SRAM的基本存储电路中所含晶体管较多,故集成度较低,且功耗较大。

SRAM 的存储单元以锁存器来存储数据,种电路结构不需要定时刷新充电,就能保持状态
在这里插入图片描述

动态随机存储器(DRAM)

DRAM利用电容存储电荷的原理保存信息,电路简单,集成度高。主要的作用原理是利用电容内存储电荷的多寡来代表一个二进制比特(bit)是1还是0。,有电荷代表 1,无电荷代表 0,由于任何电容都存在漏电,因此,当电容存储有电荷时,过一段时间由于电容放电会导致电荷流失,使保存信息丢失。解决的办法是每隔一定时间(一般为2ms)须对DRAM进行读出和再写入,使原处于逻辑电平“l”的电容上所泄放的电荷又得到补充,原处于电平“0”的电容仍保持“0”,这个过程叫DRAM的刷新

在这里插入图片描述

DRAM与SRAM相比具有集成度高、功耗低、价格便宜等优点,所以在大容量存储器中普遍采用。 DRAM的缺点是需要刷新逻辑电路,且刷新操作时不能进行正常读,写操作。

在这里插入图片描述

在这里,你只需要知道三点:

  • 1.SRAM只要有电,其中的数据就不会有变化。加电情况下,不需要一直刷新,数据不会丢失
  • 2.DRAM,动态随机存取存储器,需要不断的刷新,才能保存数据,且刷新操作时不能进行正常读,写操作
  • 3.SRAM由于太贵了,所以虽然DRAM需要刷新,但是大部分存储还是采用DRAM

DRAM可以分为同步和异步两种,这两种方式根据通讯时是否需要使用时钟信号来区分。

下图是一种利用时钟进行同步的通讯时序,它在时钟的上升沿表示有效数据,也就是SDRAM
在这里插入图片描述

SDRAM

同步动态随机存取内存(synchronous dynamic random-access memory,简称SDRAM)是有一个同步接口的动态随机存取内存(DRAM)。通常DRAM是有一个异步接口的,这样它可以随时响应控制输入的变化。而SDRAM有一个同步接口,在响应控制输入前会等待一个时钟信号,这样就能和计算机的系统总线同步。

也就是SDRAM加上了一个同步的时钟信号线,所有的读写操作都是跟着这个时钟信号走的,跟CPU通信和交互有了很大的提高 提高了可操作性 而目前市面上使用的RAM基本都是SDRAM

关于RAM这部分及讨论到这里,如果想深入了解请参看:
《SDRAM、DRAM及DDR FLASH ROM概念详解》


关于FMC的原理讲解,请参看这两篇文章,已经说的很详细了

STM32 FSMC/FMC原理保姆级讲解(一)

STM32 FSMC/FMC原理保姆级讲解(二)

STM32 FMC原理详解


接下来,我们来讨论SDRAM的芯片原理及接口时序

我们用的SDRAM芯片为W9825G6KH,其内部框图和原理图如下:

在这里插入图片描述

在这里插入图片描述

  • FMC_D0~15:16位数据线;

  • FMC_A0~12:13位地址线,行地址与列地址是公用的,作为行地址时使用了0~12位,作为列地址时使用了0~8位;

  • FMC_SDNWE:低电平时写,高电平时读;

  • FMC_SDNCAS:列地址选通信号,低电平有效;

  • FMC_SDNRAS:行地址选通信号,低电平有效;

  • FMC_SDNE0:片选信号,低电平有效;

  • FMC_BA0~1:Bank选择信号,两位对应4个区域

  • FMC_SDCKE0:时钟使能信号;

  • FMC_SDCLK:时钟信号;

  • FMC_NBL0~1:写访问的输出字节屏蔽,数据掩码,下面有介绍

在这里插入图片描述

上面的引脚说明,请认真阅读下,都很简单

SDRAM存储单元结构

SDRAM 的存储单元(称之为:BANK)是以阵列的形式排列的,
在这里插入图片描述
对于这个存储阵列,我们可以将其看成是一个表格,只需要给定行地址(Row)和列地址(Column),就可以确定其唯一位置,这就是 SDRAM 寻址的基本原理。而一个 SDRAM 芯片内部,一般又有 4 个
这样的存储单元(BANK),所以,在 SDRAM 内部寻址的时候,先指定 BANK 号和行地址,
然后再指定列地址,就可以查找到目标地址。从而完成对目标存储地址数据的读写 。

SDRAM 的存储结构示意图,如下图所示

在这里插入图片描述
我们来说一下寻址方式:

  1. 寻址的时候,首先 RAS 信号为低电平,选通行地址.
  2. 地址线 A0~A12 所表示的地址,会被传输并锁存到行地址译码器里面,行地址就确定了
  3. 同时BANK地址线上面的BS0,BS1所表示的BANK地址,也会被锁存 ,选中对应的BANK 两位二进制就是00~11 对应BANK0~BANK3
  4. 然后,CAS 信号为低电平,选通列地址
  5. 地址线 A0~A12 所表示的地址,会被传输并锁存到列地址译码器里面,作为列地址

这样,就完成了一次寻址。

W9825G6KH 的存储结构为:行地址:8192 个;列地址:512 个;BANK 数:4 个;位宽:
16 位;这样,整个芯片的容量为:81925124*16=32M 字节。

数据输入输出

在这里插入图片描述
若是写 SDRAM 内容,寻址完成后,DQ[15:0]数据线的数据经过输入数据寄存器(内部框图5),然后传输到存储器阵列中,数据被保存;

若是读 SDRAM 内容,寻址完成后,DQ[15:0]数据线的数据经过输出数据寄存器(内部框图5),然后传输到存储器阵列中,数据被读出;

数据掩码

我们使用的SDRAM 存储阵列的“数据宽度”是 16 位(即数据线的数量),而SDRAM 的位宽,可以达到 32 位,也就是最多有 32 条数据线,在与 SDRAM进行数据通讯时,我们可能会以:8 位、16 位、24 位和 32 位等宽度来读写数据 。
也就是说 16位的数据线并不是所有时候都同时使用的,而且在传输低宽度数据的时候,我们不希望其它数据线表示的数据被录入。如传输 8 位数据的时候,我们只需要 DQ[7:0]表示的数据,而 DQ[15:8]数据线表示的数据必须忽略,否则会修改非目标存储空间的内容。

这个时候就到数据掩码(DQM)线来控制了,每一个数据掩码线,对应 8 个位的数据,低电平表示对应数据位有效,高电平表示对应数据位无效。如“DQM0(LDQM)”为低电平,“DQM1(HDQM)”为高电平时,数据线 DQ[7:0]表示的数据有效,而 DQ[15:8]表示的数据无效。

在STM32中是FMC_NBL0~1 为 对应DQM0/1

控制命令

我们列一些常用的控制指令
在这里插入图片描述

  1. NO-Operation NO-Operation : 即空操作命令,用于选中 SDRAM,防止 SDRAM 接受错误的命令,为接下来的命令发送做准备。
  2. Active : 即激活命令,该命令必须在读写操作之前被发送,用于设置所需要的 Bank 和
    行地址(同时设置这 2 个地址),Bank 地址由 BA0,BA1指定,行地址由 A0~A12 指定

在这里插入图片描述

  1. Read/Write,即读/写命令,行地址通过“行有效”命令确定后,就要对列地址进行寻址了,,再发送列地址就可以完成对 SDRAM的寻址,并进行读写操作了,列地址由 A0~A9 指定。 WE 引脚表示读/写方向,WE 为低电平时表示写,高电平时表示读, 读/写命令和列地址的发送,是通过一次传输完成的

在这里插入图片描述

  1. Precharge,预充电指令,用于关闭 Bank 中所打开的行地址。由于 SDRAM 的寻址具有独占性,所以在进行完读写操作后,如果要对同一 Bank 的另一行进行寻址,就要将原来有效(ACTIVE)的行关闭,重新发送行/列地址。Bank 关闭现有工作行,准备打开新行的操作就叫做预充电(Precharge)

在这里插入图片描述

预充电命令可以通过独立的命令发送,也可以在每次发送读/写命令的时候,使用地址线A10,来设置自动预充电。在发送读/写命令的时候,若 A10 为高电平时,在读/写操作完成后,所有 Bank 都预充
这样,下次读/写操作之前,就不需要再发预充电命令了,A10 为低电平时,使用 BA 线选择要预充电的 Bank

  1. Refresh,即刷新命令,用于刷新一行数据。SDRAM 里面存储的数据,需要不断的进行刷新操作才能保留住,因此刷新命令对于 SDRAM 来说,尤为重要。预充电命令和刷新命令,都可以实现对 SDRAM 数据的刷新,不过预充电仅对当前打开的行有效(仅刷新当前行),而刷新命令,则可以依次对所有的行进行刷新操作。

刷新操作分为两种:“自动刷新”(Auto Refresh)与“自我刷新”(Self Refresh),发送命令后 CKE 时钟为有效时(低电平),使用自动刷新操作,否则使用自我刷新操作。不论是何种刷新方式,都不需要外部提供行地址信息,因为这是一个内部的自动操作

自动刷新:SDRAM 内部有一个行地址生成器(也称刷新计数器)用来自动的依次生成要刷新的行地址。由于刷新是针对一行中的所有存储体进行,所以无需列寻址。刷新涉及到所有Bank,因此在刷新过程中,所有 Bank 都停止工作,而每次刷新所占用的时间为 9 个时钟周期(PC133 标准),之后就可进入正常的工作状态,也就是说在这 9 个时钟期间内,所有工作指令只能等待而无法执行。刷新操作必须不停的执行,完成一次所有行的刷新所需要的时间,称为刷新周期,一般为 64ms。显然,刷新操作肯定会对 SDRAM 的性能造成影响,但这是没办法的事情,也是 DRAM 相对于 SRAM(静态内存,无需刷新仍能保留数据)取得成本优势的同时所付出的代价。
自我刷新:主要用于休眠模式低功耗状态下的数据保存,在发出自动刷新命令时,将 CKE置于无效状态(低电平),就进入了自我刷新模式,此时不再依靠系统时钟工作,而是根据内部的时钟进行刷新操作。在自我刷新期间除了 CKE 之外的所有外部信号都是无效的(无需外部提供刷新指令),只有重新使 CKE 有效(高电平)才能退出自刷新模式并进入正常操作状态。

SDRAM突发模式

SDRAM的读/写操作,都是一次对一个存储单元进行寻址,如果要连续读/写就还要对当前存储
单元的下一个单元进行寻址,也就是要不断的发送列地址与读/写命令(同一行数据行地址不变,所以不用再对行寻址)。它占用了大量的内存控制资源,在数据进行连续传输时无法输入新的命令,效率很低。 我们的IO口时序都被用到了发送地址上。

为此,出现了突发传输技术,只要指定起始列地址与突发长度,内存就会依次地自动对后面相应数量的存储单元进行读/写操作而不再需要控制器连续地提供列地址。这样,除了第一次行列数据的传输需要若干个周期外,其后每个数据只需一个周期的即可获得。

突发模式也就是指在同一行中相邻的存储单元连续进行数据传输的方式
只要指定起始列地址与突发长度,寻址与数据的读取就会自动进行,而只要控制好两段突发读取命令的间隔周期 即可做到连续的突发传输 大大减少了我们读写数据的时间。

突发长度

Burst Length 译为突发长度,简称 BL,每次发送完一次行列地址,连续传输存储单元(列)的数量就是突发长度

BL 可设为 1、2、4、8,常见的设定是 4 和 8。若传输时实际需要数据长度小于设定的 BL 值,则
调用“突发停止”(BURST TERMINATE) 命令结束传输

突发间隔

突发模式分为顺序 (Sequential) 与间隔 (Interleaved) 两种。在顺序方式中,操作按地址的顺序连续执行,如果是间隔模式,则操作地址是跳跃的。跳跃访问的方式比较乱,不太符合思维习惯,我们一般用顺序模式。顺序访问模式时按照“0-1-2-3-4-5-6-7”的地址序列访问。


关于SDRAM 的介绍就先到这里,下面我们来看FMC。

FMC通俗讲解

STM32 FMC原理详解

既然我们知道FMC是可以方便的跟内存存储,那么到底方便到什么地方了呢?

我们用DRAM做一个最简单的举例,让你最直观的了解FMC的用处和便捷之处。

首先我们想一下,你想要在自己的电脑中查找一个文档文件的数据 ,然后拷到U盘里,需要的步骤是什么呢?

  1. 找到该文档在电脑中的位置(地址)
  2. 复制该文档(数据)
  3. 将文档粘贴到U盘中(数据传输)

在这里插入图片描述

一共需要三步,而我们的DRAM和NOR FLASH 都是存储器,把它们想成电脑 ,U盘是我们的STM32

单片机跟外部存储器通信,也需要知道数据的地址(电脑中的位置),然后把数据的内容传递(复制粘贴)过来。 那这样的话,存储器就需要地址传输线数据传输线,还要加上一些控制时序引脚 比方说复位 写数据 读数据 等等

  • 1、地址线:是用来传输地址信息用的。举个简单的例子:cpu在内存或硬盘里面寻找一个数据时,先通过地址线找到地址,然后再通过数据线将数据取出来。 如果有32根.就可以访问2的32次方的字节,也就是4GB。

  • 2、数据线(data cable),来传递数据或通信。通俗点说,就是单片机发送指令给存储器,和存储器发送数据给单片机这两个功能

我们来看一个DRAM存储器的原理图:
在这里插入图片描述

图中A0 ~ 18为地址线,总共19根地址线(即2^19=512K,1K=1024);DQ0 ~ 15为数据线,总共16根数据线。CEn是芯片使能信号,低电平有效;OEn是输出使能信号,低电平有效;WEn是写使能信号,低电平有效;BLEnBHEn分别是高字节控制和低字节控制信号;


假设我们不用FSMC,直接跟DRAM通信,那么代码应该这样写:

CEn=0;
WEn=0;
....
省略的控制时序
//确定地址线
A0=1;
A1=0;
A2=1;
A3=1;
A4=1;
A5=0;
A6=1;
A7=1;
A8=1;
A9=0;
A10=1;
A11=1;
A12=1;
A13=0;
A14=1;
A15=1;
A16=1;
A17=1;
A18=1;

//地址线确定好了,假设是写数据,那么就要开始发送数据了
CEn=0;
....
省略的控制时序
//数据总线发送数据
D0=1;
D1=0;
D2=1;
D3=1;
D4=1;
D5=0;
D6=1;
D7=1;
D8=1;
D9=0;
D10=1;
D11=1;
D12=1;
D13=0;
D14=1;
D15=1;

....
省略的控制时序

通过上面最基本的演示,你就会发现,正常通过IO口的时序逻辑跟DRAM通信是非常繁琐的

那么有没有简单的方法呢? 有的! STM32自带的FSMC功能,就是专门为这类存储器设计的,在STM32上,有一些引脚被专门设计成地址线,还有一些被专门设计成数据线,还有一些被设计成控制线,然后这些地址线和数据线对应着固定的地址,只要外部的DRAM等存储器将对应的数据线连接到STM32这些对应的引脚上,引脚功能设置为复用模式,通过配置FSMC ,你可以直接给上面那个固定的地址赋值 ,其他操作STM32都会自动给你完成,就可以把数据存储到SRAM中!


我们来看下使用FSMC读写数据的流程:

定义FSMC数据线对应的地址


//FSMC_Bank1_NORSRAM  
#define      FSMC_Addr_DATA        ( ( uint32_t ) 0x60020000 )

如果要写数据,直接给这个地址赋值就可以:

/**
  * @brief  SRAM写入数据
  * @param  usData :要写入的数据
  * @retval 无
  */	
 void SRAM_Write_Data ( uint16_t usData )
{
    
    
	* ( __IO uint16_t * ) ( FSMC_Addr_DATA ) = usData;
	
}

如果要从存储器中读取数据,直接读取这个地址就可以:


/**
  * @brief  从SRAM读取数据
  * @param  无
  * @retval 读取到的数据
  */	
 uint16_t SRAM_Read_Data ( void )
{
    
    
	return ( * ( __IO uint16_t * ) ( FSMC_Addr_DATA ) );	
}

uint16_t usR=0;

usR = SRAM_Read_Data (); 	/* READ DATA*/

是不是傻瓜式操作,极大的方便了我们的程序编写,其实这就好比软件IIC SPI 跟硬件IIC SPI 一样 我们不需要关心协议本身的时序,这些都由STM32内部来设置,我们只需要发送和读取数据就可以,STM32跟外部存储器通信,使用硬件方式就是FMC,这样就很容易理解了


下面关于FMC的讲解,为了缩减篇幅,请参看:

我们来看一些基本的配置:

下面是STM32 FMC的框图具体功能都有写:
在这里插入图片描述
在这里插入图片描述
FMC地址框图
在这里插入图片描述
通过FMC地址框图我们可以看到STM32对于SDRAM分配了两个bank空间 Bank1 和 Bank2 ,这里的 Bank 与 SDRAM 芯片内部的Bank 是不一样的,这是FMC内部有2个物理Bank地址的意思,每个BANK都可以接一个SDRAM,可以理解为FMC支持连接2个SDRAM芯片, 实际使用的时候看下具体的接线选择是BANK1还是BANK2,

MCU通过不同的片选信号SDNE0和SDNE1来选择具体使用哪个片外RAM 通过SDCKE0和SDCKE1来确定使能那个BANK的时钟

BANK0对应的存储区域 1 的地址范围是 0xC000 0000-0xCFFF FFFF,
而BANK1 对应的存储区域 2 的地址范围是 0xD000 0000- 0xDFFF FFFF。

当程序里控制内核访问这些地址的存储空间时,FMC 外设会即会产生对应的时序,对它外接的 SDRAM 芯片进行读写

在这里插入图片描述

我这里使用的是正点原子的阿波罗,外部SDRAM如下:
在这里插入图片描述
具体的引脚接线如下:

A[0:12]接 FMC_A[0:12]
BA[0:1]接 FMC_BA[0:1]
D[0:15]接 FMC_D[0:15]
CKE 接 FMC_SDCKE0
CLK 接 FMC_SDCLK

UDQM 接 FMC_NBL1
LDQM 接 FMC_NBL0

WE 接 FMC_SDNWE s
CAS 接 FMC_SDNCAS
RAS 接 FMC_SDNRAS
CS 接 FMC_SDNE0

基于CubeMx的讲解

1设置RCC时钟

在这里插入图片描述
设置高速外部时钟HSE 选择外部时钟源

对于H7系列,可以选择是否使能I-cache和D-cache高速缓存,以及是否使能MPU
在这里插入图片描述

2.FMC设置

在这里插入图片描述

  • Clock and chip enable:配置时钟使能和片选引脚,很明显我们使用的 CKE 接 FMC_SDCKE0,CS 接 FMC_SDNE0 所以选择第一个bank
  • internal bank numbers SDRAM有几个存储单元BANK 我们用的芯片有4 个这样的存储单元(BANK)
  • Address: 地址线位数 - FMC_D0~15:16位数据线
  • Data: 数据线位数 - FMC_A0~12:13位地址线
  • Byte Enable是否使能数据掩码,这里设置使能

然后我们通过GPIO Settings 看下设置的数据线,地址线,控制线跟我们手上的板子是否一致,因为CubeMx是默认配置的,但是可能有多个IO口引脚都可以复用成同一个功能,F746的芯片手册中,PC3、PH2都可以通过复用功能映射成 FMC_SDCK0 信号
所以如果你自己连接的引脚有不一样的地方记得修改正确

在这里插入图片描述

这里我们说一个查看复用功能的小技巧

比方说我们想看FMC_SDCKE0片选信号能设置到哪些引脚,按住Ctrl键然后点击PC3 就可以看到对应的引脚在变黑闪烁,这些引脚都是可以配置成FMC_SDCKE0的

像其他的串口,ADC,IIC等复用,都可以采用此方式。
在这里插入图片描述

FMC时钟

点击Clock Configuration

  • 设置HSE为25Mhz
  • 系统时钟来源选择PLL锁相环
  • 系统时钟哪里填写400,然后按回车,CubemMx会自动配置好

在这里插入图片描述

FMC 外设挂载在 AHB3 总线上,时钟信号来自于 HCLK(默认 200MHz),控制器的时钟输出就是
由它分频得到。还可以可以选择如下几种时钟源 HCLK3,PLL1Q,PLL2R 和 PER_CK

我们这里直接使用 HCLK3,配置 STM32H7 的主频为 400MHz 的时候,HCLK3 输出的 200MHz,这个速度是 FMC 支持的最高时钟

在这里插入图片描述

在SDRAM中,SDRAM 控制器的 FMC_SDCLK 引脚输出时钟频率,用于与 SDRAM 芯片进
行同步通讯,它的时钟频率可通过 FMC_SDCR1 寄存器的 SDCLK 位配置,可以配置为 HCLK 的
1/2 或 1/3,也就是说,与 SDRAM 通讯的同步时钟最高频率为 100MHz。

下面我们来看下SDRAM的参数配置:

在这里插入图片描述

  • Bank选择的是SDRAM的bank1还是bank2 上面Clock and chip enable设置了这里就会自动选择,我们用的是BANK1,这里也是BANK1

  • Number of column address bits 列地址位数 W9825G6KH 有 9 位列地址

  • Number of row address bits 行地址位数 W9825G6KH 有 13 位行地址

  • CAS latency: 指列地址选通延迟,简称 CL,在发出读命令 (命令同时包含列地址) 后,需要等待几个时钟周期数据线 Data才会输出有效数据,这之间的等待时间就是指 CL,CL一般可以设置为 2 或 3 个FMC时钟周期 这里我们设置为两个时钟周期

CL 只是针对读命令时的数据延时,在写命令是不需要这个延时的,发出写命令时可同时发送要
写入的数据

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

  • SDRAM common clock 设置 FMC 与外部 SDRAM 通讯时的时钟频率,可以设置成 STM32的 HCLK 时钟频率的 1/2、1/3 或禁止输出时钟 (异步RAM不需要时钟)
    这里我们设置为2分频,就是1/2 SDRAM的时钟就是100Mhz
    (FMC_SDRAM_CLOCK_PERIOD_2/3 或FMC_SDRAM_CLOCK_DISABLE)

  • SDRAM common burst read 设置是否使能突发读取模式,禁止时等效于 BL=1,使能时 BL 的值等于模式寄
    存器中的配置

  • SDRAM common read pipe delay 于配置在 CASLatency 地址选通延迟后,再等待多少个 HCLK 时钟周期才进行数据采样,在确保正确的前提下,这个值设置为越短越好,可选择设置的参数值为 0、 1 或 2 个 HCLK 时钟周期 (FMC_SDRAM_RPIPE_DELAY_0/1/2)


然后我们再来下面那些参数的配置:

  • Load mode register to active delaytRSC 加载模式寄存器命令与行有效或刷新命令之间的延迟
  • Exit self-refresh delay:tXSR 退出自我刷新到行有效命令之间的延迟
  • Self-refresh time : tRAS 自刷新周期
  • SDRAM common row cycle delay : tRC 刷新命令和激活命令之间的延迟
  • Write recovery time : tWR 写命令和预充电命令之间的延迟
  • SDRAM common row precharge delay: tRP 义预充电命令与其它命令之间的延迟
  • Row to column delay tRCD 定义行有效命令与读/写命令之间的延迟

我们查看《W9825G6KH》数据手册,即可看到对应的参数:
在这里插入图片描述

在CubeMX中点击对应参数,下面会出来对应的介绍:
在这里插入图片描述
这些参数在手册里都有详细的说明,我们看MIN最小时间就好

以tXSR,举个例子 我们SDRAM时钟为HCLK 2分频得到,为100MHZ 那么时钟周期就是 T=1/F =1/100MHz=10ns纳秒 那么tXSR最少为72ns,也就是最小要延迟8个时钟周期 所以我们设置为8

tRSC,最小为两个时钟周期tCK 所以我们设置为2

项目文件设置

在这里插入图片描述

  • 1 设置项目名称
  • 2 设置存储路径
  • 3 选择所用IDE
  • 4 选择所用固件包版本,勾选旁边的对钩会使用最新的可用版本

在这里插入图片描述

创建工程文件

然后点击GENERATE CODE 创建工程

配置下载工具
新建的工程所有配置都是默认的 我们需要自行选择下载模式,勾选上下载后复位运行

在这里插入图片描述

HAL库SDRAM函数详解

因为篇幅问题,这个我们在下一篇中讲解

【STM32】HAL库 STM32CubeMX教程十五—FMC-SDRAM(二)
请添加图片描述
请添加图片描述

猜你喜欢

转载自blog.csdn.net/as480133937/article/details/123455833