精华内容
下载资源
问答
  • 异步FSMC的方式实现FPGA与STM32通信。自己写的程序。通过16位复用的地址信号线实现STM32与FPGA直接的数据交互。在FPGA中例化了位宽:16位;深度:4096 word的 8K RAM空间。其中前16个字地址为预留的16个16位寄存器,...
  • 在STM32上开发LCD显示,可以有两种方式来对LCD进行操作,一种是通过普通的IO口,连接LCM的相应引脚来进行操作,第2种是通过FSMC来进行操作。
  • 开始只是谈到别人对FSMC的理解,注意这里只讨论FSMC控制TFT,也就是在FSMC的NOR\PSRAM模式控制LCD,所以我们以下的分析都是基于这种模式的。
  • 本文提出了一种能直接驱动数字液晶屏的设计方案,方案先介绍了TFT数字彩屏的工作原理,利用STM32处理器的FSMC接口设计的硬件电路和软件程序均能对显示控制芯片进行有效的控制。在实际应用中显示清晰流畅,并且CPU有...
  • STM32 LCD的LTDC及FSMC驱动,STM32 MCU上的LCD-TFT显示控制器(LTDC),STM32F4系列和STM32F7系列微控制器上的DSI主机,TFT LCD 与 FSMC 的硬件连接,TFT LCD与高密度STM32F10xxx FSMC接口,使用大容量STM32F10xxx的...
  • stm32的FSMC总线驱动的8位液晶屏驱动代码,这只是修改了原子库的lcd.c,其它代码请参考原子库.
  • stm32cube HAL库 FSMC+FPGA通信
  • 本文档详细的讲解了基于 stm32 的FSMC方式 读写 扩展SRAM,的时序的测量 及配置,如果布线经验不足,会有误码率,可以适当的调整时序,加以规避。
  • STM32FSMC接口详解

    2018-01-29 00:03:13
    详解地解释了STM32的FSMC接口操作与原理,以及如何使用lcd
  • 而其特殊的可变静态存储技术FSMC具有高度的灵活性,对于存储容量要求较高的嵌入式系统设计,能够在不增加外部分立器件的情况下,扩展多种不同类型和容量的存储芯片,降低了系统设计的复杂性,提高了系统的可靠性。
  • STM32F407的FSMC工程模板,可以直接使用 ,STM32F407的FSMC工程模板,可以直接使用
  • 基于stm32的FSMC的ad7606 的的程序,实测可用。AD7606 的配置很简单,它没有内部寄存器。量程范围和过采样参数是通过外部IO控制的。 采样速率由MCU或DSP提供的脉冲频率控制。 AD7606 必须使用单5V供电。 AD7606 和...
  • 使用stm32cubemx配置fsmc驱动R61509V的TFT彩屏,笔者源于普中科技例程修改得到。
  • STM32F407使用FSMC接口的PC card控制器以 Memory / I/O 模式对CF卡读写。
  • 1、FSMC简介:FSMC即灵活的静态存储控制器,FSMC管理1GB空间,拥有4个Bank连接外部存储器,每个Bank有独立的片选信号和独立的时序配置;支持的存储器类型有SRAM、PSRAM、NOR/ONENAND、ROM、LCD接口(支持8080和6800...
  • 在完成IO驱动彩屏的试验后,就准备着手使用FSMC来驱动彩屏,先了解一下预备知识一、所谓的FSMC机制简单介绍FSMC在这篇博文里面很清楚,
  • stm32 fsmc 功能讲解

    2020-08-09 20:27:40
    本文针对LCD讲解了FSMC,但是其实对NOR和外部RAM的操作也是类似的,只不过多了些地址线来寻址而已。
  • STM32是ST(意法半导体)公司推出的基于ARM内核Cortex-M3...STM32系列采用一种新型的存储器扩展技术——FSMC,在外部存储器扩展方面具有独特的优势,可根据系统的应用需要,方便地进行不同类型大容量静态存储器的扩展。
  • 使用FSMC读写S29系列NOR Flash
  • 在STM32上跑UCOS_II和UCGUI时,要想让屏幕稳定不闪,显示...最好的方法就是配置FSMC使内部RAM作为堆栈使用,而外部RAM作为变量存储和UCOS_II的任务堆栈。现在介绍FSMC以及如何配置,并写出启动文件中需要修改的地方。
  • STM32F407 FSMC控制AD7606、SRAM和NOR FLASH的初始化代码,时序配置经过验证
  • 现在我用stm32f103ve, 配置fsmc, 驱动TFT, 只能配置成 psram模式, 如果配置其他模式,就会出现 fsmc总线没反应情况(当配置成sram,nor模式, 运行到FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); ,就出现没有响应)
  • FSMC

    万次阅读 多人点赞 2018-06-14 14:43:23
    第一个角度理解STM32有FSMC(其实其他芯片基本都有类似的总线功能),FSMC的好处就是你一旦设置好之后,WR(写)、RD(读)、DB0-DB15这些控制线和数据线,都是FSMC自动控制的。打个比方,当你在程序中写到: *...

    第一个角度理解STM32有FSMC(其实其他芯片基本都有类似的总线功能),FSMC的好处就是你一旦设置好之后,WR(写)、RD(读)、DB0-DB15这些控制线和数据线,都是FSMC自动控制的。打个比方,当你在程序中写到:

    *(volatile unsigned short int *)(0x60000000)=val;

     

    那么FSMC就会自动执行一个写的操作,其对应的主控芯片的WE、RD这些脚,就会呈现出写的时序出来(即WE=0,RD=1),数据val的值也

    会通过DB0-15自动呈现出来(即FSMC-D0:FSMC-D15=val  )。地址0x60000000会被呈现在数据线上(即A0-A25=0,地址线的对应最麻烦,要根据具体情况来,好好看看FSMC手册)。

     

    那么在硬件上面,我们需要做的,仅仅是MCU和LCD控制芯片的连接关系:

    WE-WR,均为低电平有效

    RD-RD,均为低电平有效

    FSMC-D0-15接LCD DB0-15

    FSMC_NE1--CS接PD7

     

    连接好之后,读写时序都会被FSMC自动完成。但是还有一个很关键的问题,就是RS没有接因为在FSMC里面,根本就没有对应RS。怎么办呢?这个时候,有一个好方法,就是用某一根地址线来接RS。比如我们选择了A16这根地址线来接,那么当我们要写寄存器的时候,我们需要RS,也就是A16(RS为高)置高。软件中怎么做呢?也就是将FSMC要写的地址改成0x60020000,如下:

     

    *(volatile unsigned short int *)(0x60020000)=val;

     

    这个时候,A16在执行其他FSMC的同时会被拉高,因为A0-A18要呈现出地址0x60020000。0x60020000里面的Bit17=1,就会导致A16为1。

    当要读数据时,地址由0x60020000改为了0x60000000,这个时候A16就为0了。

     

    那么有朋友就会有疑问,第一,为什么地址是0x6xxxxxxx而不是0x0xxxxxxx;第二,CS怎么接;第三,为什么Bit17对应A16?

     

    RS问题:RS为0表示;读写寄存器;RS为1,读写数据RAM;

     

    先来看前两个问题,大家找到STM32的FSMC手册,在FSMC手册里面,我们很容易找到,FSMC将0x60000000-0x6fffffff的地址用作NOR/PRAM(

    共256M地址范围)。而这个存储块,又被分成了四部分,每部分64M地址范围。当对其中某个存储块进行读写时,对应的NEx就会置低。这里,

    就解决了我们两个问题,

     

    第一,LCD的操作时序,和NOR/PRAM是一样的(为什么一样自己找找NOR/PRAM的时序看看),所以我们选择0x6xxxxxxx

    这个地址范围(选择这个地址范围,操作这个地址时,FSMC就会呈现出NOR/PRAM的时序)。

     

    第二,我们可以将NEx连接到LCD的CS,只要我们操作

    的地址是第一个存储块内即可(即0-0x3ffffff地址范围)。

     

    第三个问题再来看一看FSMC手册关于存储器字宽的描述,我们发现,当外部存储器是16位时,硬件管脚A0-A24表示的是地址线A1-A25的值,所以

    我们要位移一下,Bit17的值,实际会被反应到A16这根IO来。关于数据宽度及位移的问题,初学的朋友可能会比较疑惑,当你接触了多NOR/PRAM

    这样的器件后,你会发现,很多芯片的总线,都是这样设计的,为的是节省地址线。

     

    展开全文
  • NOR_flash_NOR_fsmc_源码

    2021-10-01 03:07:11
    FSMC_NOR FSMC NOR example
  • FSMC配置

    2021-08-07 18:05:13
    相关定义 #define FSMC_GPIO_AF GPIO_AF_FSMC #define FSMC_A0_GPIO_PORT GPIOF #define FSMC_A0_GPIO_CLK RCC_AHB1Periph_GPIOF #define FSMC_A0_GPIO_Pin GPIO_Pin_0 #define FSMC_A0_GPIO_PinSource GPIO_...

    FSMC配置

    1.GPIO配置

    static void LCD_GPIO_Config(){
     
    	GPIO_InitTypeDef GPIO_InitStructure;
    	RCC_AHB1PeriphClockCmd(FSMC_A0_GPIO_CLK,ENABLE);
    
    	//通用GPIO设置
    	GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
    	GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP;
    	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF;
    	//使用
    	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz;
    
    	/*A地址信号线针对引脚配置*/
      GPIO_InitStructure.GPIO_Pin = FSMC_A0_GPIO_Pin;
      GPIO_Init(FSMC_A0_GPIO_PORT,&GPIO_InitStructure);
    GPIO_PinAFConfig(FSMC_A0_GPIO_PORT,FSMC_A0_GPIO_PinSource,FSMC_GPIO_AF);
    
    }
    
    static void ILI9806G_GPIO_Config ( void )
    {
        GPIO_InitTypeDef GPIO_InitStructure;
    
        /* 使能FSMC对应相应管脚时钟*/
        RCC_AHB1PeriphClockCmd (
            /*控制信号*/
            ILI9806G_CS_CLK|ILI9806G_DC_CLK|ILI9806G_WR_CLK|
            ILI9806G_RD_CLK |ILI9806G_BK_CLK|ILI9806G_RST_CLK|
            /*数据信号*/
            ILI9806G_D0_CLK|, ENABLE );
    
    
        /* 配置FSMC相对应的数据线,FSMC-D0~D15 */
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    
        GPIO_InitStructure.GPIO_Pin = ILI9806G_D0_PIN;
        GPIO_Init(ILI9806G_D0_PORT, &GPIO_InitStructure);
        GPIO_PinAFConfig(ILI9806G_D0_PORT,ILI9806G_D0_PinSource,FSMC_AF);
    
        /* 配置FSMC相对应的控制线
        * FSMC_NOE   :LCD-RD
        * FSMC_NWE   :LCD-WR
        * FSMC_NE1   :LCD-CS
        * FSMC_A0    :LCD-DC
        */
        GPIO_InitStructure.GPIO_Pin = ILI9806G_RD_PIN;
        GPIO_Init(ILI9806G_RD_PORT, &GPIO_InitStructure);
        GPIO_PinAFConfig(ILI9806G_RD_PORT,ILI9806G_RD_PinSource,FSMC_AF);
    
        GPIO_InitStructure.GPIO_Pin = ILI9806G_WR_PIN;
        GPIO_Init(ILI9806G_WR_PORT, &GPIO_InitStructure);
        GPIO_PinAFConfig(ILI9806G_WR_PORT,ILI9806G_WR_PinSource,FSMC_AF);
    
        GPIO_InitStructure.GPIO_Pin = ILI9806G_CS_PIN;
        GPIO_Init(ILI9806G_CS_PORT, &GPIO_InitStructure);
        GPIO_PinAFConfig(ILI9806G_CS_PORT,ILI9806G_CS_PinSource,FSMC_AF);
    
        GPIO_InitStructure.GPIO_Pin = ILI9806G_DC_PIN;
        GPIO_Init(ILI9806G_DC_PORT, &GPIO_InitStructure);
        GPIO_PinAFConfig(ILI9806G_DC_PORT,ILI9806G_DC_PinSource,FSMC_AF);
    
        /* 配置LCD复位RST控制管脚*/
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    
        GPIO_InitStructure.GPIO_Pin = ILI9806G_RST_PIN;
        GPIO_Init ( ILI9806G_RST_PORT, & GPIO_InitStructure );
    
        /* 配置LCD背光控制管脚BK*/
        GPIO_InitStructure.GPIO_Pin = ILI9806G_BK_PIN;
        GPIO_Init ( ILI9806G_BK_PORT, & GPIO_InitStructure );
    }
    

    2.FSMC_Init
    模式B与模式A的相同和区别:
    (1)使用异步控制,因此不使用CLK时钟同步引脚;
    (2)8080时序没有A[25:0]引脚,但会用其中一根信号线作为地址信号线;
    (3)都有D[15:0]引脚作为双向数据总线;
    (4)模式B不使用NWAIT以及NADV引脚;
    (5)都有NOE、NWE分别进行输出使能和写使能;
    (6)都有NE[x],x=1-4,片选信号线。
    当FSMC外设被配置成正常工作,并且外部接了NOR FLASH时,若向0x60000000地址写入数据如0xABCD,FSMC会自动在各信号线上产生相应的电平信号,写入数据。

    static void FSMC_SRAM_Init(){
    	
    FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
    FSMC_NORSRAMTimingInitTypeDef readWriteTiming;
    	
    	
    /*使能FSMC外设时钟*/
    RCC_AHB3PeriphClockCmd (RCC_AHB3Periph_FSMC,ENABLE);
    	
    	
      //地址建立时间(ADDSET)为5个HCLK,5/168M = 30ns
      readWriteTiming. FSMC_AddressSetupTime = 0x04;
      //地址保持时间(ADDHLD)模式B未用到
      readWriteTiming.FSMC_AddressHoldTime = 0x00;
      //数据保持时间(DATAST)+1个HCLK =5/168M=30ns(对EM的SRAM芯片)
      readWriteTiming. FSMC_DataSetupTime = 0x04;
      //设置总线转换周期,仅用于复用模式的NOR操作
      readWriteTiming.FSMC_BusTurnAroundDuration = 0x00;
      //设置时钟分频,仅用于同步类型的存储器
      readWriteTiming.FSMC_CLKDivision = 0x00;
      //数据保持时间,仅用于同步型的NOR
      readWriteTiming. FSMC_DataLatency = 0x00 ;
      //选择匹配异步NOR FLASH的模式(模拟8080)
      readWriteTiming. FSMC_AccessMode = FSMC_AccessMode_B;
    	
      //选择FSMC映射的存储区域:Bank1 sram3
      FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM3;
      //设置地址总线与数据总线是否复用,仅用于NOR
      FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
      //设置要控制的存储器类型:NOR FLASH类型
      FSMC_NORSRAMInitStructure.FSMC_MemoryType =FSMC_MemoryType_NOR;
      //存储器数据宽度:16位
      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 = &readWriteTiming;
    	
      //读写同样时序,使用扩展模式时这个配置才有效
      FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &readWriteTiming;
    	
    	FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);    //初始化FSMC配置
    	
      FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM3,ENABLE);     //使能BANK
    }
    
    

    设置存储区域FSMC_Bank:
    FSMC_Bank成员设置FSMC的NOR FLASH存储区域映射选择为宏FSMC_Bank1_NORSRAMx (即FSMC_Bank1_NORSRAM3), 这是由于我们的SRAM硬件连接到FSMC_NE3和NOR/PSRAM相关引脚,所以对应到存储区域Bank1SRAM3,对应的基地址为0X6800 0000;

    存储器类型FSMC_MemoryType:
    由于使用异步NOR FLASH模式模拟8080时序,所以FSMC_MemoryType成员要选择相应的FSMC_MemoryType_NOR;

    数据线宽度FSMC_MemoryDataWidth:
    根据硬件的数据线连接,数据线宽度被配置为16位宽FSMC_MemoryDataWidth_16b;

    写使能FSMC_WriteOperation:
    FSMC_WriteOperation用于设置写使能,只有使能了才能正常使用FSMC向外部存储器写入数据;

    扩展模式以及读写时序:
    在FSMC_ExtendedMode成员中可以配置是否使用扩展模式,当设置扩展模式时,读时序使用FSMC_ReadWriteTimingStruct中的配置, 写时序使用FSMC_WriteTimingStruct中的配置,两种配置互相独立,可以赋值为不同的读写时序结构体。在本实例中不使用扩展模式, 即读写时序使用相同的配置,都是赋值为前面的readWriteTiming结构体。
    当访问特定地址时,FSMC会产生相应的模拟8080时序,控制地址线输出要访问的内存地址,使用数据信号线接收或发送数据, 其它片选信号NE、读使能信号NOE、写使能信号NWE辅助产生完整的时序
    3.相关定义

    #define FSMC_GPIO_AF            GPIO_AF_FSMC
    
    #define FSMC_A0_GPIO_PORT       GPIOF
    #define FSMC_A0_GPIO_CLK        RCC_AHB1Periph_GPIOF
    #define FSMC_A0_GPIO_Pin        GPIO_Pin_0
    #define FSMC_A0_GPIO_PinSource  GPIO_PinSource0
    
    #define FSMC_CS_PORT            GPIOG
    #define FSMC_CS_CLK             RCC_AHB1Periph_GPIOG
    #define FSMC_CS_Pin             GPIO_Pin_12
    #define FSMC_CS_PinSource       GPIO_PinSource12
    
    /*WE写使能*/
    #define FSMC_WE_GPIO_PORT       GPIOD
    #define FSMC_WE_GPIO_CLK        RCC_AHB1Periph_GPIOD
    #define FSMC_WE_GPIO_PIN        GPIO_Pin_5
    #define FSMC_WE_GPIO_PinSource  GPIO_PinSource5
    /*OE读使能*/
    #define FSMC_OE_GPIO_PORT       GPIOD
    #define FSMC_OE_GPIO_CLK        RCC_AHB1Periph_GPIOD
    #define FSMC_OE_GPIO_PIN        GPIO_Pin_4
    #define FSMC_OE_GPIO_PinSource  GPIO_PinSource4
    
    //复位引脚
    #define      ILI9806G_RST_CLK               RCC_AHB1Periph_GPIOF
    #define      ILI9806G_RST_PORT              GPIOF
    #define      ILI9806G_RST_PIN               GPIO_Pin_11
    
    //背光引脚
    #define      ILI9806G_BK_CLK                RCC_AHB1Periph_GPIOF
    #define      ILI9806G_BK_PORT               GPIOF
    #define      ILI9806G_BK_PIN                GPIO_Pin_9
    
    /********数据信号线***************/
    #define      ILI9806G_D0_CLK                RCC_AHB1Periph_GPIOD
    #define      ILI9806G_D0_PORT               GPIOD
    #define      ILI9806G_D0_PIN                GPIO_Pin_14
    #define      ILI9806G_D0_PinSource          GPIO_PinSource14
    
    //FSMC_Bank1_NORSRAM用于LCD命令操作的地址
    #define      FSMC_Addr_ILI9806G_CMD         ( ( uint32_t ) 0x68000000 )
    
    //FSMC_Bank1_NORSRAM用于LCD数据操作的地址
    #define      FSMC_Addr_ILI9806G_DATA        ( ( uint32_t ) 0x68000002 )
    

    4.全局初始化

    uint8_t LCD_SCAN_MODE = 6;
    void ILI9806G_Init ( void )
    {
        ILI9806G_GPIO_Config ();
        ILI9806G_FSMC_Config ();
    
        ILI9806G_Rst ();
        ILI9806G_REG_Config ();
    
        //设置默认扫描方向,其中 6 模式为大部分液晶例程的默认显示方向
        ILI9806G_GramScan(LCD_SCAN_MODE);
    
        ILI9806G_Clear(0,0,LCD_X_LENGTH,LCD_Y_LENGTH);  /* 清屏,显示全黑 */
        ILI9806G_BackLed_Control ( ENABLE );      //点亮LCD背光灯
    }
    

    5.地址计算原理

    使用FSMC_NE3作为8080_CS片选信号,所以首先可以确认地址范围, 当访问0X6800 0000 ~ 0X6BFF FFFF地址时,FSMC均会对外产生片选有效的访问时序;
    使用FSMC_A0地址线作为命令/数据选择线RS信号,所以在以上地址范围内,再选择出使得FSMC_A0输出高电平的地址,
    即可控制表示数据,选择出使得FSMC_A0输出低电平的地址,即可控制表示命令。
    要使FSMC_A0地址线为高电平,实质是输出地址信号的第0位为1即可,使用0X6800 0000~0X6BFF FFFF内的任意地址,作如下运算: 设置地址的第0位为1: 0X6800 0000 |= (1<<0) = 0x6800 0001
    要使FSMC_A0地址线为低电平,实质是输出地址信号的第0位为0即可,使用0X6800 0000~0X6BFF FFFF内的任意地址,作如下运算: 设置地址的第0位为0: 0X6800 0000 &= ~ (1<<0) = 0x6800 0000
    但是,以上方法计算的地址还不完全正确,根据《STM32参考手册》对FSMC访问NOR FLASH的说明,STM32内部访问地址时使用的是内部HADDR总线,它是需要转换到外部存储器的内部AHB地址线,它是字节地址(8位), 而存储器访问不都是按字节访问,因此接到存储器的地址线依存储器的数据宽度有所不同。

    对于FSMC和8080接口,前四种信号线都是完全一样的,仅仅是FSMC的地址信号线A[25:0]与8080的数据/命令选择线D/CX有区别。而对于D/CX线, 它为高电平的时候表示数值,为低电平的时候表示命令,如果能使用FSMC的A地址线根据不同的情况产生对应的电平, 那么就完全可以使用FSMC来产生8080接口需要的时序了。

    为了模拟出8080时序,我们可以把FSMC的A0地址线(也可以使用其它A1/A2等地址线,上文中为A0)与ILI9806G芯片8080接口的D/CX信号线连接, 那么当A0为高电平时(即D/CX为高电平),数据线D[15:0]的信号会被ILI9806G理解为数值,若A0为低电平时(即D/CX为低电平), 传输的信号则会被理解为命令。

    由于FSMC会自动产生地址信号,当使用FSMC向0x6xxx xxx1、0x6xxx xxx3、 0x6xxx xxx5…这些奇数地址写入数据时,地址最低位的值均为1, 所以它会控制地址线A0(D/CX)输出高电平,那么这时通过数据线传输的信号会被理解为数值; 若向0x6xxx xxx0 、0x6xxx xxx2、0x6xxx xxx4…这些偶数地址写入数据时, 地址最低位的值均为0,所以它会控制地址线A0(D/CX)输出低电平, 因此这时通过数据线传输的信号会被理解为命令,见下表
    在这里插入图片描述

    展开全文
  • STM32的FSMC驱动TFT笔记

    2020-07-10 18:57:27
    FSMC初初了解:FSMC 包括4个模块:(1)AHB接口(包括FSMC配置寄存器)(2)NOR闪存和PSRAM控制器(驱动LCD的时候LCD就好像一个PSRAM的里面只有2个16位的存储空间,一个是DATA RAM 一个是CMD RAM)
  • fsmc

    千次阅读 2016-05-31 17:01:32
    16位宽度存储器的外部地址FSMC_A[24:0]貌似每个地址代表16位宽度。


    16位宽度存储器的外部地址FSMC_A[24:0]貌似每个地址代表16位宽度。stm32的内部都是以字节形式存在的。所以地址要右移一位



    1、如果我的FSMC的A0与某外设的A1相连,而外设的A0与FSMC的NBL0相连,这样地址需要偏移吗?
    如果是16位模式 要的 地址偏移是FSMC内部的固化操作 如果你选择16位模式就会有地址偏移(稍后说明原因) 这样做是为了用户使用方便
    2、另外如果设置数据宽度为16bit,那么NBL0和NBL1不应该都是输出高吗? 
    不一定 偶字节读写时仅NBL0有效,奇字节读写时仅NBL1有效 字读写都有效(低电平有效)
    3、有点乱。因为是确实看见有人讲外设的A0与FSMC的NBL0相连 
    不知道 没见过

    这里说一下我对FSMC地址操作的一点认识

    首先说一个前提:STM32 单片机的一个地址(如:0x20000000)是一个字节 
    也就是说如果定义一个16位数组 u16 temp[5]  如果temp对应的地址是0x00000000 那么temp+1对应的地址是0x00000002 (地址是加2)

    假设此时我们有一个 64K*8bit 的sram
    那很简单 stm32的A0~A15 与存储器A0~A15连接 大家很容易理解

    若此时是 64K*16bit 的sram
    也就是此时sram的一个地址对应两个字节 但是stm32是一个地址一个字节 这就出现了对准的问题
    如果我们的地址线依然是stm32A0~A15 和 存储器的A0~A15 连接 
    如果stm32要从sram中读取前面提到数组中的temp[1]
    stm32会给出0x0002(二进制地址0000000000000010b) 可是对于我们这个sram来说 读到却是temp[2],因为sram一个地址就是一个16位数据 
    为了解决这个问题 我们只需要在给sram送地址时 右移一位 再送地址 即可(sram的一个地址对应stm32两个地址的数据)
    比如读取0x0002 右移一位(即除2)为0x0001(0000000000000010b) 此时对应的就是temp[1]
    而为了给用户提供方便 如果你选择的是16位宽度的sram FSMC会在你送地址的时候自动为你做右移一位的操作 
    此时会有另外一个问题 每次都右移一位 A0没用吗 也即只能读写偶地址的数据吗?
    这也就是NBL0和NBL1的作用了 如果你要进行字节操作 
    如stm32发送地址0x0001读取一个字节 右移一位对应的是sram地址0x0000处的16位数据 FSMC会根据AO 来控制NBLO和NBL110 读取高字节数据
    所以呢  偶字节读写时仅NBL0有效,奇字节读写时仅NBL1有效 字读写都有效(低电平有效)

    //----------------------------------------------------------------------------------------


    对地址65535写8位的数i代码
          *(vu8*)(Bank1_SRAM3_ADDR+65534)=i;
          i++;
       
    STM32通过FSMC写8位数据
    C代码中地址为实际要写入的地址字节,若将FSMC 的数据位宽配置为16位,则每次寻址实际都寻址了两个字节,例如,FSMC的地址总线值为0,则实际位于地址0有16位,两个字节,因此需要通过高低字节控制信号来区分,即LB和UB信号(注意:所有控制信号都是低电平有效)。例如当希望对地址0上的高字节进行寻址时,则FSMC总线地址值任然为0,同时LB无效(高电平)UB有效(低电平),即可实现对地址0上的高字节单独寻址。假设C代码中的要写入的地址为C_Addr,则实际FSMC总线上地址线的值与LB、UB值的状态为:
    FSMC_ADDR = C_Addr/2
    FSMC_LB = C_Addr%2
    FSMC_UB =~ (C_Addr%2)
    16位操作方式:
    对地址65534写16位的数6555代码
          *(vu16*)(Bank1_SRAM3_ADDR+65534)=6555;
       
    STM32通过FSMC写16位数据
    C代码中地址为实际要写入的地址字节,若将FSMC 的数据位宽配置为16位,则每次寻址实际都寻址了两个字节,例如,FSMC的地址总线值为0,则实际位于地址0有16位,两个字节,因此需要通过高低字节控制信号来区分,即LB和UB信号(注意:所有控制信号都是低电平有效)。例如当希望对地址0上的高字节进行寻址时,则FSMC总线地址值任然为0,同时LB无效(高电平)UB有效(低电平),即可实现对地址0上的高字节单独寻址。假设C代码中的要写入的地址为C_Addr,则实际FSMC总线上地址线的值与LB、UB值的状态为:
    如果C_Addr为偶数,则
    FSMC_ADDR = C_Addr/2
    FSMC_LB = FSMC_UB = 0;
    FSMC一次性即可完成16位数据的写入。
    如果C_Addr为奇数,则实际FSMC会将数据分成两个8位的数据来进行操作,因此效率会低很多。
    先写C_Addr,写入数据字节为待写入数据的高字节
    FSMC_ADDR = C_Addr/2
    FSMC_LB =1;
    FSMC_UB =0;
    然后写C_Addr + 1地址,写入数据字节为待写入数据的低字节
    FSMC_ADDR = (C_Addr + 1) /2
    FSMC_LB =0;
    FSMC_UB =1;
    32位操作方式:
    对地址65534写32位的数1265536(0x134F80)代码
          *(vu32*)(Bank1_SRAM3_ADDR+65534)= 1265536;
       
    STM32通过FSMC写32数据
    C代码中地址为实际要写入的地址字节,若将FSMC 的数据位宽配置为16位,则每次寻址实际都寻址了两个字节,例如,FSMC的地址总线值为0,则实际位于地址0有16位,两个字节,因此需要通过高低字节控制信号来区分,即LB和UB信号(注意:所有控制信号都是低电平有效)。例如当希望对地址0上的高字节进行寻址时,则FSMC总线地址值任然为0,同时LB无效(高电平)UB有效(低电平),即可实现对地址0上的高字节单独寻址。假设C代码中的要写入的起始地址为C_Addr,则实际FSMC总线上地址线的值与LB、UB值的状态为:
    如果C_Addr为4的倍数,则FSMC首先在起始地址处写入待写入数据的低字节和次低字节:
    FSMC_ADDR = C_Addr/2
    FSMC_LB = FSMC_UB = 0;
    然后FSMC再在起始地址+2处写入待写入数据的低字节和次低字节:
    FSMC_ADDR = (C_Addr+2)/2
    FSMC_LB = FSMC_UB = 0;
    只需要两次16位数据写入操作即可完成一个32位数据的写入,因此效率较高。
    如果C_Addr为奇数,则实际FSMC会将数据分成两个8位的数据和一个16位的数据来进行操作,需要3次写入操作才能完成32位数据的写入(效率较低)。
    FSMC首先在起始地址(C_Addr)位置以8位写入方式写入待写入数据的低字节:
    FSMC_ADDR = C_Addr/2
    FSMC_LB = 1;
    FSMC_UB = 0;
    然后FSMC再在起始地址+2处(C_Addr + 2)以16位数据方式写入带写入数据的次低字节和次高字节:
    FSMC_ADDR = (C_Addr+2)/2
    FSMC_LB = FSMC_UB = 0;
    最后FSMC再在起始地址+4处(C_Addr + 2)以8位写入方式写入待写入数据的高字节:
    FSMC_ADDR = (C_Addr+4)/2
    FSMC_LB = 0;
    FSMC_UB = 1;

    展开全文
  • 基于stm32的hal库和FSMC的nand驱动 包含坏块处理,其中自动累加地址,只要设置好首地址就可以.自动坏块处理

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,071
精华内容 1,628
关键字:

FSMC