历史上的今天
返回首页

历史上的今天

今天是:2026年03月23日(星期一)

正在发生

2023年03月23日 | STM32CubeMX系列 | 外部SRAM

2023-03-23 来源:zhihu

1.外部SRAM简介

本例程使用的STM32F103ZET6本身有64K字节的SRAM,一般应用已经足够;不过在一些对内存要求高的场合,比如跑算法或者GUI等,就需要外扩SRAM来满足大内存使用的需求。这里我们使用了一颗256K字节容量的SRAM芯片:IS62WV12816,利用STM32F1的FSMC控制该SRAM芯片,实现对该SRAM芯片的访问控制

IS62WV12816是一种16位宽128K(128*2,即256K字节)容量的CMOS静态内存芯片,它有高速访问、低功耗、兼容TTL电平接口、全静态操作(不需要刷新和时钟电路)、三态输出和字节控制(支持高/低字节控制)等特点

IS62WV12816的引脚以及对应的引脚功能如下图示:

A0 ~ A16为地址线,总共17根地址线(可访问 217 = 128K字节空间);I/O0 ~ I/O15为数据线,总共16根数据线;CS1(低电平有效)和CS2(高电平有效)都是片选信号;WE为输入使能信号(写信号);OE为输出使能信号(读信号);UB和LB分别是高字节和低字节控制信号

FSMC的相关介绍可参考TFTLCD显示例程中的FSMC介绍部分

2. 硬件设计

D1指示灯用来提示系统运行状态,按键用来控制IS62WV12816数据读写,TFTLCD和串口1用来显示读写的内容

  • D1指示灯

  • K_UP/K_DOWN

  • USART1

  • TFTLCD模块

  • IS62WV12816

从电路图中可以看到IS62WV12816和STM32F1的连接线路: A0 ~ A16连接在FSMC_A0 ~ FSMC_A16上(连接顺序可以打乱,因为地址是固定的) I/O0 ~ I/O15连接在FSMC_D0 ~ FSMC_D15上(连接顺序不能打乱,否则读写数据将出错) UB和LB连接在FSMC_NBL1 和 FSMC_NBL0上 OE和WE分别连接在FSMC_NOE 和 FSMC_NWE上 CE连接在FSMC_NE3上

由于TFTLCD核SRAM共用FSMC总线,因此他们通过不同片选分时复用,互不影响

3. 软件设计

3.1 STM32CubeMX设置

  • RCC设置外接HSE,时钟设置为72M

  • PC0设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平

  • PA0设置为GPIO输入模式、下拉模式;PE3设置为GPIO输入模式、上拉模式

  • USART1选择为异步通讯方式,波特率设置为115200Bits/s,传输数据长度为8Bit,无奇偶校验,1位停止位

  • 激活FSMC,详细请参考TFTLCD显示章节的设置

  • 输入工程名,选择工程路径(不要有中文),选择MDK-ARM V5;勾选Generated periphera initialization as a pair of ‘.c/.h’ files per IP ;点击GENERATE CODE,生成工程代码

由于TFTLCD使用的Bank1_sector4和SRAM使用的Bank1_sector3无法同时在CubeMX里设置分时复用,因此需要单独创建SRAM的FSMC初始化函数(可自行创建,也可另外创建一个CubeMX工程,按下图设置后将生成的相关FSMC初始化代码拷贝到当前工程源码中并稍作修改)


3.2 MDK-ARM编程

  • 添加按键驱动文件key.c和key.h,参考按键输入例程

  • 添加TFTLCD驱动文件tftlcd.c 和tftlcd.h,参考TFTLCD显示例程

  • 添加IS62WV12816芯片驱动文件sram.c和sram.h

#define Bank1_SRAM3_ADDR    ((uint32_t)(0x68000000))    //Bank1区域3的起始地址 

SRAM_HandleTypeDef SRAM_Handler;    //定义SRAM句柄

//SRAM的FSMC初始化函数

void FSMC_SRAM_Init(void){  

    GPIO_InitTypeDef GPIO_InitStruct;

    FSMC_NORSRAM_TimingTypeDef FSMC_ReadWriteTim; 

    __HAL_RCC_FSMC_CLK_ENABLE();           

    __HAL_RCC_GPIOD_CLK_ENABLE();              

    __HAL_RCC_GPIOE_CLK_ENABLE();               

    __HAL_RCC_GPIOF_CLK_ENABLE();              

    __HAL_RCC_GPIOG_CLK_ENABLE();               

    GPIO_InitStruct.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_InitStruct.Mode = GPIO_MODE_AF_PP;

    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

    HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3 

                         |GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_10;

    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

    HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);

    GPIO_InitStruct.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_InitStruct.Mode = GPIO_MODE_AF_PP;

    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11 

                          |GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1 

                          |GPIO_PIN_4|GPIO_PIN_5;

    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);  


    SRAM_Handler.Instance=FSMC_NORSRAM_DEVICE;                

    SRAM_Handler.Extended=FSMC_NORSRAM_EXTENDED_DEVICE;    


    SRAM_Handler.Init.NSBank=FSMC_NORSRAM_BANK3;                        //使用NE3

    SRAM_Handler.Init.DataAddressMux=FSMC_DATA_ADDRESS_MUX_DISABLE;     //地址/数据线不复用

    SRAM_Handler.Init.MemoryType=FSMC_MEMORY_TYPE_SRAM;                 //SRAM

    SRAM_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;      

    SRAM_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;              //禁止突发写

    //FSMC读时序控制器

    FSMC_ReadWriteTim.AddressSetupTime=0x00;        //地址建立时间(ADDSET)为1个HCLK

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

    FSMC_ReadWriteTim.DataSetupTime=0x08;           //数据保持时间(DATAST)为9个HCLK

    FSMC_ReadWriteTim.BusTurnAroundDuration=0X00;

    FSMC_ReadWriteTim.AccessMode=FSMC_ACCESS_MODE_A;    //模式A

    HAL_SRAM_Init(&SRAM_Handler,&FSMC_ReadWriteTim,&FSMC_ReadWriteTim); 

}

//n向指定地址写数据

void FSMC_SRAM_WriteBuffer(uint8_t *pBuffer,uint32_t WriteAddr,uint32_t n){

    for(;n!=0;n--){     // n表示要连续写入的字节个数

        *(vu8*)(Bank1_SRAM3_ADDR + WriteAddr) = *pBuffer;

        WriteAddr++;    //要写入的地址

        pBuffer++;      //要写入的数据的指针

    }

}

//从指定地址读数据

void FSMC_SRAM_ReadBuffer(uint8_t *pBuffer,uint32_t ReadAddr,uint32_t n){

    for(;n!=0;n--){     // n表示要连续读出的字节个数

        *pBuffer++=*(vu8*)(Bank1_SRAM3_ADDR+ReadAddr);  //存放读出的数据

        ReadAddr++;     //要读出的起始地址

    }

}

//      

void ExSRAM_Cap_Test(uint16_t x,uint16_t y){

    uint8_t writeData = 0xf0, readData;

    uint16_t cap=0;

    uint32_t addr;  

    addr = 1024;    //从1KB位置开始计算    

    LCD_ShowString(x,y,239,y+16,16,"ExSRAM Cap:   0KB"); 


    while(1){

        FSMC_SRAM_WriteBuffer(&writeData, addr, 1);

        FSMC_SRAM_ReadBuffer(&readData,addr,1);


        if(readData == writeData){  //检查读出的数据是否与写入的数据一样

            cap++;      //如果相同表示写入/读出成功,容量加1(单位KB)

            addr += 1024;   //地址加1024

            readData = 0;

            if(addr > 256 * 1024)   //IS62WV12816的容量为256KB

                break;   

        }

        else

            break;  

    }

    LCD_ShowxNum(x+11*8,y,cap,4,16,0);  //LCD上显示内存容量

    printf("SRAM Menmory Size:%dKBrn",cap);

}

在main.c文件下编写SRAM测试代码

int main(void){

    /* USER CODE BEGIN 1 */

    uint8_t key;

    uint8_t text_buf[] = "This is SRAM testing...";

    uint8_t textlen = sizeof(text_buf);

    uint8_t read_buf[textlen];

    /* USER CODE END 1 */

    HAL_Init();

    SystemClock_Config();

    MX_GPIO_Init();

    MX_FSMC_Init();

    MX_USART1_UART_Init();

    /* USER CODE BEGIN 2 */

    TFTLCD_Init();

    FSMC_SRAM_Init();


    FRONT_COLOR=BROWN;

    LCD_DrawRectangle(5,5,235,95);

    FRONT_COLOR=BLACK;

    LCD_ShowString(10,10,tftlcd_data.width,tftlcd_data.height,16,"ANDYXI STM32F1");

    LCD_ShowString(10,30,tftlcd_data.width,tftlcd_data.height,16,"STM32CubeMx SRAM");

    LCD_ShowString(10,50,tftlcd_data.width,tftlcd_data.height,16,"ExSRAM Test");

    LCD_ShowString(10,70,tftlcd_data.width,tftlcd_data.height,16,"K_UP:Write   K_DOWN:Read");


    FRONT_COLOR=RED;

    ExSRAM_Cap_Test(10,110); 

    FRONT_COLOR=MAGENTA;

    LCD_ShowString(10,130,tftlcd_data.width,tftlcd_data.height,16,"Write:");

    LCD_ShowString(10,150,tftlcd_data.width,tftlcd_data.height,16,"Read :");

  /* USER CODE END 2 */


  /* Infinite loop */

  /* USER CODE BEGIN WHILE */

    while(1){

        key = KEY_Scan(0);

        if(key == KEY_UP_PRES){     //KEY_UP按下写数据到SRAM

            FSMC_SRAM_WriteBuffer(text_buf,0,textlen);

            printf("SRAM_Write:%srn",text_buf);

推荐阅读

史海拾趣

Chauvin Arnoux公司的发展小趣事

1934年,Chauvin Arnoux再次引领技术潮流,发明了电流互感器钳形表,这是世界上第一个非接触式电流表。这一发明不仅改变了电流测量的传统方式,而且极大地提高了测量的便捷性和安全性。非接触式电流表的出现,为电气工程师和技术人员提供了更为高效和安全的测量工具,推动了电气行业的发展。

比亚迪(BYD)公司的发展小趣事

随着市场的不断变化和竞争的加剧,比亚迪意识到品牌形象的重要性。2015年,比亚迪推出了全新的“次世代品牌形象”,以更加年轻、前卫的形象与消费者进行连接。这一举措有效地提升了比亚迪的品牌认知度和美誉度,为其在全球范围内的市场推广提供了有力支持。同时,比亚迪继续深化全球化战略,加大在全球范围的市场开拓和品牌推广力度。通过与国际知名企业的合作和技术交流,比亚迪不断提升自身的技术水平和市场竞争力。

扬州国芯(Gcore)公司的发展小趣事

进入21世纪,新能源汽车市场逐渐兴起。比亚迪凭借在电池领域的深厚积累,果断转型进入新能源汽车领域。2000年,比亚迪推出了全球第一款纯电动乘用车——比亚迪e6,这一创新产品引起了市场的广泛关注。此后,比亚迪不断加大对新能源汽车的研发和生产投入,推出了多款具有竞争力的新能源汽车产品。同时,比亚迪还积极涉足光伏和LED照明等其他领域,不断拓展其电子业务版图。

Comair Rotron公司的发展小趣事

1987年,为了更好地适应市场变化和拓展国际业务,Comair决定进行品牌重塑,将公司名称更改为“Comair Rotron”。同时,公司还在墨西哥建立了新的制造工厂,并在圣地亚哥设立了销售和工程中心,以支持其在北美地区的业务发展。这一举措不仅提升了Comair Rotron的品牌形象,也为其在全球范围内的市场拓展奠定了坚实基础。

GTK UK Ltd公司的发展小趣事
选择响应速度快、灵敏度高、稳定性好的光电传感器。
Electronic Sensor + Resistor GmbH公司的发展小趣事

品质是ESR公司的生命线。公司始终坚持“质量第一、用户至上”的原则,建立了完善的质量管理体系和严格的质量控制流程。从原材料采购、生产加工到成品检验等各个环节都实行严格的质量控制措施,确保每一件产品都符合高品质标准。

此外,ESR公司还建立了完善的售后服务体系,为用户提供及时、专业的技术支持和解决方案。这种对品质的执着追求和对用户的真诚服务赢得了客户的广泛赞誉和信赖。

问答坊 | AI 解惑

国赛最新题目

本帖最后由 paulhyde 于 2014-9-15 09:06 编辑 各位参加09国赛的同学 有可靠的题目不要私藏了 大家研究研究  …

查看全部问答>

数据总线操作时遇到的难题,请大家指点一下

在我的电路板上(现在只焊了最小系统部分)对LPC2292进行数据总线操作时,用示波器测到脉冲的高电平只有600mV样子,加了10K上拉电阻之后,电平也只能到1.5V样子,同样的程序我下载到Magic ARM2200开发板上时,用示波器测到的脉冲的高电平能达到3.3V ...…

查看全部问答>

波特图的相位是这样看的吗?

先选一个参考位,为-180.那么-90~-180为相位超前。比-180小的为相位滞后。对吗? …

查看全部问答>

全国电子设计大赛赛后感

本帖最后由 paulhyde 于 2014-9-15 09:23 编辑 国大学生电子设计竞赛给我们提供了一个培养创新、协作和钻研精神的平台,是大学生展现自己、积累经验的舞台。激情创造,精彩无限!参加过“索尼杯”电子设计竞赛的人,都从中体会到了奋斗的快乐、团 ...…

查看全部问答>

ADC问题

大家好,关于ADC问题请教大家:1)我要用到20通道AD,选的芯片是STM32F103ZCT6,用到ADC3、ADC1,设置如下:void ADC3_Configuration(void){    ADC_InitTypeDef ADC_InitStructure;    &n ...…

查看全部问答>

05.16【每日一问】:PWM

今天起晚了 想早点起来发问题的   大家讨论讨论啊   你是怎样理解或者计算PWM的精度和分辨率的   可以用实际的程序来讨论或者计算 …

查看全部问答>

见过双卡双待的,见过双电池的手机吗

看电池的商标,打的是基伍,在印度曾经是市场占有率第一哦!…

查看全部问答>

提交试卷的时候出现这个

在提交试卷的时候出现了atel学习平台的登陆界面,是不是就是提交失败了 ?…

查看全部问答>

俞洪敏:跟什么样的老板会倒霉

    “年轻人进入职场,都希望先拿高薪,再认真工作,心里想的是我工资待遇不够,凭什么努力工作。但实际上最后真正在职场取胜的,是那些不计较个人得失辛勤工作,持续不懈努力的人。”俞敏洪告诉刚入职场的年轻人,不要太计较一开始的薪 ...…

查看全部问答>