摘要:使用FSMC模拟8080时序,进行LCD芯片的基本驱动过程和代码。

1. FSMC介绍

1.1 概念

FSMC,Flexible Static Memory Controller,灵活的静态存储控制器。

用途:用于驱动SRAM,NOR FLASH,NAND FLASH及PC卡类型的存储器。

配置好FSMC,定义一个指向这些地址的指针,通过对指针操作就可以直接修改存储单元的内容,FSMC自动完成读写命令和数据访问操作,不需要程序去实现时序。

这里需要配置FSMC外设,模拟8080时序。

FSMC和FMC的区别是,后者可以控制SDRAM等,只在F4/F7/H7系列STM32芯片中

1.2 框图

image-20250512013820089

最左边是时钟控制逻辑,FMC挂在AHB总线上(高速总线),时钟来自HCLK

中间是STM32内部是FMC控制单元,包括:

  1. FSMC配置寄存器
  2. NOR/PSRAM控制器
  3. NAMD/PC卡控制器

右边是通信引脚,包括不同存储器要用到的和公共的。

1.3 通信引脚

用于连接硬件设备的引脚。

FSMC信号 信号方向 功能
FSMC_NE[x] 输出 片选引脚,x=1…4,每个对应不同的内存块
FSMC_CLK 输出 时钟(同步突发模式使用)
FSMC_A[25:0] 输出 地址总线
FSMC_D[15:0] 输出/输入 双向数据总线
FSMC_NOE 输出 输出使能(“N”表明低电平有效信号)
FSMC_NWE 输出 写使能
FSMC_NWAIT 输入 NOR闪存要求FSMC等待的信号
FSMC_NADV 输出 地址、数据线复用时作锁存信号

LCD使用的是类似异步、地址与数据线独立的SRAM控制方式,因此使用的信号有NE, A, D, NOE, NWE

2. FSMC驱动LCD的方法(硬件层面)

image-20250512014824182

2.1 FSMC时序(NOR/PSRAM)

NOR/PSRAM控制器使用的异步时序:

访问模式 对应的外部存储器 时序特性
模式1 SRAM/CRAM OE在读时序片选过程不翻转,有NBL信号,无NADV信号
模式A SRAM/PSRAM(CRAM) OE在读时序片选过程翻转,有NBL信号,无NADV信号
模式B/2 NOR FLASH OE在读时序片选过程不翻转,无NBL信号,有NADV信号
模式C NOR FLASH OE在读时序片选过程翻转,无NBL信号,有NADV信号
模式D 带地址扩展的异步操作 OE在读时序片选过程翻转,无NBL信号,有NADV信号,存在地址保存时间

使用模式A通信LCD。(SRAM, 读使能需要上升沿触发)

模式A和8080时序对比:

image-20250512015700224

设置ADDSET和DATASET参数来设置FSMC参数

2.2 LCD所需要的时序(ILI9341.pdf p232)

image-20250512020348850

3 FSMC地址映射(软硬件接口)

3.1 STM32 内部地址和FSMC_NE/A/D信号线的关系

使用FSMC外接存储器,其存储单元是映射到STM32的内部寻址空间的。从FSMC角度看,可以把外部存储器划分为固定大小为256M字节的四个存储块。如下图所示。

image-20250512023459719

其中,FSMC存储块1被分为4个区,每个区管理64M字节空间。

BANK1选区 片选信号 地址范围 HADDR
[27:26] [25:0]
第1区 FSMC_NE1 0x6000 0000 ~ 0x63FF FFFF 00 FSMC_A[25:0]
第2区 FSMC_NE2 0x6400 0000 ~ 0x67FF FFFF 01 FSMC_A[25:0]
第3区 FSMC_NE3 0x6800 0000 ~ 0x6BFF FFFF 10 FSMC_A[25:0]
第4区 FSMC_NE4 0x6C00 0000 ~ 0x6FFF FFFF 11 FSMC_A[25:0]

FSMC_A的26位对应4MB = 2^26Byte的数据空间。

地址映射的表现就是,如果在程序中访问上述地址,向这些地址写入值,能够直接根据地址控制NE和A引脚的电平,然后将数据写入D引脚,通过FSMC直接完成数据传输。

FSMC是连接外部存储器的CPU外设。NE是SRAM/CRAM这类外部存储器专用的引脚,而A/D是通用的。相当于,FSMC_A连接外部存储器(如LCD)的地址引脚,FSMC_D连接外部存储器的数据引脚,配置好以后,直接读写CPU的对于地址,就可以完成对外部存储器的读写。

3.2 HADDR和FSMC_A的关系

HADDR总线是转换到外部存储器的内部AHB地址线,简单来说就是从CPU通过AHB总线到外部信号线之间的关系。

3.1说过,FSMC的地址对应的是字节空间(即一个地址对应一个字节的数据);HADDR是字节地址,而存储器访问不都是按字节访问,接到存储器的地址线与其数据宽度相关。

例如在LCD中,数据位就是16位。数据宽度和地址线连接方法的关系如下。

image-20250512025632498

地址少了一位,即变成了1/2,现在一个地址位能对应两个字节的数据了。

1字节(Byte) = 8位(bit)

3.3 地址的计算(以LCD为例)

上面说过,FSMC_A是对应地址的,对于LCD来说,CPU需要访问的地址只有两个:命令和数据,也就是说,一个FSMC_A引脚代替RS就足够了。

正点原子精英版 v2中,LCD使用NE4作为CS线,FSMC_A10作为RS线,以下计算使用这两个引脚为例。

当FSMC_A10为高电平时(即RS为高电平),FSMC_D[15:0]被理解为数据。当FSMC_A10为低电平时(即RS为低电平),FSMC_D[15:0]被理解为命令。

LCD命令/数据地址的计算方法如下。

  1. 确认FSMC_NE4的基地址:0x6C000000
  2. 确认FSMC_A10高电平时对应HADDR的地址值(注意偏移*2): 2^10 *2 = 0x0800
  3. 确认LCD地址
    1. 命令:RS置0,#define FSMC_ADDR_CMD ((uint32_t) 0x6C000000)
    2. 数据:RS置1,#define FSMC_ADDR_DATA ((uint32_t) 0x6C000800)

4 FSMC相关寄存器(软件层面)

碎碎念:在了解寄存器之前,想一想在硬件层面连接完成后,FSMC寄存器要控制什么东西?首先肯定要确认访问模式来控制时序,需要这部分参数;然后就是地址映射相关的?这部分除了读写CPU地址之外还需要做什么?数据格式肯定要确认的,如果是16位的话依次读写需要读写两个字节的数据,这部分逻辑肯定是FSMC内部实现的

FSMC的存储块1(NOR_FLASH/PSRAM控制器)通过以下三种寄存器配置。(x = 1~4)

寄存器 名称 作用
FSMC_BCRx 片选控制寄存器 包含存储器块的信息(存储器类型/数据宽度等)
FSMC_BTRx 片选时序寄存器 设置读操作时序参数(ADDSET/DATAST)
FSMC_BWTR4x 写时序寄存器 设置写操作时序参数(ADDSET/DATAST)

4.1 SRAM/NOR闪存片选控制寄存器(FSMC_BCRx )

如下图所示。(详见F103中文参考手册 19.5.6)

image-20250512221217635

  • 位14 EXTMOD:扩展模式使能位,控制是否允许读写使用不同的时序(需要置1)
  • 位12 WREN:写使能位(需要置1)
  • 位[5:4] MWID[1:0]:存储器数据总线宽度(00: 8位模式,01: 16位模式,10/11保留)(需要置01)
  • 位[3:2] MTYP[1:0]:存储器类型(00: SRAM/ROM,01:PSRAM,10:NOR FLASH,11保留)(需要置00)
  • 位0 MBKEN:存储块使能位(需要置1)

4.2 SRAM/NOR闪存片选时序寄存器(FSMC_BTRx )

image-20250512223020918

(因为F1的FSMC性能有问题,所以设置位15已经可以达到355ns的要求。。。)

4.3 SRAM/NOR闪存写时序寄存器(FSMC_BWTRx )

image-20250512223056703

4.4 解释

结合2.1 的FSMC时序图和2.2 LCD的时序规格图,可以看到,LCD的读信号和写信号都有两个规格约束:读/写信号的拉低持续时间和恢复高电平持续时间(到下一次拉低之前)。

对于FSMC的模式A而言:

  1. 写信号:拉低时间是 (DATAST+1)*HCLK 就是写信号的拉低时间,(ADDSET+1)*HCLK 就是写信号的拉高时间,这两个时间限制都是最小15ns。
  2. 读信号,同理,拉低时间和拉高时间分别是(DATASET+3)*HCLK和(ADDSET+1)*HCLK,具体见2.2。
  3. 寄存器里面的DATAST和ADDSET两个数据位,乘以HCLK就能直接得到拉低时间和拉高时间。

4.5 寄存器组合

同一类寄存器

image-20250512230642750

5 编程要点

5.1 初始化结构体

见下。

Sram控制句柄

image-20250513010733210

SRAM初始化结构体

image-20250513010755800

FSMC时序结构体

image-20250513011137774

5.2 CubeMX配置

使用CubeMX的话事情就会变得异常简单,这就是一键配置的优点;当然缺点就是对结构可能缺乏了解。

ChipSelect 选择NE4,Memory type 选择 LCD Interface,LCD Register选择A10,Data 选择16比特

image-20250515012737436

下面打开写操作和扩展模式(读写时钟分离),然后按照下图配置就可以了。

image-20250515013052079

最后把LCD背光的Pin加上就行,可以生成代码了。

image-20250515013112254

5.3 功能函数

和上一节的GPIO模拟8080时序相比,GPIO基础操作函数删去,LCD写指令、读数据和写数据这三个二级函数按照下图修改,直接通过地址读写寄存器即可;具体指令操作的三级函数和上一节一模一样。除去CubeMx自动配置,比之前的代码少很多,也更直观。

image-20250515013220130

5.4 出现的问题

keil的C/C++优化等级必须在Level01或以下,否则会出错。

image-20250515013923426



本站由 kisekino yama 使用 Stellar 1.29.1主题创建。

本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0许可协议,转载请注明出处。