STM32外扩SRAM及用法

一.概述

     一般单片机有片内的RAM,但都不多,比如:STM32F407ZGT6 自带了 192K 字节的 RAM,对一般应用来说,已经足够了,不过在一些对内存要求高的场合,比如做华丽效果的 GUI,处理大量数据的应用等,STM32 自带的这些内存就可能不太够用了。好在嵌入式方案提供了扩展芯片 RAM 的方法,使用 SRAM 芯片,并驱动这个外部 SRAM 提供程序需要的一部分RAM 空间即可。

1.存储器的分类

2.嵌入式程序主要对应ROM 和 RAM这两种存储器。对于 RAM,目前常见的是 SRAM 和 DRAM,它们因工作方式不同而得名,它们主要有以下的特性:

二.SRAM芯片与国产替代

1.IS62WV51216 是 ISSI(Integrated Silicon Solution, Inc)公司生产的一颗 16 位宽 512K(512*16,即 1M 字节)容量的 CMOS 静态内存芯片。该芯片具有如下几个特点:

高速。具有 45ns/55ns 访问速度。

低功耗。

TTL 电平兼容。

全静态操作。不需要刷新和时钟电路。

三态输出。

字节控制功能。支持高/低字节控制。

2.国产替代一直是国内嵌入式领域的一个话题,国产替代的优势一般是货源稳定,售价更低,也有专门研发对某款芯片作 Pin to Pin 兼容的厂家,使用时无需修改 PCB,直接更换元件即可,十分方便。

一款替代 IS62WV51216 的芯片是 XM8A5121,它与IS62WV51216 一样采用 TSOP44 封装,引脚顺序也与前者完全一致。

XM8A51216 是星忆存储生产的一颗 16 位宽 512K(512*16,即 1M 位)容量的 CMOS 静态内存芯片。采用异步 SRAM 接口并结合独有的 XRAM 免刷新专利技术,在大容量、高性能和高可靠及品质方面完全可以匹敌同类 SRAM,具有较低功耗和低成本优势,可以与市面上同类型 SRAM 产品硬件完全兼容,并且满足各种应用系统对高性能和低成本的要求,XM8A51216也可以当做异步 SRAM 使用,该芯片具有如下几个特点:

高速,具有最高访问速度 10/12ns。

低功耗。

TTL 电平兼容。

全静态操作。不需要刷新和时钟电路。

三态输出。

字节控制功能。支持高/低字节控制。

该芯片与 IS62WV51216 引脚和完全兼容,控制时序也类似,大家可以方便地直接替换。

三.FSMC介绍

FSMC 接口可以通过地址信号,快速地找到存储器对应存储块上的数据。STM32F407 的 FSMC接口支持包括 SRAM、NAND FLASH、NOR FLASH 和 PSRAM 等存储器。F4 系列的大容量型号,且引脚数目在 100 脚及以上的 STM32F407 芯片都带有 FSMC 接口, STM32F407ZGT6是带有 FSMC 接口的。

四.使用 SRAM 的配置步骤:

1)使能 FSMC 时钟,并配置 FSMC 相关的 IO 及其时钟使能。

要使用 FSMC,当然首先得开启其时钟。然后需要把 FSMC_D0~15,FSMCA0~18 等相关

IO 口,全部配置为复用输出,并使能各 IO 组的时钟。

使能 FSMC 时钟的方法前面 LCD 实验已经讲解过,方法为:

 __HAL_RCC_FSMC_CLK_ENABLE();

配置 IO 口为复用输出的关键行代码为:

 gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */

2)设置 FSMC BANK1 区域 3 的相关寄存器。

此部分包括设置区域 3 的存储器的工作模式、位宽和读写时序等。本章我们使用模式 A、

16 位宽,读写共用一个时序寄存器。

这个是通过调用函数 HAL_SRAM_Init 来实现的,函数原型为:

HAL_StatusTypeDef HAL_SRAM_Init(SRAM_HandleTypeDef *hsram,

FSMC_NORSRAM_TimingTypeDef *Timing, FSMC_NORSRAM_TimingTypeDef *ExtTiming)

通过以上几个步骤,我们就完成了 FSMC 的配置,初始化 FSMC 后就可以访问 SRAM 芯

片时行读写操作了,这里还需要注意,因为我们使用的是 BANK1 的区域 3,所以

HADDR[27:26]=10,故外部内存的首地址为 0X68000000。

.SRAM 驱动

核心代码:

#define SRAM_WR_GPIO_PORT GPIOD

#define SRAM_WR_GPIO_PIN GPIO_PIN_5

#define SRAM_WR_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOD_CLK_ENABLE();}while(0)

#define SRAM_RD_GPIO_PORT GPIOD

#define SRAM_RD_GPIO_PIN GPIO_PIN_4

#define SRAM_RD_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOD_CLK_ENABLE(); }while(0)

/* SRAM_CS(需要根据 SRAM_FSMC_NEX 设置正确的 IO 口) 引脚 定义 */

#define SRAM_CS_GPIO_PORT GPIOG

#define SRAM_CS_GPIO_PIN GPIO_PIN_10

#define SRAM_CS_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOG_CLK_ENABLE();}while(0)

根据 STM32F4 参考手册,SRAM 可以选择 FSMC 对应的存储块 1 上的 4 个区域之一作为

访问地址,它上面有四块相互独立的 64M 的连续寻址空间,为了能灵活根据不同的计算出使用

的地址空间,我们定义了以下的宏:

/* FSMC 相关参数 定义

* 注意: 我们默认是通过 FSMC 块 3 来连接 SRAM, 块 1 有 4 个片选: FSMC_NE1~4

*

* 修改 SRAM_FSMC_NEX, 对应的 SRAM_CS_GPIO 相关设置也得改

*/

#define SRAM_FSMC_NEX 3 /* 使用 FSMC_NE3 接 SRAM_CS,取值范围只能是: 1~4 */

/*****************************************************************/

/* SRAM 基地址, 根据 SRAM_FSMC_NEX 的设置来决定基址地址

* 我们一般使用 FSMC 的块 1(BANK1)来驱动 SRAM, 块 1 地址范围总大小为 256MB,均分成 4 块:

* 存储块 1(FSMC_NE1)地址范围: 0X6000 0000 ~ 0X63FF FFFF

* 存储块 2(FSMC_NE2)地址范围: 0X6400 0000 ~ 0X67FF FFFF

* 存储块 3(FSMC_NE3)地址范围: 0X6800 0000 ~ 0X6BFF FFFF

* 存储块 4(FSMC_NE4)地址范围: 0X6C00 0000 ~ 0X6FFF FFFF

*/

#define SRAM_BASE_ADDR (0X60000000 + (0X4000000 * (SRAM_FSMC_NEX - 1)))

上述定义 SRAM_FSMC_NEX 的值为 3,即使用 FSMC 存储块 1 的第 3 个地址范围,上面

的 SRAM_BASE_ADDR 则根据我们使用的存储块计算出 SRAM 空间的首地址,存储块 3 对应

的是 0X68000000 ~ 0X6BFFFFFF 的地址空间。

sram 的初始化函数我们编写如下:

/**

* @brief 初始化 外部 SRAM

* @param 无

* @retval 无

*/

void sram_init(void)

{

 GPIO_InitTypeDef GPIO_Initure;

 FSMC_NORSRAM_TimingTypeDef fsmc_readwritetim;

 SRAM_CS_GPIO_CLK_ENABLE(); /* SRAM_CS 脚时钟使能 */

 SRAM_WR_GPIO_CLK_ENABLE(); /* SRAM_WR 脚时钟使能 */

 SRAM_RD_GPIO_CLK_ENABLE(); /* SRAM_RD 脚时钟使能 */

 __HAL_RCC_FSMC_CLK_ENABLE(); /* 使能 FSMC 时钟 */

761

STM32F407 开发指南

正点原子探索者 STM32F407 开发板教程

 __HAL_RCC_GPIOD_CLK_ENABLE(); /* 使能 GPIOD 时钟 */

 __HAL_RCC_GPIOE_CLK_ENABLE(); /* 使能 GPIOE 时钟 */

 __HAL_RCC_GPIOF_CLK_ENABLE(); /* 使能 GPIOF 时钟 */

 __HAL_RCC_GPIOG_CLK_ENABLE(); /* 使能 GPIOG 时钟 */

 GPIO_Initure.Pin = SRAM_CS_GPIO_PIN;

 GPIO_Initure.Mode = GPIO_MODE_AF_PP;

 GPIO_Initure.Pull = GPIO_PULLUP;

 GPIO_Initure.Speed = GPIO_SPEED_FREQ_HIGH;

 HAL_GPIO_Init(SRAM_CS_GPIO_PORT, &GPIO_Initure); /* SRAM_CS 引脚模式设置 */

 GPIO_Initure.Pin = SRAM_WR_GPIO_PIN;

 HAL_GPIO_Init(SRAM_WR_GPIO_PORT, &GPIO_Initure); /* SRAM_WR 引脚模式设置 */

 GPIO_Initure.Pin = SRAM_RD_GPIO_PIN;

 HAL_GPIO_Init(SRAM_RD_GPIO_PORT, &GPIO_Initure); /* SRAM_CS 引脚模式设置 */

 /* PD0,1,4,5,8~15 */

GPIO_Initure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_8 | GPIO_PIN_9 |

GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13

GPIO_PIN_14 | GPIO_PIN_15;

 GPIO_Initure.Mode = GPIO_MODE_AF_PP; /* 推挽复用 */

 GPIO_Initure.Pull = GPIO_PULLUP; /* 上拉 */

 GPIO_Initure.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */

 HAL_GPIO_Init(GPIOD, &GPIO_Initure);

 /* PE0,1,7~15 */

GPIO_Initure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_7 | GPIO_PIN_8 |

GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 |

GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;

 HAL_GPIO_Init(GPIOE, &GPIO_Initure);

 /* PF0~5,12~15 */

GPIO_Initure.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 |

GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_12 | GPIO_PIN_13 |

GPIO_PIN_14 | GPIO_PIN_15;

 HAL_GPIO_Init(GPIOF, &GPIO_Initure);

 /* PG0~5,10 */

GPIO_Initure.Pin = GPIO_PIN_0 | GPIO_PIN_1 |

GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5;

 HAL_GPIO_Init(GPIOG, &GPIO_Initure);

 g_sram_handler.Instance = FSMC_NORSRAM_DEVICE;

 g_sram_handler.Extended = FSMC_NORSRAM_EXTENDED_DEVICE;

 g_sram_handler.Init.NSBank = (SRAM_FSMC_NEX == 1) ? FSMC_NORSRAM_BANK1 : \

 (SRAM_FSMC_NEX == 2) ? FSMC_NORSRAM_BANK2:\

(SRAM_FSMC_NEX == 3) ? FSMC_NORSRAM_BANK3:\

 FSMC_NORSRAM_BANK4; /* 根据配置选择 FSMC_NE1~4 */

 /* 地址/数据线不复用 */

 g_sram_handler.Init.DataAddressMux = FSMC_DATA_ADDRESS_MUX_DISABLE;

g_sram_handler.Init.MemoryType = FSMC_MEMORY_TYPE_SRAM; /* SRAM */

/* 16 位数据宽度 */

g_sram_handler.Init.MemoryDataWidth = SMC_NORSRAM_MEM_BUS_WIDTH_16;

/* 是否使能突发访问,仅对同步突发存储器有效,此处未用到 */

g_sram_handler.Init.BurstAccessMode = FSMC_BURST_ACCESS_MODE_DISABLE;

/* 等待信号的极性,仅在突发模式访问下有用 */

g_sram_handler.Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW;

/* 存储器是在等待周期之前的一个时钟周期还是等待周期期间使能 NWAIT */

g_sram_handler.Init.WaitSignalActive = FSMC_WAIT_TIMING_BEFORE_WS;

/* 存储器写使能 */

g_sram_handler.Init.WriteOperation = FSMC_WRITE_OPERATION_ENABLE;

/* 等待使能位,此处未用到 */

g_sram_handler.Init.WaitSignal = FSMC_WAIT_SIGNAL_DISABLE;

/* 读写使用相同的时序 */

g_sram_handler.Init.ExtendedMode = FSMC_EXTENDED_MODE_DISABLE;

/* 是否使能同步传输模式下的等待信号,此处未用到 */

 g_sram_handler.Init.AsynchronousWait = FSMC_ASYNCHRONOUS_WAIT_DISABLE;

 g_sram_handler.Init.WriteBurst = FSMC_WRITE_BURST_DISABLE; /* 禁止突发写 */

/* FSMC 读时序控制寄存器 */

/* 地址建立时间(ADDSET)为 2 个 HCLK 1/168M=6ns*2=12ns */

 fsmc_readwritetim.AddressSetupTime = 0x02;

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

 fsmc_readwritetim.DataSetupTime = 0x08; /* 数据保存时间为 8 个 HCLK=6ns*8=48ns */

 fsmc_readwritetim.BusTurnAroundDuration = 0X00;

 fsmc_readwritetim.AccessMode = FSMC_ACCESS_MODE_A; /* 模式 A */

 HAL_SRAM_Init(&g_sram_handler,&fsmc_readwritetim,&fsmc_readwritetim);

}

初始化成功后,FSMC 控制器就能根据扩展的地址线访问 SRAM 的数据,于是我们可以直

接根据地址指针来访问 SRAM,我们定义 SRAM 的写函数如下;

void sram_write(uint8_t *pbuf, uint32_t addr, uint32_t datalen)

{

 for (; datalen != 0; datalen--)

 {

 *(volatile uint8_t *)(SRAM_BASE_ADDR + addr) = *pbuf;

 addr++;

 pbuf++;

 }

}

同样地,也是利用地址,可以构造出一个 SRAM 的连续读函数:

void sram_read(uint8_t *pbuf, uint32_t addr, uint32_t datalen)

{

 for (; datalen != 0; datalen--)

 {

 *pbuf++ = *(volatile uint8_t *)(SRAM_BASE_ADDR + addr);

 addr++;

 }

}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

swagger的接口文档导入到yapi上

一、访问swagger接口 swagger集成到项目后,通过http:\\ip:port/swagger-ui.html 访问。 说明:这里的路径是基于swagger2。如果用swagger3,需要用swagger3的路径进行访问。 访问如图: 这就是swagger接口首页。如果想导入到yapi上…

module_param_named 内核启动时模块参数实现原理

基于上节内核启动参数实现原理内容, 其中对early_param的实现流程做了分析, 已基本清晰. 但有不少的参数是在内核模块中声明的, 具体赋值流程也值得一探究竟. nomodeset 装过Linux系统的同学可能多少有看到过nomodeset这个参数, 解决一些显卡点不亮Linux的问题. 那么这个nomo…

AI绘画Stable Diffusion 新手入门教程:万字长文解析Lora模型的使用,快速上手Lora模型!

大家好,我是设计师阿威 今天给大家讲解一下AI绘画Stable Diffusion 中的一个重要模型—Lora模型,如果还有小伙伴没有SD安装包的,可以看我往期入门教程2024最新超强AI绘画Stable Diffusion整合包安装教程,零基础入门必备&#xff…

React Hooks --- 分享自己开发中常用的自定义的Hooks (1)

为什么要使用自定义 Hooks 自定义 Hooks 是 React 中一种复用逻辑的机制,通过它们可以抽离组件中的逻辑,使代码更加简洁、易读、易维护。它们可以在多个组件中复用相同的逻辑,减少重复代码。 1、useThrottle 代码 import React,{ useRef,…

三叶青图像识别研究简概

三叶青图像识别研究总概 文章目录 前言一、整体目录介绍二、前期安排三、构建图像分类数据集四、模型训练准备五、迁移学习模型六、在测试集上评估模型精度七、可解释性分析、显著性分析八、图像分类部署九、树莓派部署十、相关补充总结 前言 本系列文章为近期所做项目研究而作…

工作助手VB开发笔记(2)

今天继续讲功能 2.功能 2.9开机自启 设置程序随windows系统启动,其实就是就是将程序加载到注册表 Public Sub StartRunRegHKLM()REM HKEY_LOCAL_MACHINE \ SOFTWARE \ WOW6432Node \ Microsoft \ Windows \ CurrentVersion \ RunDim strName As String Applicat…

教师商调函流程详解

作为一名教师,您是否曾面临过工作调动的困惑?当您决定迈向新的教育环境,是否清楚整个商调函流程的每一个细节?今天,就让我们一起来探讨这一过程,确保您能够顺利地完成工作调动。 首先需要确定新调入的学校已…

裁员风波中的项目经理,如何自洽?

最近都在担心企业裁员,那么项目经理会不会也有被优化的风险呢? 答案是,一定会! 今天从3个方面给大家阐述一下项目经理岗位的发展现状以及未来的趋势 01 项目经理被优化的可能性大吗? 02 哪一类项目经理会被最先裁员…

CSDN导入本地md文件图片不能正常回显问题

标题 搭建图像仓库获取图片URL 路径替换 因为服务器读取不到本地图片,故不能正常回显,因此想要正常回显图片,我们首先要做的就是搭建一个可以存放图片的服务器,像你可以选择购买一个云服务器、FastDFS图片服务器、Minio多云对象存…

信息收集-arping

信息收集-arping 简介 arping 是一个用于发送 ARP 请求和接收 ARP 回复的工具。它通常用于检查网络中的 IP 地址是否被使用,或发现网络中的重复 IP 地址。arping 工具类似于 ping 命令,但它使用的是 ARP 协议而不是 ICMP 协议。在 Kali Linux 中&#…

娱乐圈惊爆已婚男星刘端端深夜幽会

【娱乐圈惊爆!已婚男星刘端端深夜幽会,竟是《庆余年》二皇子“戏外风云”】在这个信息爆炸的时代,娱乐圈的每一次风吹草动都能瞬间点燃公众的热情。今日,知名娱乐博主刘大锤的一则预告如同投入湖中的巨石,激起了层层涟…

纸电混合阶段,如何在线上实现纸电会档案的协同管理?

随着国家政策的出台和引导,电子会计档案的管理越来越规范,电子会计档案建设成为打通财务数字化最后一公里的重要一环。但是,当前很多企业的财务管理仍处于电子档案和纸质档案并行的阶段,如何能将其建立合理清晰关联,统…

《数字图像处理-OpenCV/Python》第17章:图像的特征描述

《数字图像处理-OpenCV/Python》第17章:图像的特征描述 本书京东 优惠购书链接 https://item.jd.com/14098452.html 本书CSDN 独家连载专栏 https://blog.csdn.net/youcans/category_12418787.html 第17章:图像的特征描述 特征检测与匹配是计算机视觉的…

javascript v8编译器的使用记录

我的机器是MacOS Mx系列。 一、v8源码下载构建 1.1 下载并更新depot_tools git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git export PATH/path/to/depot_tools:$PATH 失败的话可能是网络问题,可以试一下是否能ping通,连…

【代码随想录_Day25】452. 用最少数量的箭引爆气球 435. 无重叠区间 763. 划分字母区间

Day25 OK,今日份的打卡!第二十五天 以下是今日份的总结用最少数量的箭引爆气球无重叠区间划分字母区间 以下是今日份的总结 用最少数量的箭引爆气球无重叠区间划分字母区间 今天的题目难度不低,而且非常的有意思,尽量还是写一些…

imx6ull/linux应用编程学习(11)CAN应用编程基础

关于裸机的can通信,会在其他文章发,这里主要讲讲linux上的can通信。 与I2C,SPI等同步通讯方式不同,CAN通讯是异步通讯,也就是没有时钟信号线来保持信号接收同步,也就是所说的半双工,无法同时发送与接收&…

python项目常见使用的传参调试方法

简介 你是否经常遇到下载的github开源知名项目,不知如何调试?只知道按说明的命令行运行?遇到异常或想改造也无从下手?这篇文档章将指导你如何入手调试别人的大型开源项目。 常见项目使用说明及代码如何调试 常见情况一 使用说…

16.【C语言】初识常见关键字 上

1.关键字由C语言自带,不能自创 2.关键字不作变量名 3.关键字举例: auto自动:每个局部变量都由auto修饰,含义:自动创建,自动销毁 auto int a0;等价于int a0; exturn:申明外部符号 register:寄存器关键字…

数据治理的制胜法宝:筛斗数据技术在现代企业管理中的应用

数据治理的制胜法宝:筛斗数据技术在现代企业管理中的应用 在当今这个数据驱动的时代,企业管理的效率和竞争力越来越依赖于对数据的精准把握和高效利用。然而,随着企业规模的扩大和业务复杂度的增加,数据治理成为了一个亟需解决的…

EasyExcel 单元格根据图片数量动态设置宽度

在使用 EasyExcel 导出 Excel 时&#xff0c;如果某个单元格是图片内容&#xff0c;且存在多张图片&#xff0c;此时就需要单元格根据图片数量动态设置宽度。 经过自己的研究和实验&#xff0c;导出效果如下&#xff1a; 具体代码如下&#xff1a; EasyExcel 版本 <depen…