1.闇练 FSMC 模块
2.理解外部 SRAM 的操作。
9.1 IS62WV51216 简介

IS62WV51216 是 ISSI(Integrated Silicon Solution, Inc)公司生产的一颗 16位宽 512K(51216,即 1M 字节)容量的 CMOS 静态内存芯片。它拥有如下几个特点:
1)高速访问。具有 45ns/55ns 访问速率
2)低功耗。
-36mW(范例)操作功耗。
-12uW(范例)待机功耗。
3)兼容 TTL 电平接口。
4)全静态操作。不须要刷新和时钟电路。
5)字节掌握功能。支持高/低字节掌握。
IS62WV51216 引脚构造如下:
它们的利用功能如下:
9.2 IS62WV51216 的事理图
IS62WV51216 事理图接线很随意马虎理解,我们这里利用的 FSMC 模块来掌握这个外部 SRAM,从事理图上面,看出我们利用的是 FSMC_NE3 作片选,那么我们利用的是第三个内存块。
9.3 例程程序
在学习 LCD 彩屏的时候,我们就已经学习过什么是 FSMC 了,我们这里就不重复讲了,紧张差异是:
1)FSMC_MemoryType: 选择利用内存类型选择 SRAM 模式,即:FSMC_MemoryType_SRAM。
2)FSMC_ExtendedMode:是否开启拓展模式,就不开启了,SRAM 的读写韶光相差不多,设置为:FSMC_ExtendedMode_Disable。
3)FSMC_Bank:选择 bank 的时候,我们这里利用的是第三个内存块,以是设置为:FSMC_Bank1_NORSRAM3。
详细初始化程序如下:
1. SRAM 初始化程序
void SRAM_Config(void){/ 初始化函数 /GPIO_InitTypeDef GPIO_InitStructure;FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;FSMC_NORSRAMTimingInitTypeDef FSMC_NORSRAMTiming;/------------------------------------------------------------------------------------//------------------- 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);/ ---------------------------------------------------------------------------------- // ------------ 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_AsynchronousWait_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);}
这个函数,包含了 GPIO 的初始化和 FSMC 的初始化,要把稳的是一样平常初始化的时候要一定要把稳打开时钟。
2. SRAM 写入程序
void SRAM_WriteBuffer(uint16_t writeBuf, uint32_t writeAddr, uint32_tlength){ while(length--) /!< while there is data to write /{ /!< Transfer data to the memory /(uint16_t ) (Bank1_SRAM3_ADDR + writeAddr) = writeBuf++;/ 十六位长度的是地址+2 / writeAddr += 2; }}
在这个函数中(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 位长度的。
3. 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;}}
这个程序恰好跟写入程序相似,只是操作恰好反过来了,大家参照写入程序,就可以理解了。
4. 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);}
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);}}}
这个主程序的效果是,在彩屏上面显示 SRAM 的大小,然后确当按 KEY_UP键的时候,读取前面写入 SRAM 里面的程序数据,然后通过串口发送到电脑上面,测试数据是 0~49。