FSMC—扩展外部SRAM
一、SRAM控制原理
????????STM32控制器芯片内部有一定大小的SRAM及FLASH作为内存和程序存储空间,但当程序较大,内存和程序空间不足时,就需要在STM32芯片的外部扩展存储器了。STM32F103ZE系列芯片可以扩展外部SRAM用作内存。?
????????给STM32芯片扩展内存与给PC扩展内存的原理是一样的,只是PC上一般以内存条的形式扩展,而且内存条实质是由多个内存颗粒(即SDRAM芯片)组成的通用标准模块,而STM32扩展时,直接直接与SRAM芯片连接。
1.1 型号为IS62WV51216的SRAM芯片外观
1.2??SRAM芯片的内部功能框架
?1.3?SRAM信号线
信号线 | 类型 | 说明 |
A0-A18 | I | 地址输入 |
I/O0-I/O7 | I/O | 数据输入输出信号,低字节 |
I/O8-I/O15 | I/O | 数据输入输出信号,高字节 |
CS2 和CS1# | I | 片选信号,CS2高电平有效,CS1#低电平有 效,部分芯片只有其中一个引脚 |
OE# | I | 输出使能信号,低电平有效 |
WE# | I | 写入使能,低电平有效 |
UB# | I | 数据掩码信号Upper Byte,高位字节允许访问,低电平有效, |
LB# | I | 数据掩码信号Lower Byte,低位字节允许访问,低电平有效 |
????????SRAM的控制比较简单,只要控制信号线使能了访问,从地址线输入要访问的地址,即可从I/O数据线写入或读出数据。
1.4 SRAM的存储矩阵
?????????SRAM内部包含的存储阵列,可以把它理解成一张表格,数据就填在这张表格上。和表格查找一样,指定一个行地址和列地址,就可以精确地找到目标单元格,这是SRAM芯片寻址的基本原理。这样的每个单元格被称为存储单元,而这样的表则被称为存储矩阵。
1.5 地址译码器、列I/O及I/O数据电路
????????地址译码器把N根地址线转换成2N根信号线,每根信号线对应一行或一列存储单元,通过地址线找到具体的存储单元,实现寻址。
????????本实例中的SRAM比较小,没有列地址线,它的数据宽度为16位,即一个行地址对应2字节空间,框图中左侧的A0-A18是行址信号,18根地址线一共可以表示218=28x1024=512K行存储单元,所以它一共能访问512Kx16bits大小的空间。访问时,使用UB#或LB#线控制数据宽度。
1.6 控制电路
控制电路主要包含了片选、读写使能以及上面提到的宽度控制信号UB#和LB#。利用CS2或CS1#片选信号,可以把多个SRAM芯片组成一个大容量的内存条。OE#和WE#可以控制读写使能,防止误操作。
1.7 SRAM的读写流程
对SRAM进行读数据时,它各个信号线的时序流程如下:
无时钟线,异步通信,通过时间参数来协调通信,要求地址线通过A0-A18来告诉SRAM要读取哪一个地址的单元格。
tRC:地址线的保持时间
tDOE:读使能过了一段时间,给了读使能OE信号后多长时间,SRAM可以输出数据,且这个数据线会保持一段时间使STM32能够有时间去读取数据,给出OE信号后,数据输出的时间
tOHA:从使能信号开始以后给出数据到读取周期过程结束后,还会保持tOHA的事故华北
所以在tAA之后进行采样就可以读取到有效的数据
tAA:从给出地址之后到数据出现,也就是返回数数据的过程的时间
?对SRAM进行写数据时,它各个信号线的时序流程如下:读写时序的流程很类似,过程如下:
(1)? 主机使用地址信号线发出要访问的存储器目标地址;
(2)? 控制片选信号CS1#及CS2#使能存储器芯片;
(3)? 若是要进行读操作,则控制读使能信号OE#表示要读数据,若进行写操作则控制写使能信号WE#表示要写数据;
(4)? 使用掩码信号LB#与UB#指示要访问目标地址的高、低字节部分;
(5)? 若是读取过程,存储器会通过数据线向主机输出目标数据,若是写入过程,主要使用数据线向存储器传输目标数据。
SRAM的读写时序参数
时间参数 | IS62WV51216BLL-55ns型号要求的最短时间 | 说明 |
tRC | 55ns | 读操作周期 |
tAA | 0ns | 地址访问时间 |
tWC | 55ns | 写操作周期 |
tSA | 0ns | 地址建立时间 |
tSD | 25ns | 数据建立至写结束的时间 |
tHD | 0ns | 数据写结束后的保持时间 |
在读写时序中,有几个比较重要的时间参数,在使用STM32 控制的时候需要参考,它们的介绍见表
二、STM32的FSMC特性及架构
????????STM32F1系列芯片使用FSMC外设来管理扩展的存储器,FSMC是Flexible Static Memory Controller的缩写,译为灵活的静态存储控制器。它可以用于驱动包括SRAM、NOR FLASH以及NAND FLSAH类型的存储器,不能驱动如SDRAM这种动态的存储器,而在STM32F429系列的控制器中,它具有FMC外设,支持控制SDRAM存储器。
FSMC框图剖析
- 通讯引脚
- 存储器控制器
- 时钟控制逻辑
2.1 通讯引脚?
????????由于控制不同类型存储器的时候会有一些不同的引脚,看起来有非常多,其中地址线FSMC_A和数据线FSMC_D是所有控制器都共用的
FSMC引脚名称 | 对应SRAM引脚名 | 说明 |
FSMC_NBL[1:0] | LB#、UB# | 数据掩码信号 |
FSMC_A[18:0] | A[18:0] | 行地址线 |
FSMC_D[15:0] | I/O[15:0] | 数据线 |
FSMC_NWE | WE# | 写入使能 |
FSMC_NOE | OE# | 输出使能(读使能) |
FSMC_NE[1:4] | CE# | 片选信号 |
2.2 SRAM信号线
????????其中比较特殊的FSMC_NE是用于控制SRAM芯片的控制信号线,STM32具有FSMC_NE1/2/3/4号引脚,不同的引脚对应STM32内部不同的地址区域。
????????例如,当STM32访问0x68000000-0x6BFFFFFF地址空间时,FSMC_NE3引脚会自动设置为低电平,由于它连接到SRAM的CE#引脚,所以SRAM的片选被使能,而访问0x60000000-0x63FFFFFF地址时,FSMC_NE1会输出低电平。当使用不同的FSMC_NE引脚连接外部存储器时,STM32访问SRAM的地址不一样,从而达到控制多块SRAM芯片的目的。
2.3 存储器控制器
????????上面不同类型的引脚是连接到FSMC内部对应的存储控制器中的。NOR/PSRAM/SRAM设备使用相同的控制器,NAND/PC卡设备使用相同的控制器,不同的控制器有专用的寄存器用于配置其工作模式。
????????控制SRAM的有FSMC_BCR1/2/3/4控制寄存器、FSMC_BTR1/2/3/4片选时序寄存器以及FSMC_BWTR1/2/3/4写时序寄存器。每种寄存器都有4个,分别对应于4个不同的存储区域,各种寄存器介绍如下:
- FSMC_BCR控制寄存器可配置要控制的存储器类型、数据线宽度以及信号有效极性能参数。
- FMC_BTR时序寄存器用于配置SRAM访问时的各种时间延迟,如数据保持时间、地址保持时间等。
- FMC_BWTR写时序寄存器与FMC_BTR寄存器控制的参数类似,它专门用于控制写时序的时间参数。
2.4 时钟控制逻辑
????????FSMC外设挂载在AHB总线上,时钟信号来自于HCLK(默认72MHz),控制器的同步时钟输出就是由它分频得到。例如,NOR控制器的FSMC_CLK引脚输出的时钟,它可用于与同步类型的SRAM芯片进行同步通讯,它的时钟频率可通过FSMC_BTR寄存器的CLKDIV位配置,可以配置为HCLK的1/2或1/3,也就是说,若它与同步类型的SRAM通讯时,同步时钟最高频率为36MHz。本示例中的SRAM为异步类型的存储器,不使用同步时钟信号,所以时钟分频配置不起作用。
2.5 FSMC的地址映射?
?????????FSMC连接好外部的存储器并初始化后,就可以直接通过访问地址来读写数据。
????????FSMC访问存储器的方式与I2C EEPROM、SPI FLASH的不一样,后两种方式都需要控制I2C或SPI总线给存储器发送地址,然后获取数据;在程序里,这个地址和数据都需要分开使用不同的变量存储,并且访问时还需要使用代码控制发送读写命令。
????????而使用FSMC外接存储器时,其存储单元是映射到STM32的内部寻址空间的;在程序里,定义一个指向这些地址的指针,然后就可以通过指针直接修改该存储单元的内容,FSMC外设会自动完成数据访问过程,读写命令之类的操作不需要程序控制。
????????图中左侧的是Cortex-M3内核的存储空间分配,右侧是STM32 FSMC外设的地址映射。可以看到FSMC的NOR/PSRAM/SRAM/NAND FLASH以及PC卡的地址都在External RAM地址空间内。
????????正是因为存在这样的地址映射,使得访问FSMC控制的存储器时,就跟访问STM32的片上外设寄存器一样(片上外设的地址映射即图中左侧的“Peripheral”区域)。
????????FSMC把整个External RAM存储区域分成了4个Bank区域,并分配了地址范围及适用的存储器类型,如NOR及SRAM存储器只能使用Bank1的地址。
????????在NOR及SRAM区域,每个Bank的内部又分成了4个小块,每个小块有相应的控制引脚用于连接片选信号,如FSMC_NE[4:1]信号线可用于选择BANK1内部的4小块地址区域,当STM32访问0x68000000-0x6BFFFFFF地址空间时,会访问到Bank1的第3小块区域,相应的FSMC_NE3信号线会输出控制信号。
2.6 FSMC控制SRAM的时序?
????????FSMC外设支持输出多种不同的时序以便于控制不同的存储器,它具有ABCD四种模式,下面我们仅针对控制SRAM使用的模式A进行讲解
读时序?
当内核发出访问某个指向外部存储器地址时,FSMC外设会根据配置控制信号线产生时序访问存储器,上图中的是访问外部SRAM时FSMC外设的读写时序。
?以读时序为例,该图表示一个存储器操作周期由地址建立周期(ADDSET)、数据建立周期(DATAST)以及2个HCLK周期组成。在地址建立周期中,地址线发出要访问的地址,数据掩码信号线指示出要读取地址的高、低字节部分,片选信号使能存储器芯片;地址建立周期结束后读使能信号线发出读使能信号,接着存储器通过数据信号线把目标数据传输给FSMC,FSMC把它交给内核。
? 写时序类似,区别是它的一个存储器操作周期仅由地址建立周期(ADDSET)和数据建立周期(DATAST)组成,且在数据建立周期期间写使能信号线发出写信号,接着FSMC把数据通过数据线传输到存储器中。
写时序
当内核发出访问某个指向外部存储器地址时,FSMC外设会根据配置控制信号线产生时序访问存储器,上图中的是访问外部SRAM时FSMC外设的读写时序。
以读时序为例,该图表示一个存储器操作周期由地址建立周期(ADDSET)、数据建立
周期(DATAST)以及2 个HCLK周期组成。在地址建立周期,地址线发出要访问的地址,数据掩码信号线指示出要读取地址的高、低字节部分,片选信号使能存储器芯片;地址建
立周期结束后读使能信号线发出读使能信号,接着存储器通过数据信号线把目标数据传输
给FSMC,FSMC 把它交给内核。
写时序类似,区别是它的一个存储器操作周期仅由地址建立周期(ADDSET)和数据建
立周期(DATAST)组成,且在数据建立周期期间写使能信号线发出写信号,接着FSMC把数
据通过数据线传输到存储器中。
三、FSMC控制SRAM的相关结构体
控制FSMC使用SRAM存储器时主要是配置时序寄存器以及控制寄存器,利用ST标准库的SRAM时序结构体以及初始化结构体可以很方便地写入参数。?
- 时序结构体:FSMC_NORSRAMTimingInitTypeDef
- 初始化结构体:FSMC_NORSRAMInitTypeDef
3.1 FSMC时序结构体?
FSMC的SRAM时序结构体成员定义的都是SRAM读写时序中的各项时间参数,这些成员的的参数都与FSMC_BRT及FSMC_BWTR寄存器配置对应。
- FSMC_AddressSetupTime ?本成员设置地址建立时间,它可以被设置为0-0xF个HCLK周期数,按STM32标准库的默认配置,HCLK的时钟频率为72MHz,即一个HCLK周期为1/72微秒。
- FSMC_AddressHoldTime 本成员设置地址保持时间,它可以被设置为0-0xF个HCLK周期数。
- FSMC_DataSetupTime 本成员设置数据建立时间,它可以被设置为0-0xF个HCLK周期数。
- FSMC_BusTurnAroundDuration 本成员设置总线转换周期,在NOR FLASH存储器中,地址线与数据线可以分时复用,总线转换周期就是指总线在这两种状态间切换需要的延时,防止冲突。控制其它存储器时这个参数无效,配置为0即可。
- FSMC_CLKDivision 本成员用于设置时钟分频,它以HCLK时钟作为输入,经过FSMC_CLKDivision分频后输出到FSMC_CLK引脚作为通讯使用的同步时钟。控制其它异步通讯的存储器时这个参数无效,配置为0即可。
- FSMC_DataLatency 本成员设置数据保持时间,它表示在读取第一个数据之前要等待的周期数,该周期指同步时钟的周期,本参数仅用于同步NOR FLASH类型的存储器,控制其它类型的存储器时,本参数无效。
- FSMC_DataLatency 本成员设置数据保持时间,它表示在读取第一个数据之前要等待的周期数,该周期指同步时钟的周期,本参数仅用于同步NOR FLASH类型的存储器,控制其它类型的存储器时,本参数无效。
- FSMC_AccessMode 本成员设置存储器访问模式,不同的模式下FSMC访问存储器地址时引脚输出的时序不一样,可选FSMC_AccessMode_A/B/C/D模式。一般来说控制SRAM时使用A模式。
? 这个FSMC_NORSRAMTimingInitTypeDef 时序结构体配置的延时参数,将作为下一节的FSMC SRAM初始化结构体的一个成员。
3.2 FSMC的SRAM初始化结构体
????????FSMC初始化结构体,除最后两个成员是上一小节讲解的时序配置外,其它结构体成员的配置都对应到FSMC_BCR中的寄存器位。
可以输入的宏 | 对应的地址区域 |
FSMC_Bank1_NORSRAM1 | 0x60000000-0x63FFFFFF |
FSMC_Bank1_NORSRAM2 | 0x64000000-0x67FFFFFF |
FSMC_Bank1_NORSRAM3 | 0x68000000-0x6BFFFFFF |
FSMC_Bank1_NORSRAM4 | 0x6C000000-0x6FFFFFFF |
- FSMC_Bank本成员用于选择FSMC映射的存储区域,它的可选参数以及相应的内核地址映射范围见上面的表格
- FSMC_DataAddressMux本成员用于设置地址总线与数据总线是否复用(FSMC_DataAddressMux_Enable /Disable),在控制NOR FLASH时,可以地址总线与数据总线可以分时复用,以减少使用STM32信号线的数量。
- FSMC_MemoryType本成员用于设置要控制的存储器类型,它支持控制的存储器类型为SRAM、PSRAM以及NOR FLASH(FSMC_MemoryType_SRAM/PSRAM/NOR)
- FSMC_MemoryDataWidth?本成员用于设置要控制的存储器的数据宽度,可选择设置成8或16位(FSMC_MemoryDataWidth_8b /16b)。
- FSMC_BurstAccessMode 本成员用于设置是否使用突发访问模式(FSMC_BurstAccessMode_Enable/Disable),突发访问模式是指发送一个地址后连续访问多个数据,非突发模式下每访问一个数据都需要输入一个地址,仅在控制同步类型的存储器时才能使用突发模式。
- ??FSMC_AsynchronousWait?本成员用于设置是否使能在同步传输时使用的等待信号(FSMC_AsynchronousWait_Enable/Disable),在控制同步类型的NOR或PSRAM时,存储器可以使用FSMC_NWAIT引脚通知STM32需要等待。
- FSMC_WaitSignalPolarity 本成员用于设置等待信号的有效极性,即要求等待时,使用高电平还是低电平(FSMC_WaitSignalPolarity_High/Low)。
- FSMC_WrapMode 本成员用于设置是否支持把非对齐的AHB突发操作分割成2次线性操作(FSMC_WrapMode_Enable/Disable),该配置仅在突发模式下有效。
- FSMC_WaitSignalActive?本成员用于配置在突发传输模式时,决定存储器是在等待状态之前的一个数据周期有效还是在等待状态期间有效(FSMC_WaitSignalActive_BeforeWaitState/DuringWaitState)。
- FSMC_WriteOperation 这个成员用于设置是否写使能(FSMC_WriteOperation_ Enable /Disable),禁止写使能的话FSMC只能从存储器中读取数据,不能写入。
- FSMC_WaitSignal?本成员用于设置当存储器牌突发传输模式时,是否允许通过NWAIT信号插入等待状态(FSMC_WaitSignal_Enable/Disable)。
- FSMC_ExtendedMode?本成员用于设置是否使用扩展模式(FSMC_ExtendedMode_Enable/Disable),在非扩展模式下,对存储器读写的时序都只使用FSMC_BCR寄存器中的配置,即下面的FSMC_ReadWriteTimingStruct结构体成员;在扩展模式下,对存储器的读写时序可以分开配置,读时序使用FSMC_BCR寄存器,写时序使用FSMC_BWTR寄存器的配置,即下面的FSMC_WriteTimingStruct结构体。
- FSMC_ReadWriteTimingStruct?本成员是一个指针,赋值时使用上一小节中讲解的时序结构体FSMC_NORSRAMInitTypeDef设置,当不使用扩展模式时,读写时序都使用本成员的参数配置。
- FSMC_WriteTimingStruct?同样地,本成员也是一个时序结构体的指针,只有当使用扩展模式时,本配置才有效,它是写操作使用的时序。
四、FSMC—扩展外部SRAM
接下来对时序结构体FSMC_NORSRAMTimingInitTypeDef 赋值。在这个时序结构体配
置中,由于我们要控制的是SRAM,所以选择FSMC 为模式A,在该模式下配置FSMC 的
控制时序结构体中,实际上只有地址建立时间FSMC_AddressSetupTime(即ADDSET 的值)
以及数据建立时间FSMC_DataSetupTime(即DATAST 的值)成员的配置值是有效的,其
它SRAM没使用到的成员值全配置为0 即可。而且,这些成员值使用的单位为:1 个HCLK
的时钟周期,而HCLK 的时钟频率为72MHz,对应每个时钟周期为1/72 微秒。
FSMC 时序配置与SRAM 时序参数要求对比(读)
由上图的FSMC 时序和SRAM时序对比及SRAM时间参数要求可总结下表最右侧的计算表达式。
根据FSMC配置表达式的配置要求把时间单位1/72 微秒(即1000/72 纳秒)代入,可求得
ADDSET = 0,DATAST=1 时即可符合要求。如:
tRC=ADDSET+1+DATAST+1+2 =( 0+1+1+1+2 )*1000/72 = 69 ns > 55 ns
tDOE=DATAST+1 = (1+1)*1000/72 = 27.7 > 25 ns
不过,经实验总结出该配置在连续读取多个数据的时候会出现问题,更正确的配置为
ADDSET=0,DATAST=2,而这样的配置与写时序是一致的,下面再来列出写时序的计算
过程:
FSMC 时序配置与SRAM 时序参数要求对比(写)?
根据FSMC配置表达式的配置要求把时间单位1/72 微秒(即1000/72 纳秒)代入,可求得
ADDSET = 0,DATAST=2 时即可符合要求。如:
tWC = ADDSET+1+DATAST+1 =( 0+1+2+1 )*1000/72 = 55.555 ns > 55 ns
tPWB = DATAST+1 = (2+1) *1000/72 = 41.6666 > 40 ns
把计算得的参数赋值到时序结构体中的FSMC_AddressSetupTime(即ADDSET 的值)
及FSMC_DataSetupTime(即DATAST 的值)中,然后再把时序结构体作为指针赋值到下
面的FSMC 初始化结构体中,作为读写的时序参数,最后再调用FSMC_NORSRAMInit 函
数即可把参数写入到相应的寄存器中。
bsp_sram.c
******************************************************************************
*/
#include "./sram/bsp_sram.h"
/**
* @brief 初始化控制SRAM的IO
* @param 无
* @retval 无
*/
static void SRAM_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* 使能SRAM相关的GPIO时钟 */
/*地址信号线*/
RCC_APB2PeriphClockCmd(FSMC_A0_GPIO_CLK | FSMC_A1_GPIO_CLK | FSMC_A2_GPIO_CLK |
FSMC_A3_GPIO_CLK | FSMC_A4_GPIO_CLK | FSMC_A5_GPIO_CLK |
FSMC_A6_GPIO_CLK | FSMC_A7_GPIO_CLK | FSMC_A8_GPIO_CLK |
FSMC_A9_GPIO_CLK | FSMC_A10_GPIO_CLK| FSMC_A11_GPIO_CLK|
FSMC_A12_GPIO_CLK| FSMC_A13_GPIO_CLK|FSMC_A14_GPIO_CLK |
FSMC_A15_GPIO_CLK|FSMC_A16_GPIO_CLK |FSMC_A17_GPIO_CLK |FSMC_A18_GPIO_CLK|
/*数据信号线*/
FSMC_D0_GPIO_CLK | FSMC_D1_GPIO_CLK | FSMC_D2_GPIO_CLK |
FSMC_D3_GPIO_CLK | FSMC_D4_GPIO_CLK | FSMC_D5_GPIO_CLK |
FSMC_D6_GPIO_CLK | FSMC_D7_GPIO_CLK | FSMC_D8_GPIO_CLK |
FSMC_D9_GPIO_CLK | FSMC_D10_GPIO_CLK| FSMC_D11_GPIO_CLK|
FSMC_D12_GPIO_CLK| FSMC_D13_GPIO_CLK| FSMC_D14_GPIO_CLK|
FSMC_D15_GPIO_CLK|
/*控制信号线*/
FSMC_CS_GPIO_CLK | FSMC_WE_GPIO_CLK | FSMC_OE_GPIO_CLK |
FSMC_UDQM_GPIO_CLK|FSMC_LDQM_GPIO_CLK, ENABLE);
/*-- GPIO 配置 -----------------------------------------------------*/
/* 通用 GPIO 配置 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //配置为复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*A地址信号线 针对引脚配置*/
GPIO_InitStructure.GPIO_Pin = FSMC_A0_GPIO_PIN;
GPIO_Init(FSMC_A0_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_A1_GPIO_PIN;
GPIO_Init(FSMC_A1_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_A2_GPIO_PIN;
GPIO_Init(FSMC_A2_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_A3_GPIO_PIN;
GPIO_Init(FSMC_A3_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_A4_GPIO_PIN;
GPIO_Init(FSMC_A4_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_A5_GPIO_PIN;
GPIO_Init(FSMC_A5_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_A6_GPIO_PIN;
GPIO_Init(FSMC_A6_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_A7_GPIO_PIN;
GPIO_Init(FSMC_A7_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_A8_GPIO_PIN;
GPIO_Init(FSMC_A8_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_A9_GPIO_PIN;
GPIO_Init(FSMC_A9_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_A10_GPIO_PIN;
GPIO_Init(FSMC_A10_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_A11_GPIO_PIN;
GPIO_Init(FSMC_A11_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_A12_GPIO_PIN;
GPIO_Init(FSMC_A12_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_A13_GPIO_PIN;
GPIO_Init(FSMC_A13_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_A14_GPIO_PIN;
GPIO_Init(FSMC_A14_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_A15_GPIO_PIN;
GPIO_Init(FSMC_A15_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_A16_GPIO_PIN;
GPIO_Init(FSMC_A16_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_A17_GPIO_PIN;
GPIO_Init(FSMC_A17_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_A18_GPIO_PIN;
GPIO_Init(FSMC_A18_GPIO_PORT, &GPIO_InitStructure);
/*DQ数据信号线 针对引脚配置*/
GPIO_InitStructure.GPIO_Pin = FSMC_D0_GPIO_PIN;
GPIO_Init(FSMC_D0_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_D1_GPIO_PIN;
GPIO_Init(FSMC_D1_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_D2_GPIO_PIN;
GPIO_Init(FSMC_D2_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_D3_GPIO_PIN;
GPIO_Init(FSMC_D3_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_D4_GPIO_PIN;
GPIO_Init(FSMC_D4_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_D5_GPIO_PIN;
GPIO_Init(FSMC_D5_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_D6_GPIO_PIN;
GPIO_Init(FSMC_D6_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_D7_GPIO_PIN;
GPIO_Init(FSMC_D7_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_D8_GPIO_PIN;
GPIO_Init(FSMC_D8_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_D9_GPIO_PIN;
GPIO_Init(FSMC_D9_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_D10_GPIO_PIN;
GPIO_Init(FSMC_D10_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_D11_GPIO_PIN;
GPIO_Init(FSMC_D11_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_D12_GPIO_PIN;
GPIO_Init(FSMC_D12_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_D13_GPIO_PIN;
GPIO_Init(FSMC_D13_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_D14_GPIO_PIN;
GPIO_Init(FSMC_D14_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_D15_GPIO_PIN;
GPIO_Init(FSMC_D15_GPIO_PORT, &GPIO_InitStructure);
/*控制信号线*/
GPIO_InitStructure.GPIO_Pin = FSMC_CS_GPIO_PIN;
GPIO_Init(FSMC_CS_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_WE_GPIO_PIN;
GPIO_Init(FSMC_WE_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_OE_GPIO_PIN;
GPIO_Init(FSMC_OE_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_UDQM_GPIO_PIN;
GPIO_Init(FSMC_UDQM_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = FSMC_LDQM_GPIO_PIN;
GPIO_Init(FSMC_LDQM_GPIO_PORT, &GPIO_InitStructure);
}
/**
* @brief 初始化FSMC外设
* @param None.
* @retval None.
*/
void FSMC_SRAM_Init(void)
{
FSMC_NORSRAMTimingInitTypeDef FSMC_ReadTimingStruct;
FSMC_NORSRAMTimingInitTypeDef FSMC_WriteTimingStruct;
FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
RCC_AHBPeriphClockCmd ( RCC_AHBPeriph_FSMC , ENABLE ) ;
//读时序
FSMC_ReadTimingStruct.FSMC_AccessMode = FSMC_AccessMode_A ;
FSMC_ReadTimingStruct.FSMC_AddressHoldTime = 0; //SRAM没用到
FSMC_ReadTimingStruct.FSMC_AddressSetupTime = 0; //理论值
FSMC_ReadTimingStruct.FSMC_BusTurnAroundDuration = 0;//SRAM没用到
FSMC_ReadTimingStruct.FSMC_CLKDivision = 0; //SRAM没用到
FSMC_ReadTimingStruct.FSMC_DataLatency = 0; //SRAM没用到
FSMC_ReadTimingStruct.FSMC_DataSetupTime = 2; //2是经验值 理论值是1
//写时序
FSMC_ReadTimingStruct.FSMC_AccessMode = FSMC_AccessMode_A ;
FSMC_ReadTimingStruct.FSMC_AddressHoldTime = 0; //SRAM没用到
FSMC_ReadTimingStruct.FSMC_AddressSetupTime = 0; //理论值
FSMC_ReadTimingStruct.FSMC_BusTurnAroundDuration = 0;//SRAM没用到
FSMC_ReadTimingStruct.FSMC_CLKDivision = 0; //SRAM没用到
FSMC_ReadTimingStruct.FSMC_DataLatency = 0; //SRAM没用到
FSMC_ReadTimingStruct.FSMC_DataSetupTime = 2; //2是经验值 理论值是1
FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM3;
FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Enable;
FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable ;
FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &FSMC_ReadTimingStruct;
FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignalPolarity_Low;
FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState ;
FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &FSMC_WriteTimingStruct;
//把配置写入到寄存器
FSMC_NORSRAMInit ( &FSMC_NORSRAMInitStructure ) ;
//使能FSMC
FSMC_NORSRAMCmd ( FSMC_Bank1_NORSRAM3, ENABLE );
}
void SARM_Init(void )
{
SRAM_GPIO_Config();
FSMC_SRAM_Init();
}
/*********************************************END OF FILE**********************/
bsp_sram.h
//使用NOR/SRAM的 Bank1.sector3,地址位HADDR[27,26]=10
//对IS61LV25616/IS62WV25616,地址线范围为A0~A17
//对IS61LV51216/IS62WV51216,地址线范围为A0~A18
#define Bank1_SRAM3_ADDR ((uint32_t)(0x68000000))
#define IS62WV51216_SIZE 0x100000 //512*16/2bits = 0x100000 ,1M字节
/*A地址信号线*/
#define FSMC_A0_GPIO_PORT GPIOF
#define FSMC_A0_GPIO_CLK RCC_APB2Periph_GPIOF
#define FSMC_A0_GPIO_PIN GPIO_Pin_0
#define FSMC_A1_GPIO_PORT GPIOF
#define FSMC_A1_GPIO_CLK RCC_APB2Periph_GPIOF
#define FSMC_A1_GPIO_PIN GPIO_Pin_1
#define FSMC_A2_GPIO_PORT GPIOF
#define FSMC_A2_GPIO_CLK RCC_APB2Periph_GPIOF
#define FSMC_A2_GPIO_PIN GPIO_Pin_2
#define FSMC_A3_GPIO_PORT GPIOF
#define FSMC_A3_GPIO_CLK RCC_APB2Periph_GPIOF
#define FSMC_A3_GPIO_PIN GPIO_Pin_3
#define FSMC_A4_GPIO_PORT GPIOF
#define FSMC_A4_GPIO_CLK RCC_APB2Periph_GPIOF
#define FSMC_A4_GPIO_PIN GPIO_Pin_4
#define FSMC_A5_GPIO_PORT GPIOF
#define FSMC_A5_GPIO_CLK RCC_APB2Periph_GPIOF
#define FSMC_A5_GPIO_PIN GPIO_Pin_5
#define FSMC_A6_GPIO_PORT GPIOF
#define FSMC_A6_GPIO_CLK RCC_APB2Periph_GPIOF
#define FSMC_A6_GPIO_PIN GPIO_Pin_12
#define FSMC_A7_GPIO_PORT GPIOF
#define FSMC_A7_GPIO_CLK RCC_APB2Periph_GPIOF
#define FSMC_A7_GPIO_PIN GPIO_Pin_13
#define FSMC_A8_GPIO_PORT GPIOF
#define FSMC_A8_GPIO_CLK RCC_APB2Periph_GPIOF
#define FSMC_A8_GPIO_PIN GPIO_Pin_14
#define FSMC_A9_GPIO_PORT GPIOF
#define FSMC_A9_GPIO_CLK RCC_APB2Periph_GPIOF
#define FSMC_A9_GPIO_PIN GPIO_Pin_15
#define FSMC_A10_GPIO_PORT GPIOG
#define FSMC_A10_GPIO_CLK RCC_APB2Periph_GPIOG
#define FSMC_A10_GPIO_PIN GPIO_Pin_0
#define FSMC_A11_GPIO_PORT GPIOG
#define FSMC_A11_GPIO_CLK RCC_APB2Periph_GPIOG
#define FSMC_A11_GPIO_PIN GPIO_Pin_1
#define FSMC_A12_GPIO_PORT GPIOG
#define FSMC_A12_GPIO_CLK RCC_APB2Periph_GPIOG
#define FSMC_A12_GPIO_PIN GPIO_Pin_2
#define FSMC_A13_GPIO_PORT GPIOG
#define FSMC_A13_GPIO_CLK RCC_APB2Periph_GPIOG
#define FSMC_A13_GPIO_PIN GPIO_Pin_3
#define FSMC_A14_GPIO_PORT GPIOG
#define FSMC_A14_GPIO_CLK RCC_APB2Periph_GPIOG
#define FSMC_A14_GPIO_PIN GPIO_Pin_4
#define FSMC_A15_GPIO_PORT GPIOG
#define FSMC_A15_GPIO_CLK RCC_APB2Periph_GPIOG
#define FSMC_A15_GPIO_PIN GPIO_Pin_5
#define FSMC_A16_GPIO_PORT GPIOD
#define FSMC_A16_GPIO_CLK RCC_APB2Periph_GPIOD
#define FSMC_A16_GPIO_PIN GPIO_Pin_11
#define FSMC_A17_GPIO_PORT GPIOD
#define FSMC_A17_GPIO_CLK RCC_APB2Periph_GPIOD
#define FSMC_A17_GPIO_PIN GPIO_Pin_12
#define FSMC_A18_GPIO_PORT GPIOD
#define FSMC_A18_GPIO_CLK RCC_APB2Periph_GPIOD
#define FSMC_A18_GPIO_PIN GPIO_Pin_13
/*D 数据信号线*/
#define FSMC_D0_GPIO_PORT GPIOD
#define FSMC_D0_GPIO_CLK RCC_APB2Periph_GPIOD
#define FSMC_D0_GPIO_PIN GPIO_Pin_14
#define FSMC_D1_GPIO_PORT GPIOD
#define FSMC_D1_GPIO_CLK RCC_APB2Periph_GPIOD
#define FSMC_D1_GPIO_PIN GPIO_Pin_15
#define FSMC_D2_GPIO_PORT GPIOD
#define FSMC_D2_GPIO_CLK RCC_APB2Periph_GPIOD
#define FSMC_D2_GPIO_PIN GPIO_Pin_0
#define FSMC_D3_GPIO_PORT GPIOD
#define FSMC_D3_GPIO_CLK RCC_APB2Periph_GPIOD
#define FSMC_D3_GPIO_PIN GPIO_Pin_1
#define FSMC_D4_GPIO_PORT GPIOE
#define FSMC_D4_GPIO_CLK RCC_APB2Periph_GPIOE
#define FSMC_D4_GPIO_PIN GPIO_Pin_7
#define FSMC_D5_GPIO_PORT GPIOE
#define FSMC_D5_GPIO_CLK RCC_APB2Periph_GPIOE
#define FSMC_D5_GPIO_PIN GPIO_Pin_8
#define FSMC_D6_GPIO_PORT GPIOE
#define FSMC_D6_GPIO_CLK RCC_APB2Periph_GPIOE
#define FSMC_D6_GPIO_PIN GPIO_Pin_9
#define FSMC_D7_GPIO_PORT GPIOE
#define FSMC_D7_GPIO_CLK RCC_APB2Periph_GPIOE
#define FSMC_D7_GPIO_PIN GPIO_Pin_10
#define FSMC_D8_GPIO_PORT GPIOE
#define FSMC_D8_GPIO_CLK RCC_APB2Periph_GPIOE
#define FSMC_D8_GPIO_PIN GPIO_Pin_11
#define FSMC_D9_GPIO_PORT GPIOE
#define FSMC_D9_GPIO_CLK RCC_APB2Periph_GPIOE
#define FSMC_D9_GPIO_PIN GPIO_Pin_12
#define FSMC_D10_GPIO_PORT GPIOE
#define FSMC_D10_GPIO_CLK RCC_APB2Periph_GPIOE
#define FSMC_D10_GPIO_PIN GPIO_Pin_13
#define FSMC_D11_GPIO_PORT GPIOE
#define FSMC_D11_GPIO_CLK RCC_APB2Periph_GPIOE
#define FSMC_D11_GPIO_PIN GPIO_Pin_14
#define FSMC_D12_GPIO_PORT GPIOE
#define FSMC_D12_GPIO_CLK RCC_APB2Periph_GPIOE
#define FSMC_D12_GPIO_PIN GPIO_Pin_15
#define FSMC_D13_GPIO_PORT GPIOD
#define FSMC_D13_GPIO_CLK RCC_APB2Periph_GPIOD
#define FSMC_D13_GPIO_PIN GPIO_Pin_8
#define FSMC_D14_GPIO_PORT GPIOD
#define FSMC_D14_GPIO_CLK RCC_APB2Periph_GPIOD
#define FSMC_D14_GPIO_PIN GPIO_Pin_9
#define FSMC_D15_GPIO_PORT GPIOD
#define FSMC_D15_GPIO_CLK RCC_APB2Periph_GPIOD
#define FSMC_D15_GPIO_PIN GPIO_Pin_10
/*控制信号线*/
/*CS片选*/
/*NE3 ,对应的基地址0x68000000*/
#define FSMC_CS_GPIO_PORT GPIOG
#define FSMC_CS_GPIO_CLK RCC_APB2Periph_GPIOG
#define FSMC_CS_GPIO_PIN GPIO_Pin_10
/*WE写使能*/
#define FSMC_WE_GPIO_PORT GPIOD
#define FSMC_WE_GPIO_CLK RCC_APB2Periph_GPIOD
#define FSMC_WE_GPIO_PIN GPIO_Pin_5
/*OE读使能*/
#define FSMC_OE_GPIO_PORT GPIOD
#define FSMC_OE_GPIO_CLK RCC_APB2Periph_GPIOD
#define FSMC_OE_GPIO_PIN GPIO_Pin_4
/*UB数据掩码*/
#define FSMC_UDQM_GPIO_PORT GPIOE
#define FSMC_UDQM_GPIO_CLK RCC_APB2Periph_GPIOE
#define FSMC_UDQM_GPIO_PIN GPIO_Pin_1
/*LB数据掩码*/
#define FSMC_LDQM_GPIO_PORT GPIOE
#define FSMC_LDQM_GPIO_CLK RCC_APB2Periph_GPIOE
#define FSMC_LDQM_GPIO_PIN GPIO_Pin_0
//SRAM初始化
void SARM_Init(void );
#endif /* __SRAM_H */
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!