IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 扩展外部SRAM -> 正文阅读

[嵌入式]扩展外部SRAM

扩展外部SRAM

一、SRAM控制原理
STM32控制器芯片内部有一定大小的SRAM及FLASH作为内存和程序存储空间,但当程序较大,内存和程序空间不足时,就需要在STM32芯片的外部扩展存储器了。SRAM中的数据断电即失(属于易失性存储器),因此只适用于存储经常改变的变量。扩展内存时一般使用SRAM和SDRAM存储器,但STM32F407系列的芯片不支持扩展SDRAM(STM32F429系列支持),它仅支持使用FSMC外设扩展SRAM。给STM32芯片扩展内存与给PC扩展内存的原理是一样的,只是PC上一般以内存条的形式扩展, 内存条实质是由多个内存颗粒(即SRAM芯片)组成的通用标准模块,而STM32直接与SRAM芯片连接。
在STM32中,数组等变量的使用会在SRAM中进行,而程序编译后,整个程序中的代码、指令不会再进行修改了,存储再FLASH中。如果使用的变量较多时,就需要使用扩展外部SRAM(相当于电脑加扩展内存条)。

STM32扩展外部SRAM管脚
在这里插入图片描述
SRAM芯片内部功能框架,其中A0-A18即指上图中的A0-A18引脚
在这里插入图片描述
UB、LB两根线代表的是读取数据的高八位/低八位
CS线是片选信号线
WE/OE是读使能/写使能信号线
信号A0-A18信号线到地址译码器,得到应该访问哪个相应的单元格(读或写都可)
都与上图引脚对应
下图为SRAM信号线控制的引脚说明
在这里插入图片描述

储存矩阵
在这里插入图片描述
SRAM内部包含的存储阵列,按行地址与列地址储存,可以把它理解成一张表格,数据就填在这张表格上。和表格查找一样,指定一个行地址和列地址,就可以精确地找到目标单元格, 这是SRAM芯片寻址的基本原理。这样的每个单元格被称为存储单元,而这样的表则被称为存储矩阵。
地址译码器把N根地址线转换为2的N次方根信号线,每根信号线对应一行或一列存储单元,每个存储单元都有其独立行列地址,通过此来寻址。
访问时, 使用UB或LB线控制数据宽度,例如,当要访问宽度为16位的数据时,使用行地址线指出地址,然后把UB和LB线都设置为低电平(使能), 那么I/O0-I/O15线都有效,它们一起输出该地址的16位数据(或者接收16位数据到该地址);当要访问宽度为8位的数据时,使用行地址线指出地址, 然后把UB或LB其中一个设置为低电平,I/O会对应输出该地址的高8位和低8位数据,因此它们被称为数据掩码信号。(推测)

二、SRAM的读写流程
(1) 主机使用地址信号线发出要访问的存储器目标地址;
(2) 控制片选信号CS1#及CS2#使能存储器芯片;
(3) 若是要进行读操作,则控制读使能信号OE#表示要读数据,若进行写操作则控制写使能信号WE#表示要写数据;
(4) 使用掩码信号LB#与UB#指示要访问目标地址的高、低字节部分;
(5) 若是读取过程,存储器会通过数据线向主机输出目标数据,若是写入过程,主要使用数据线向存储器传输目标数据。
在读写时序中,有几个比较重要的时间参数,在使用STM32 控制的时候需要参考。
在这里插入图片描述

在这里插入图片描述

tRC:读操作周期 最短时间:55ns
tAA:地址访问时间 最短时间:0ns
tWC:写操作周期 最短时间:55ns
rSA:地址建立时间 最短时间:0ns
tSD:数据建立至写结束的时间 最短时间:25ns
tHD:数据写结束后的保持时间 最短时间:0ns

三、FSMC简介
STM32F407系列芯片使用FSMC外设来管理扩展的存储器, FSMC即Flexible Static Memory Controlle。 它可以用于驱动包括SRAM、NOR FLASH以及NAND FLSAH类型的存储器,(FSMC是静态的)不能驱动如SDRAM这种动态的存储器。而在STM32F429系列的控制器中, 它具有FMC(Flexible Memory Controlle)外设,支持控制SDRAM存储器。
1.FSMC框图
在这里插入图片描述
FSCM不是挂载在APBx总线上,而是挂载在AHB高速总线上(具体为AHB3),原因是FSMC要求较快的驱动速度,直接当内存访问,相应应该使用AHB时钟。地址线FSMC_A和数据线FSMC_D是所有控制器都共用的。
通讯引脚:
在这里插入图片描述
其中比较特殊的FSMC_NE是用于控制SRAM芯片的片选控制信号线,STM32具有FSMC_NE1/2/3/4号引脚,不同的引脚对应STM32内部不同的地址区域。 例如,当STM32访问0x6C000000-0x6FFFFFFF地址空间时,FSMC_NE3引脚会自动设置为低电平,由于它连接到SRAM的CE#引脚, 所以SRAM的片选被使能,而访问0x60000000-0x63FFFFFF地址时,FSMC_NE1会输出低电平。当使用不同的FSMC_NE引脚连接外部存储器时, STM32访问SRAM的地址不一样,从而达到控制多块SRAM芯片的目的。也就是说,连接到哪个相应的地址与之相对的引脚就会被设置为低电平。
存储器控制器
上面不同类型的引脚是连接到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控制寄存器可配置要控制的存储器类型、数据线宽度以及信号有效极性能参数。

模式A-SRAM的FSMC_BCR
在这里插入图片描述

模式B-NOR FLASH的FSMC_BCR
在这里插入图片描述

FMC_BTR时序寄存器用于配置SRAM访问时的各种时间延迟,如数据保持时间、地址保持时间等。

模式A-SRAM的FSMC_BTR在这里插入图片描述
模式B-NOR FLASH的FSMC_BTR
在这里插入图片描述

FSMC_BWTR写时序寄存器与FMC_BTR寄存器控制的参数类似,它专门用于控制写时序的时间参数。
时钟控制逻辑
FSMC外设挂载在AHB总线上,时钟信号来自于HCLK(默认168MHz),控制器的同步时钟输出就是由它分频得到。例如,NOR控制器的FSMC_CLK引脚输出的时钟,它可用于与同步类型的SRAM芯片进行同步通讯,它的时钟频率可通过FSMC_BTR寄存器的CLKDIV位配置,可以配置为HCLK的1/2或 1/3,也就是说,若它与同步类型的SRAM通讯时,同步时钟最高频率为84MHz。本示例中的SRAM为异步类型的存储器,不使用同步时钟信号,所以时钟分频配置不起作用。SRAM是异步的,NOR FLASH有些是同步的需要用到时钟同步逻辑。
地址映射
FSMC连接好外部的存储器并初始化后,就可以直接通过访问地址来读写数据,这种地址访问与I2C EEPROM、SPI FLASH的不一样, 后两种方式都需要控制I2C或SPI总线给存储器发送地址,然后获取数据;在程序里,这个地址和数据都需要分开使用不同的变量存储, 并且访问时还需要使用代码控制发送读写命令。而使用FSMC外接存储器时,其存储单元是映射到STM32的内部寻址空间的;在程序里, 定义一个指向这些地址的指针,然后就可以通过指针直接修改该存储单元的内容,FSMC外设会自动完成数据访问过程, 读写命令之类的操作不需要程序控制。(代码段自动储存)

通过指针直接访问后面的地址在这里插入图片描述
注:SRAM和NOR FLASH只能用Bank1就算STM32扩展到最大1G,也只能访问Bank1.Bank区域自动分配过。

SRAM时序结构体
控制FSMC使用SRAM存储器时主要是配置时序寄存器以及控制寄存器,利用ST标准库的SRAM时序结构体以及初始化结构体可以很方便地写入参数。

typedef struct
{
uint32_t FSMC_AddressSetupTime;     /*地址建立时间,0-0xF个HCLK周期*/
uint32_t FSMC_AddressHoldTime;      /*地址保持时间,0-0xF个HCLK周期*/
uint32_t FSMC_DataSetupTime;        /*地址建立时间,0-0xF个HCLK周期*/
uint32_t FSMC_BusTurnAroundDuration;/*总线转换周期,0-0xF个HCLK周期,
                                     在NOR FLASH */
uint32_t FSMC_CLKDivision;          /*时钟分频因子,1-0xF,若控制异步
                                     存储器,本参数无效 */
uint32_t FSMC_DataLatency;          /*数据延迟时间,若控制异步存储器,
                                    本参数无效 */
uint32_t FSMC_AccessMode;             
                                    /*设置访问模式 */
}FSMC_NORSRAMTimingInitTypeDef;

FSMC的SRAM初始化结构体

typedef struct
{
uint32_t FSMC_Bank;                /*设置要控制的Bank区域 */
uint32_t FSMC_DataAddressMux;      /*设置地址总线与数据总线是否复用 */
uint32_t FSMC_MemoryType;          /*设置存储器的类型 */
uint32_t FSMC_MemoryDataWidth;     /*设置存储器的数据宽度*/
uint32_t FSMC_BurstAccessMode; /*设置是否支持突发访问模式,只支持同步类型的存储器 */
uint32_t FSMC_AsynchronousWait;     /*设置是否使能在同步传输时的等待信号,*/
uint32_t FSMC_WaitSignalPolarity;  /*设置等待信号的极性*/
uint32_t FSMC_WrapMode;            /*设置是否支持对齐的突发模式 */
uint32_t FSMC_WaitSignalActive; /*配置等待信号在等待前有效还是等待期间有效 */
uint32_t FSMC_WriteOperation;      /*设置是否写使能 */
uint32_t FSMC_WaitSignal;          /*设置是否使能等待状态插入 */
uint32_t FSMC_ExtendedMode;        /*设置是否使能扩展模式 */
uint32_t FSMC_WriteBurst;          /*设置是否使能写突发操作*/
/*当不使用扩展模式时,本参数用于配置读写时序,否则用于配置读时序*/
FSMC_NORSRAMTimingInitTypeDef* FSMC_ReadWriteTimingStruct;
/*当使用扩展模式时,本参数用于配置写时序*/
FSMC_NORSRAMTimingInitTypeDef* FSMC_WriteTimingStruct;
}FSMC_NORSRAMInitTypeDef;

举例定义宏

#define FSMC_GPIO_AF             GPIO_AF_FSMC

/*A地址信号线*/
#define FSMC_A0_GPIO_PORT        GPIOF
#define FSMC_A0_GPIO_CLK         RCC_AHB1Periph_GPIOF
#define FSMC_A0_GPIO_PIN         GPIO_Pin_0
#define FSMC_A0_GPIO_PinSource   GPIO_PinSource0
/*……省略A1-A18地址线*/

/*D 数据信号线*/
#define FSMC_D0_GPIO_PORT        GPIOD
#define FSMC_D0_GPIO_CLK         RCC_AHB1Periph_GPIOD
#define FSMC_D0_GPIO_PIN         GPIO_Pin_14
#define FSMC_D0_GPIO_PinSource   GPIO_PinSource14
/*……省略D1-D15地址线*/

/*控制信号线*/
/*CS片选*/
/*NE4 ,对应的基地址0x6C000000*/
#define FSMC_CS_GPIO_PORT        GPIOG
#define FSMC_CS_GPIO_CLK         RCC_AHB1Periph_GPIOG
#define FSMC_CS_GPIO_PIN         GPIO_Pin_12
#define FSMC_CS_GPIO_PinSource   GPIO_PinSource12

/*WE写使能*/
#define FSMC_WE_GPIO_PORT        GPIOD
#define FSMC_WE_GPIO_CLK         RCC_AHB1Periph_GPIOD
#define FSMC_WE_GPIO_PIN         GPIO_Pin_5
#define FSMC_WE_GPIO_PinSource   GPIO_PinSource5

/*OE读使能*/
#define FSMC_OE_GPIO_PORT        GPIOD
#define FSMC_OE_GPIO_CLK         RCC_AHB1Periph_GPIOD
#define FSMC_OE_GPIO_PIN         GPIO_Pin_4
#define FSMC_OE_GPIO_PinSource   GPIO_PinSource4


/*UB数据掩码*/
#define FSMC_UDQM_GPIO_PORT        GPIOE
#define FSMC_UDQM_GPIO_CLK         RCC_AHB1Periph_GPIOE
#define FSMC_UDQM_GPIO_PIN         GPIO_Pin_1
#define FSMC_UDQM_GPIO_PinSource   GPIO_PinSource1

/*LB数据掩码*/
#define FSMC_LDQM_GPIO_PORT        GPIOE
#define FSMC_LDQM_GPIO_CLK         RCC_AHB1Periph_GPIOE
#define FSMC_LDQM_GPIO_PIN         GPIO_Pin_0
#define FSMC_LDQM_GPIO_PinSource   GPIO_PinSource0

初始化FSMC的 GPIO
利用上面的宏,编写FSMC的GPIO引脚初始化函数

static void SRAM_GPIO_Config(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    /* 使能SRAM相关的GPIO时钟 */
    RCC_AHB1PeriphClockCmd(FSMC_A0_GPIO_CLK |FSMC_D0_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_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

    /*A地址信号线 引脚配置*/
    GPIO_InitStructure.GPIO_Pin = FSMC_A0_GPIO_PIN;
    GPIO_Init(FSMC_A0_GPIO_PORT, &GPIO_InitStructure);
    GPIO_PinAFConfig(FSMC_A0_GPIO_PORT,FSMC_A0_GPIO_PinSource,FSMC_GPIO_AF);

    /*DQ数据信号线 引脚配置*/
    GPIO_InitStructure.GPIO_Pin = FSMC_D0_GPIO_PIN;
    GPIO_Init(FSMC_D0_GPIO_PORT, &GPIO_InitStructure);
    GPIO_PinAFConfig(FSMC_D0_GPIO_PORT,FSMC_D0_GPIO_PinSource,FSMC_GPIO_AF);
    /*控制信号线*/
    GPIO_InitStructure.GPIO_Pin = FSMC_CS_GPIO_PIN;
    GPIO_Init(FSMC_CS_GPIO_PORT, &GPIO_InitStructure);
    GPIO_PinAFConfig(FSMC_CS_GPIO_PORT,FSMC_CS_GPIO_PinSource,FSMC_GPIO_AF);
}

使用指针的方式访问SRAM

/*SRAM起始地址 存储空间4的起始地址*/
#define Bank1_SRAM4_ADDR     ((uint32_t)0x6C000000)
/*SRAM大小,1M字节*/
#define IS62WV51216_SIZE 0x100000

uint32_t temp;

/*向SRAM写入8位数据*/
*( uint8_t*) (Bank1_SRAM4_ADDR ) = (uint8_t)0xAA;
/*从SRAM读取数据*/
temp =  *( uint8_t*) (Bank1_SRAM4_ADDR );

/*写/读 16位数据*/
*( uint16_t*) (Bank1_ SRAM4_ADDR +10 ) = (uint16_t)0xBBBB;
temp =  *( uint16_t*) (Bank1_SRAM4_ADDR+10 );

/*写/读 32位数据*/
*( uint32_t*) (Bank1_SRAM4_ADDR +20 ) = (uint32_t)0xCCCCCCCC;
temp =  *( uint32_t*) (Bank1_SRAM4_ADDR+20 );

配置FSMC的模式

void FSMC_SRAM_Init(void)
{
    FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
    FSMC_NORSRAMTimingInitTypeDef  readWriteTiming;

    /*初始化SRAM相关的GPIO*/
    SRAM_GPIO_Config();

    /*使能FSMC外设时钟*/
    RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC,ENABLE);
    /*********************时序**************************/
    //地址建立时间(ADDSET)为1个HCLK
    readWriteTiming.FSMC_AddressSetupTime = 0x00;

    //地址保持时间(ADDHLD)模式A未用到
    readWriteTiming.FSMC_AddressHoldTime = 0x00;

    //数据保持时间(DATAST)+ 1个HCLK = 9/168M=54ns(对EM的SRAM芯片)
    readWriteTiming.FSMC_DataSetupTime = 0x08;

    //设置总线转换周期,仅用于复用模式的NOR操作
    readWriteTiming.FSMC_BusTurnAroundDuration = 0x00;

    //设置时钟分频,仅用于同步类型的存储器
    readWriteTiming.FSMC_CLKDivision = 0x00;

    //数据保持时间,仅用于同步型的NOR
    readWriteTiming.FSMC_DataLatency = 0x00;

    //选择匹配SRAM的模式
    readWriteTiming.FSMC_AccessMode = FSMC_AccessMode_A;

    /**************************控制************************************/
    // 选择FSMC映射的存储区域: Bank1 sram4
    FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;

    //设置地址总线与数据总线是否复用,仅用于NOR
    FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;

    //设置要控制的存储器类型:SRAM类型
    FSMC_NORSRAMInitStructure.FSMC_MemoryType =FSMC_MemoryType_SRAM;

    //存储器数据宽度:16位
    FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;

    //设置是否使用突发访问模式,仅用于同步类型的存储器
    FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode =FSMC_BurstAccessMode_Disable;

    //设置是否使能等待信号,仅用于同步类型的存储器
    FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait=FSMC_AsynchronousWait_Disable;

    //设置等待信号的有效极性,仅用于同步类型的存储器
    FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;

    //设置是否支持把非对齐的突发操作,仅用于同步类型的存储器
    FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;

    //设置等待信号插入的时间,仅用于同步类型的存储器
    FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;

    //存储器写使能
    FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;

    //不使用等待信号
    FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;

    // 不使用扩展模式,读写使用相同的时序
    FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;

    //突发写操作
    FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;

    //读写时序配置
    FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &readWriteTiming;

    //读写同样时序,使用扩展模式时这个配置才有效
    FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &readWriteTiming;

    FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);  //初始化FSMC配置

    FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE);  // 使能BANK

}
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-08-16 11:54:30  更:2021-08-16 11:55:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 2:49:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计