外部sram数组读写volatile_探索者 STM32F407 开发板资料连载第四十一章 外部 SRAM 实验

1)实验平台:alientek 阿波罗 STM32F767 开发板

2)摘自《STM32F7 开发指南(HAL 库版)》关注官方微信号公众号,获取更多资料:正点原子

b02690e47e01adca79261af7c1d3d11e.png

第四十一章 外部 SRAM 实验

STM32F407ZGT6 自带了 192K 字节的 SRAM,对一般应用来说,已经足够了,不过在一

些对内存要求高的场合,STM32F4 自带的这些内存就不够用了。比如跑算法或者跑 GUI 等,

就可能不太够用,所以探索者 STM32F4 开发板板载了一颗 1M 字节容量的 SRAM 芯片:

XM8A51216,满足大内存使用的需求。

本章,我们将使用 STM32F4 来驱动 XM8A51216,实现对 XM8A51216 的访问控制,并测

试其容量。本章分为如下几个部分:

41.1 XM8A51216 简介

41.2 硬件设计

41.3 软件设计

41.4 下载验证

41.1 XM8A51216 简介

XM8A51216 是星忆存储科技公司生产的一颗 16 位宽 512K(512*16,即 1M 字节)容量的

CMOS 静态内存芯片。该芯片具有如下几个特点:

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

⚫ 低功耗。

⚫ TTL 电平兼容。

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

⚫ 三态输出。

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

XM8A51216 的功能框图如图 41.1.1 所示:

55c7454c40a1a2f1e3227a86316fe3e0.png

图 41.1.1 XM8A51216 功能框图

图中 A0~18 为地址线,总共 19 根地址线(即 2^19=512K,1K=1024);DQ0~15 为数据线,

总共 16 根数据线。CEn 是芯片使能信号,低电平有效;OEn 是输出使能信号,低电平有效;

WEn 是写使能信号,低电平有效; BLEn 和 BHEn 分别是高字节控制和低字节控制信号;

探索者 STM32F4 开发板使用的是 TSOP44 封装的 XM8A51216 芯片,该芯片直接接在

STM32F4 的 FSMC 上,XM8A51216 原理图如图 41.1.2 所示:

05210444403c4a89e4127e130a4e105f.png

图 41.1.2 XM8A51216 原理图

从原理图可以看出,XM8A51216 同 STM32F4 的连接关系:

A[0:18]接 FMSC_A[0:18](不过顺序错乱了)

D[0:15]接 FSMC_D[0:15]

UB 接 FSMC_NBL1

LB 接 FSMC_NBL0

OE 接 FSMC_OE

WE 接 FSMC_WE

CS 接 FSMC_NE3

上面的连接关系,XM8A51216 的 A[0:18]并不是按顺序连接 STM32F4 的 FMSC_A[0:18],

不过这并不影响我们正常使用外部 SRAM,因为地址具有唯一性。所以,只要地址线不和数据

线混淆,就可以正常使用外部 SRAM。这样设计的好处,就是可以方便我们的 PCB 布线。

本章,我们使用 FSMC 的 BANK1 区域 3 来控制 XM8A51216,关于 FSMC 的详细介绍,

我们在第十八章已经介绍过,在第十八章,我们采用的是读写不同的时序来操作 TFTLCD 模块

(因为 TFTLCD 模块读的速度比写的速度慢很多),但是在本章,因为 XM8A51216 的读写时

间基本一致,所以,我们设置读写相同的时序来访问 FSMC。关于 FSMC 的详细介绍,请大家

看第十八章和《STM32F4xx 中文参考手册》。

XM8A51216 就介绍到这,最后,我们来看看实现 XM8A51216 的访问,需要对 FSMC 进

行哪些配置。步骤如下:

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

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

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

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

__HAL_RCC_FSMC_CLK_ENABLE();配置 IO 口为复用输出的关键行代码为: GPIO_Initure.Mode=GPIO_MODE_AF_PP; //推挽复用GPIO_Initure.Alternate=GPIO_AF12_FSMC;//复用为 FSMC 

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

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

16 位宽,读写共用一个时序寄存器。这个是通过调用函数 HAL_SRAM_Init 来实现的,函数原

型为:

HAL_StatusTypeDef HAL_SRAM_Init(SRAM_HandleTypeDef *hsram,FMC_NORSRAM_TimingTypeDef *Timing, FMC_NORSRAM_TimingTypeDef *ExtTiming)

通过以上几个步骤,我们就完成了 FSMC 的配置,可以访问 XM8A51216 了,这里还需要

注意,因为我们使用的是 BANK1 的区域 3,所以 HADDR[27:26]=10,故外部内存的首地址为

0X68000000。

41.2 硬件设计

本章实验功能简介:开机后,显示提示信息,然后按下 KEY0 按键,即测试外部 SRAM 容

量大小并显示在 LCD 上。按下 KEY1 按键,即显示预存在外部 SRAM 的数据。DS0 指示程序

运行状态。

本实验用到的硬件资源有:

1) 指示灯 DS0

2) KEY0 和 KEY1 按键

3) 串口

4) TFTLCD 模块

5) XM8A51216

这些我们都已经介绍过(XM8A51216 与 STM32F4 的各 IO 对应关系,请参考光盘原理图),

接下来我们开始软件设计。

41.3 软件设计

打开上一章的工程,由于本章没用到 OV2640 和定时器等相关代码,所以,先去掉这些代

码(此时 HARDWARE 组下仅剩:led.c、ILI93xx.c 和 key.c 三个文件)。

然后,在 HARDWARE 文件夹下新建 XMRAM 和 SRAM 的文件夹。可以看到,我们在 SRAM

的文件夹增加了 sram.c 文件以及头文件 sram.h。在 XMRAM 文件夹增加了 XMRAM 库以及库

对应的头文件 XMRAM.h。打开 XMRAM.h 可以看到,XMRAM 库只有一个函数接口,我们只

需要在 FSMC_SRAM_Init()函数开始调用即可,详细代码请看 sram.c。FSMC 初始化相关配置

和 定 义 都 在 这 两 个 文 件 中 。 同 时 还 引 入 了 FSMC 固 件 库 文 件 stm32f4xx_fsmc.c 和

stm32f4xx_fsmc.h 文件。

打开 sram.c 文件,输入如下代码:

#include "sram.h"#include "usart.h"#include "XMRAM.h"//使用 NOR/SRAM 的 Bank1.sector3,地址位 HADDR[27,26]=10//对 XM8A51216,地址线范围为 A0~A18#define Bank1_SRAM3_ADDR ((u32)(0x68000000))//初始化外部 SRAMvoid FSMC_SRAM_Init(void){XmRamInit(); //初始化 XMRAM 20191024delay_us(100);GPIO_InitTypeDef GPIO_Initure;FSMC_NORSRAM_TimingTypeDef FSMC_ReadWriteTim; __HAL_RCC_FSMC_CLK_ENABLE(); //使能 FSMC 时钟 __HAL_RCC_GPIOD_CLK_ENABLE(); //使能 GPIOD 时钟 __HAL_RCC_GPIOE_CLK_ENABLE(); //使能 GPIOE 时钟 __HAL_RCC_GPIOF_CLK_ENABLE(); //使能 GPIOF 时钟 __HAL_RCC_GPIOG_CLK_ENABLE(); //使能 GPIOG 时钟……省略 IO 设置代码SRAM_Handler.Instance=FSMC_NORSRAM_DEVICE;SRAM_Handler.Extended=FSMC_NORSRAM_EXTENDED_DEVICE;SRAM_Handler.Init.NSBank=FSMC_NORSRAM_BANK3; //使用 NE3SRAM_Handler.Init.DataAddressMux=FSMC_DATA_ADDRESS_MUX_DISABLE;//地址/数据线不复用SRAM_Handler.Init.MemoryType=FSMC_MEMORY_TYPE_SRAM; //SRAMSRAM_Handler.Init.MemoryDataWidth=FSMC_NORSRAM_MEM_BUS_WIDTH_16; //16 位数据宽度SRAM_Handler.Init.BurstAccessMode=FSMC_BURST_ACCESS_MODE_DISABLE;//是否使能突发访问,仅对同步突发存储器有效,此处未用到SRAM_Handler.Init.WaitSignalPolarity=FSMC_WAIT_SIGNAL_POLARITY_LOW;//等待信号的极性,仅在突发模式访问下有用SRAM_Handler.Init.WaitSignalActive=FSMC_WAIT_TIMING_BEFORE_WS;//存储器是在等待周期之前的一个时钟周期还是等待周期期间使能 NWAITSRAM_Handler.Init.WriteOperation=FSMC_WRITE_OPERATION_ENABLE;//存储器写使能SRAM_Handler.Init.WaitSignal=FSMC_WAIT_SIGNAL_DISABLE;//等待使能位,此处未用到SRAM_Handler.Init.ExtendedMode=FSMC_EXTENDED_MODE_DISABLE; //读写使用相同的时序SRAM_Handler.Init.AsynchronousWait=FSMC_ASYNCHRONOUS_WAIT_DISABLE;//是否使能同步传输模式下的等待信号,此处未用到SRAM_Handler.Init.WriteBurst=FSMC_WRITE_BURST_DISABLE; //禁止突发写SRAM_Handler.Init.ContinuousClock=FSMC_CONTINUOUS_CLOCK_SYNC_ASYNC;//FMC 读时序控制寄存器FSMC_ReadWriteTim.AddressSetupTime=0x02;//地址建立时间(ADDSET)为 2 个 HCLK 1/168M=6ns*16=12nsFSMC_ReadWriteTim.AddressHoldTime=0x00;//地址保持时间(ADDHLD)模式 A 未用到FSMC_ReadWriteTim.DataSetupTime=0x03;//数据保存时间为 3 个 HCLK=6*3=18nsFSMC_ReadWriteTim.BusTurnAroundDuration=0X00;FSMC_ReadWriteTim.AccessMode=FSMC_ACCESS_MODE_A;//模式 AHAL_SRAM_Init(&SRAM_Handler,&FSMC_ReadWriteTim,&FSMC_ReadWriteTim);}//在指定地址(WriteAddr+Bank1_SRAM3_ADDR)开始,连续写入 n 个字节.//pBuffer:字节指针//WriteAddr:要写入的地址//n:要写入的字节数void FSMC_SRAM_WriteBuffer(u8 *pBuffer,u32 WriteAddr,u32 n){for(;n!=0;n--){*(vu8*)(Bank1_SRAM3_ADDR+WriteAddr)=*pBuffer;WriteAddr++;pBuffer++;}}//在指定地址((WriteAddr+Bank1_SRAM3_ADDR))开始,连续读出 n 个字节.//pBuffer:字节指针//ReadAddr:要读出的起始地址//n:要写入的字节数void FSMC_SRAM_ReadBuffer(u8 *pBuffer,u32 ReadAddr,u32 n){for(;n!=0;n--){*pBuffer++=*(vu8*)(Bank1_SRAM3_ADDR+ReadAddr);ReadAddr++;}}

此部分代码包含 3 个函数,FSMC_SRAM_Init 函数用于初始化,包括 FSMC 相关 IO 口的

初始化以及 FSMC 配置;FSMC_SRAM_WriteBuffer 和 FSMC_SRAM_ReadBuffer 这两个函数分

别用于在外部 SRAM 的指定地址写入和读取指定长度的数据(字节数)。

这里需要注意的是:FSMC 当位宽为 16 位的时候,HADDR 右移一位同地址对其,但是

ReadAddr 我们这里却没有加 2,而是加 1,是因为我们这里用的数据为宽是 8 位,通过 UB 和

LB 来控制高低字节位,所以地址在这里是可以只加 1 的。另外,因为我们使用的是 BANK1,

区域 3,所以外部 SRAM 的基址为:0x68000000。

头文件 sram.h 内容比较简洁,主要是一些函数申明,这里我们不做过多讲解。

最后我们来看看 main.c 文件代码如下:

u32 testsram[250000] __attribute__((at(0X68000000)));//测试用数组//外部内存测试(最大支持 1M 字节内存测试)void fsmc_sram_test(u16 x,u16 y){u32 i=0;u8 temp=0;u8 sval=0;//在地址 0 读到的数据 LCD_ShowString(x,y,239,y+16,16,"Ex Memory Test: 0KB");//每隔 4K 字节,写入一个数据,总共写入 256 个数据,刚好是 1M 字节for(i=0;i<1024*1024;i+=4096){FSMC_SRAM_WriteBuffer(&temp,i,1);temp++;}//依次读出之前写入的数据,进行校验for(i=0;i<1024*1024;i+=4096){FSMC_SRAM_ReadBuffer(&temp,i,1);if(i==0)sval=temp;else if(temp<=sval)break;//后面读出的数据一定要比第一次读到的数据大.LCD_ShowxNum(x+15*8,y,(u16)(temp-sval+1)*4,4,16,0);//显示内存容量}}int main(void){u8 key;u8 i=0;u32 ts=0; HAL_Init();//初始化 HAL 库 Stm32_Clock_Init(336,8,2,7);//设置时钟,168Mhzdelay_init(168);//初始化延时函数uart_init(115200);//初始化 USARTusmart_dev.init(84);//初始化 USMARTLED_Init();//初始化 LEDKEY_Init();//初始化 KEYLCD_Init(); //初始化 LCDSRAM_Init();//初始化外部 SRAMPOINT_COLOR=RED;//设置字体为红色LCD_ShowString(30,50,200,16,16,"Explorer STM32F4");LCD_ShowString(30,70,200,16,16,"SRAM TEST");LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK");LCD_ShowString(30,110,200,16,16,"2017/4/18");LCD_ShowString(30,130,200,16,16,"KEY0:Test Sram");LCD_ShowString(30,150,200,16,16,"KEY1:TEST Data");POINT_COLOR=BLUE;//设置字体为蓝色for(ts=0;ts<250000;ts++)testsram[ts]=ts;//预存测试数据 while(1){key=KEY_Scan(0);//不支持连按if(key==KEY0_PRES)fsmc_sram_test(60,170);//测试 SRAM 容量else if(key==KEY1_PRES)//打印预存测试数据{for(ts=0;ts<250000;ts++)LCD_ShowxNum(60,190,testsram[ts],6,16,0);//显示测试数据}else delay_ms(10);i++;if(i==20)//DS0 闪烁.{i=0;LED0=!LED0;}}}

此部分代码除了 mian 函数,还有一个 fsmc_sram_test 函数,该函数用于测试外部 SRAM

的容量大小,并显示其容量。main 函数则比较简单,我们就不细说了。

此段代码,我们定义了一个超大数组 testsram,我们指定该数组定义在外部 sram 起始地址

(__attribute__((at(0X68000000)))),该数组用来测试外部 SRAM 数据的读写。注意该数组的定

义方法,是我们推荐的使用外部 SRAM 的方法。如果想用 MDK 自动分配,那么需要用到分散

加载还需要添加汇编的 FSMC 初始化代码,相对来说比较麻烦。而且外部 SRAM 访问速度又远

不如内部 SRAM,如果将一些需要快速访问的 SRAM 定义到了外部 SRAM,将会严重拖慢程序

运行速度。而如果以我们推荐的方式来分配外部 SRAM,那么就可以控制 SRAM 的分配,可以

针对性的选择放外部还是放内部,有利于提高程序运行速度,使用起来也比较方便。

41.4 下载验证

在代码编译成功之后,我们通过下载代码到 ALIENTEK 探索者 STM32F4 开发板上,得到

如图 41 在代码编译成功之后,我们通过下载代码到 ALIENTEK 探索者 STM32F4 开发板上,

得到如图 41.4.1 所示界面:

920c8f88fec558e764886d5475b2381d.png

图 41.4.1 程序运行效果图

此时,我们按下 KEY0,就可以在 LCD 上看到内存测试的画面,同样,按下 KEY1,就可

以看到 LCD 显示存放在数组 testsram 里面的测试数据,如图 41.4.2 所示:

5e7490bf43901c68d40d8f560a4c4855.png

图 41.4.2 外部 SRAM 测试界面

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值