打印
[STM32F1]

STM32基础篇 ——外部 SRAM 实验

[复制链接]
2185|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
实验目标:
1. 熟练 FSMC 模块
2. 了解外部 SRAM 的操作。
沙发
aizaixiyuanqian|  楼主 | 2018-2-28 12:01 | 只看该作者
IS62WV51216  简介
IS62WV51216 是 ISSI(Integrated Silicon Solution, Inc)公司生产的一颗 16
位宽 512K(512*16,即 1M 字节)容量的 CMOS 静态内存芯片。

使用特权

评论回复
板凳
aizaixiyuanqian|  楼主 | 2018-2-28 12:01 | 只看该作者
它拥有如下
几个特点:
1) 高速访问。具有 45ns/55ns 访问速度
2) 低功耗。
-36mW(典型)操作功耗。
-12uW(典型)待机功耗。
3) 兼容 TTL 电平接口。
4) 全静态操作。不需要刷新和时钟电路。
5) 字节控制功能。支持高/低字节控制。

使用特权

评论回复
地板
aizaixiyuanqian|  楼主 | 2018-2-28 12:03 | 只看该作者
IS62WV51216 引脚结构如下:

使用特权

评论回复
5
aizaixiyuanqian|  楼主 | 2018-2-28 12:06 | 只看该作者
它们的使用功能如下

使用特权

评论回复
6
aizaixiyuanqian|  楼主 | 2018-2-28 12:10 | 只看该作者
IS62WV51216 原理图

使用特权

评论回复
7
aizaixiyuanqian|  楼主 | 2018-2-28 12:15 | 只看该作者
IS62WV51216 原理图接线很容易理解,我们这里使用的 FSMC 模块来控制
这个外部 SRAM,从原理图上面,看出我们使用的是 FSMC_NE3 作片选,那么
我们使用的是第三个内存块。

使用特权

评论回复
8
aizaixiyuanqian|  楼主 | 2018-2-28 12:15 | 只看该作者
在学习 LCD 彩屏的时候,我们就已经学习过什么是 FSMC 了,我们这里就
不重复讲了,主要区别是:
1) FSMC_MemoryType:选择使用内存类型选择 SRAM 模式,即:
FSMC_MemoryType_SRAM。
2) FSMC_ExtendedMode:是否开启拓展模式,就不开启了,SRAM 的读写
时间相差不多,设置为:FSMC_ExtendedMode_Disable。
3) FSMC_Bank:选择 bank 的时候,我们这里使用的是第三个内存块,所
以设置为:FSMC_Bank1_NORSRAM3。

使用特权

评论回复
9
aizaixiyuanqian|  楼主 | 2018-2-28 12:16 | 只看该作者
/*------------------------------------------------------------------------------------*/
/*------------------- GPIO Config ------------------------------------------------*/
/*-------------------------------------------------------------------------------------*/
/* 打开时钟使能 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD  |
RCC_APB2Periph_GPIOE  |  RCC_APB2Periph_GPIOF  |
RCC_APB2Periph_GPIOG, ENABLE);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 |
GPIO_Pin_5 | 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_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_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;
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_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;
GPIO_Init(GPIOF, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 |
GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_10;
GPIO_Init(GPIOG, &GPIO_InitStructure);

使用特权

评论回复
10
aizaixiyuanqian|  楼主 | 2018-2-28 12:17 | 只看该作者
/* ---------------------------------------------------------------------------------- */
/* ------------ FSMC Config ----------------------------------------------------- */
/* ------------------------------------------------------------------------------------ */
/* 设置读写时序,给 FSMC_NORSRAMInitStructure 调用 */
/* 地址建立时间,1 个 HCLK 周期, 1/36M = 27ns */
FSMC_NORSRAMTiming.FSMC_AddressSetupTime = 0x00;
/* 地址保持时间,1 个 HCLK 周期 */
FSMC_NORSRAMTiming.FSMC_AddressHoldTime = 0x00;
/* 数据建立时间,63 个 HCLK 周期 4/72 = 55ns */
FSMC_NORSRAMTiming.FSMC_DataSetupTime = 0x03;
/* 数据保持时间,1 个 HCLK 周期 */
FSMC_NORSRAMTiming.FSMC_DataLatency = 0x00;
/* 总线恢复时间设置 */
FSMC_NORSRAMTiming.FSMC_BusTurnAroundDuration = 0x00;
/* 时钟分频设置 */
FSMC_NORSRAMTiming.FSMC_CLKDivision = 0x00;
/* 设置模式,如果在地址/数据不复用时,ABCD 模式都区别不大 */
FSMC_NORSRAMTiming.FSMC_AccessMode = FSMC_AccessMode_A;
/* 设置 FSMC_NORSRAMInitStructure 的数据 */
/* FSMC 有四个存储块(bank),我们使用第一个(bank1) */
/* 同时我们使用的是 bank 里面的第 3 个 RAM 区 */
FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM3;
/* 这里我们使用 SRAM 模式 */
FSMC_NORSRAMInitStructure.FSMC_MemoryType  =
FSMC_MemoryType_SRAM;
/* 使用的数据宽度为 16 位 */
FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth  =
FSMC_MemoryDataWidth_16b;
/* FSMC_BurstAccessMode_Disable; */
FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode
=FSMC_BurstAccessMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity  =
FSMC_WaitSignalPolarity_Low;
FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait=FSMC_Asynchrono
usWait_Disable;
FSMC_NORSRAMInitStructure.FSMC_WrapMode  =
FSMC_WrapMode_Disable;
FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive  =
FSMC_WaitSignalActive_BeforeWaitState;
FSMC_NORSRAMInitStructure.FSMC_WaitSignal  =
FSMC_WaitSignal_Disable;
FSMC_NORSRAMInitStructure.FSMC_WriteBurst  =
FSMC_WriteBurst_Disable;
/* 设置写使能打开 */
FSMC_NORSRAMInitStructure.FSMC_WriteOperation  =
FSMC_WriteOperation_Enable;
/* 选择拓展模式使能,即设置读和写用相同的时序 */
FSMC_NORSRAMInitStructure.FSMC_ExtendedMode  =
FSMC_ExtendedMode_Disable;
/* 设置地址和数据复用使能不打开 */
FSMC_NORSRAMInitStructure.FSMC_DataAddressMux  =
FSMC_DataAddressMux_Disable;
/* 设置读写时序 */
FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct  =
&FSMC_NORSRAMTiming;
/* 设置写时序 */
FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct  =
&FSMC_NORSRAMTiming;
/* 打开 FSMC 的时钟 */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);
/*!< Enable FSMC Bank1_SRAM Bank */
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM3, ENABLE);
}


使用特权

评论回复
11
aizaixiyuanqian|  楼主 | 2018-2-28 12:17 | 只看该作者
这个函数,包含了 GPIO 的初始化和 FSMC 的初始化,要注意的是一般初始
化的时候要一定要注意打开时钟。

使用特权

评论回复
12
aizaixiyuanqian|  楼主 | 2018-2-28 12:25 | 只看该作者
SRAM 写入程序
void SRAM_WriteBuffer(uint16_t *writeBuf, uint32_t writeAddr, uint32_t
length)
{
while(length--) /*!< while there is data to write */
{
/*!< Transfer data to the memory */
*(uint16_t *) (Bank1_SRAM3_ADDR + writeAddr) = *writeBuf++;
/* 十六位长度的是地址+2 */
writeAddr += 2;
}
}

使用特权

评论回复
13
aizaixiyuanqian|  楼主 | 2018-2-28 12:25 | 只看该作者
在这个函数中*(uint16_t *) (Bank1_SRAM3_ADDR + writeAddr)这个部分可
能比较难理解,在 sram.h 中,程序定义了:
#define Bank1_SRAM3_ADDR ((uint32_t)(0x68000000))
也就是定义 bank1 的第三个内存块的首地址也就是 0x68000000,如果大家不
理解可以翻看一下技术手册。*(uint16_t *) (Bank1_SRAM3_ADDR + writeAddr)
的意思是,首先首地址加上偏移地址 writeAddr,然后将它转换为一个 16 位长度
的指针,然后在加一个*,那么就是这个指针所指向的地址数据。那么整句的意
思就是将 Bank1_SRAM3_ADDR + writeAddr 这个地址赋值。
而注意这里还有个 writeAddr += 2,为什么是加 2 呢?因为首先你定义的是
指针是 16 位长度的。

使用特权

评论回复
14
aizaixiyuanqian|  楼主 | 2018-2-28 12:58 | 只看该作者
SRAM 读取程序
void SRAM_ReadBuffer(uint16_t* readBuff, uint32_t readAddr, uint32_t length)
{
while(length--) /*!< while there is data to read */
{
/*!< Read a half-word from the memory */
*readBuff++ = *(__IO uint16_t*) (Bank1_SRAM3_ADDR + readAddr);
/* 十六位长度的是地址+2 */
readAddr += 2;
}
}

使用特权

评论回复
15
aizaixiyuanqian|  楼主 | 2018-2-28 13:05 | 只看该作者
SRAM 测试程序
void SRAM_Test(void)
{
uint8_t showData[5] = {0, 0, 0, 0, 0};
uint16_t writeData = 0xF0F0, readData, cap = 0;
uint32_t addr;
GUI_Show12Char(0, 84, "SRAM 的内存容量为: KB", RED,
BLACK);
/* 每隔一个 1KB 写入一个数据,然后读取数据,如果不相同,那么就
满了 */
addr = 1024; //从 1KB 位置开始算起
while(1)
{
SRAM_WriteBuffer(&writeData, addr, 1); //写入
SRAM_ReadBuffer(&readData, addr, 1); //读取
/* 查看读取到的数据是否跟写入数据一样 */
if(readData == writeData)
{
cap++;
addr += 1024;
readData = 0;
if(addr > 1024 * 1024) //SRAM 容量最大为 1MB
{
break;
}
}
else
{
break;
}
}
/* 显示读取到的容量 */
showData[0] = (cap % 10000 /1000) + '0';
showData[1] = (cap % 1000 /100) + '0';
showData[2] = (cap % 100 /10) + '0';
showData[3] = (cap % 10) + '0';
GUI_Show12Char(144, 84, showData, RED, BLACK);
}

使用特权

评论回复
16
aizaixiyuanqian|  楼主 | 2018-2-28 13:06 | 只看该作者
主程序
int main(void)
{
uint32_t i;
uint8_t dat[50], ledState;
/* 初始化 */
TFT_Init();
FLASH_Init();
USART1_Config(9600);
SRAM_Config();
KEY_Config();
LED_Config();
GUI_DisplayInit();
/* 测试 SRAM 大小 */
SRAM_Test();
/* 写入数据 */
for(i=0; i<50; i++)
{
dat[i] = i;
}
SRAM_WriteBuffer((uint16_t *)dat, 0x00, 50);
while(1)
{
/* 如果按上键通过串口发送测试数据 */
if(KEY_Scan() == KEY_UP)
{
SRAM_ReadBuffer((uint16_t *)dat, 0x00, 50);
for(i=0; i<50; i++)
{
printf(" %d, ", dat[i]); //发送测试数据
dat[i] = 0; //清零读取的数据
}
printf("\n"); //换行
}
/* LED 灯闪烁 */
i++;
if(i>0x2FFFF)
{
i = 0;
if(ledState == 0xFE)
{
ledState = 0xFF;
}
else
{
ledState = 0xFE;
}
LED_SetState(ledState);
}
}
}

使用特权

评论回复
17
aizaixiyuanqian|  楼主 | 2018-2-28 13:11 | 只看该作者
这个主程序的效果是,在彩屏上面显示 SRAM 的大小,然后的当按 KEY_UP
键的时候,读取前面写入 SRAM 里面的程序数据,然后通过串口发送到电脑上
面,测试数据是 0~49。

使用特权

评论回复
18
aizaixiyuanqian|  楼主 | 2018-2-28 13:12 | 只看该作者
这次的也是比较简单,大家了解即可。对FMSC操作比较有用。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

62

主题

1353

帖子

6

粉丝