zoukankan      html  css  js  c++  java
  • STM32外扩SRAM

    这两天调试STM32F103外扩SRAM,将调试过程中遇到的问题记录下,SRAM的规格是256K*16的异步SRAM,地址总线为18,数据线宽度为16.

    在调试过程中遇到一些小问题,希望读者能少走些弯路。

    先看一下FSMC内存映射图:

    由图可知,stm32的FSMC模块分为四个bank,每个bank的大小事64M。

     下面这张图是FSMC各个块的信号分配图。

     

    由上图可知,bank1 NOR/PSRAM可以分为4个子块,由FSMC_NE[4:1]来选择使能哪个子块。

    例如:每小块NOR/PSRAM的64M地址范围如下:

     第一块:6000 0000h--63ff ffffh

     第二块:6400 0000h--67ff ffffh

     第二块:6800 0000h--6bff ffffh

     第三块:6c00 0000h--6fff ffffh

    我们可以通过选择HADDR[27:26]来确定当前使用的是哪个64M的分地址块,如下图所示:

    这里我使用的是100脚的stm32,只有NE1引脚可用,也就是说只能用Bank1的存储块1,即FSMC_Bank1_NORSRAM1。

    我用的STM32是100脚的,地址和数据总线是复用的,那么需要用到锁存器来区分地址和数据,而锁存信号是NADV输出的,注意看图173和图174的NADV信号在输出地址时是低电平,输出数据时是高电平,所以锁存器要选择一个高电平锁存或者加个反向器。

    在配置STM32的FSMC的寄存器时要注意下面两句话:

    //使能复用模式 
    FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Enable;
    //注意这里不是FSMC_MemoryType_SRAM而是FSMC_MemoryType_NOR,手册上说要想输出NADV信号只能设置成FSMC_MemoryType_NOR。
     FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_NOR

    SRAM参考原理图如下图:

    stm32的FSMC功能用到的复用IO口比较多,配置时需要细点心:

    /*
     *PD14(DA0) PD15(DA1) PD0(DA2) PD1(DA3) PE7~PE15(DA4~DA12) PD8~PD10(DA13~DA15) PD11(A16) PD12(A17)
     *PD5(WE) PD7(NE1) PD4(OE)
     *PE0(BL0) PE1(BL1) NADV(PB7)
     */
    void sram_gpio_configration(void)
    {
     GPIO_InitTypeDef GPIO_InitStructure;
    
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 |
                                   GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | 
                                   GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_14 | GPIO_Pin_15; 
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
     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_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_Init(GPIOE, &GPIO_InitStructure);
    
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_Init(GPIOB, &GPIO_InitStructure);
    }

    下面是具体的FSMC寄存器配置:

    void fsmc_for_sram_configration(void)
    {
     FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
     FSMC_NORSRAMTimingInitTypeDef  FSMC_NORSRAMTimingInitStructure;
     
     FSMC_NORSRAMTimingInitStructure.FSMC_AddressSetupTime = 15;
     FSMC_NORSRAMTimingInitStructure.FSMC_AddressHoldTime = 15;
     FSMC_NORSRAMTimingInitStructure.FSMC_DataSetupTime = 255
    FSMC_NORSRAMTimingInitStructure.FSMC_BusTurnAroundDuration = 15;//以上这四个参数在调试的时候可以先设置为最大值,程序调通后在根据器件手册和STM32手册计算出合适的值 FSMC_NORSRAMTimingInitStructure.FSMC_CLKDivision = 0;//synchronize memory下面这两个参数是为同步器件准备的 FSMC_NORSRAMTimingInitStructure.FSMC_DataLatency = 0; FSMC_NORSRAMTimingInitStructure.FSMC_AccessMode = FSMC_AccessMode_B;//复用总线模式下,访问模式设置为ModeB FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;
    FSMC_NORSRAMInitStructure.FSMC_DataAddressMux
    = FSMC_DataAddressMux_Enable; FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_NOR;//注意这里要设置成NOR,因为只有设置为NOR,才能输出NADV信号
    FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b; FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable; FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable; FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable; FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState; FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable; FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable; FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable; FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable; FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &FSMC_NORSRAMTimingInitStructure; FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &FSMC_NORSRAMTimingInitStructure; FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); /* - BANK 1 (of NOR/SRAM Bank 0~3) is enabled */ FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE); }

     外部SRAM的访问: 

    在访问SRAM时纠结了许久,最后终于弄明白了。网上看了很多资料,有说在访问时要先将地址偏移,有说直接访问就行。最后经过测试发现访问片外SRAM时跟访问内部RAM一样,直接访问就可以了,FSMC都帮我们做好了。

    当访问字节数据时:*((u8*)(BANK1_SRAM_BASE+offset))。1.读取SRAM数据时,将offset设为0x00,用示波器测试SRAM的A0地址信号是低,当offset为0x01时,用示波器测试SRAM的A0地址信号也是低,当offset为0x02和0x03时SRAM的A0地址信号是高,这说明当字节访问时地址确实是偏移了1位,原因是SRAM是16位器件(SRAM的1个地址存储16位数据),一次可以访问2个字节的数据,这个时候FSMC将根据offset值判断,访问的是高8位还是低8位,即如果offset的最低位是0则访问的是16位数据的低8位,如果offset的最低位是1则访问的是16位数据的高8位。2. 向SRAM写数据时,道理也是一样的,只是写的时候通过BL[1:0]两个管脚控制写高字节还是低字节。

    当访问半字数据时:*((u16*)(BANK1_SRAM_BASE+offset))。1.读取SRAM数据时,这个时候要注意了,FSMC在访问的时候要看offset的值是不是半字对齐的。如果offset是0x00,则直接访问的是SRAM的0x00地址处的16位数据,当offset是0x01时,FSMC是分两次访问的,第一次是访问SRAM的0x00地址的高字节,第二次是访问SRAM的0x01地址处的低字节(SRAM的1个地址存储16位数据),通过用示波器测量SRAM的A0地址信号得到,信号是先低在高的一个脉冲,验证了前面的说法。2. 向SRAM写数据时,道理也是一样的,只是写的时候通过BL[1:0]两个管脚控制写高字节还是低字节。

     当访问字数据时:访问字时,FSMC分为2个半字访问。

    总结:外部SRAM就跟片内SRAM一样用就行了。

  • 相关阅读:
    Dijjer:给流媒体插上 P2P 的同党
    gnomecolorchooser:桌面颜色设置小对象
    LXPanel:轻巧疾速的桌面面板
    批量创立缩略图
    SPE IDE:跨平台的 Python IDE
    主管的信
    使用 TRegistry 类[2]: 读取 IE 浏览器的 Start Page
    用多媒体库 Bass.dll 播放 mp3 [15] 设置与获取播放速度
    用多媒体库 Bass.dll 播放 mp3 [14] 频率均衡器
    用多媒体库 Bass.dll 播放 mp3 [13] 混响(Reverb)效果
  • 原文地址:https://www.cnblogs.com/zpehome/p/3477011.html
Copyright © 2011-2022 走看看