FSMC之LCD彩屏学习
彩屏的驱动这里主要用到的是8080并口接口, 彩屏这里有区分带有控制器和不带控制器的,80并口有如下一些信号线:
CS :片选信号
WR :写数据
RD :读数据
RST:复位
RS :命令/数据标志(0:读写命令 1:读写数据)
80并口读写过程:
①:根据要选择写入或读取数据的类型,设置RS
(RS :命令/数据标志(0:读写命令 1:读写数据))
②:拉低片选信号
③:根据是读数据还是写数据来设置RD/WR为低,然后:
在 RD 的上升沿, 使数据锁存到数据线(D[7:0])上;
在 WR 的上升沿,使数据写入;
图 80并口写数据
图 80 并口读数据
STM32的FSMC
FSMC,即灵活的静态存储控制器,能够与同步或异步存储器和 16 位 PC 存储器卡连接,STM32F4 的 FSMC 接口支持包括 SRAM、 NAND FLASH、 NOR FLASH 和 PSRAM 等存储器。
所有的外部存储器共享地址、数据和控制信号,但有各自的片选信号。FSMC一次只能访问一个外部器件。
STM32的FSMC主要功能:(详情看手册)
● 支持对同步器件(NOR Flash 和 PSRAM)的突发模式访问
● 8 或 16 位宽的数据总线
● 每个存储区域有独立的片选控制
● 每个存储区域可独立配置
● 可对时序进行编程,以支持各种器件
FSMC 包含四个主要模块:
● AHB 接口(包括 FSMC 配置寄存器)
● NOR Flash/PSRAM 控制器
● NAND Flash/PC 卡控制器
● 外部器件接口
这里我们介绍下为什么可以把 TFTLCD 当成 SRAM 设备用:首先我们了解下外部 SRAM的连接, 外部 SRAM 的控制一般有: 地址线 (如 A0~A18) 、 数据线 (如 D0~D15) 、 写信号 (WE) 、读信号 (OE) 、 片选信号 (CS) , 如果 SRAM 支持字节控制, 那么还有 UB/LB 信号。 而 TFTLCD的信号包括:RS、D0~D15、WR、RD、CS、RST 和 BL 等,其中真正在操作 LCD 的时候需要用到的就只有:RS、D0~D15、WR、 RD 和 CS。 其操作时序和 SRAM的控制完全类似,唯一不同就是 TFTLCD 有 RS 信号,但是没有地址信号。TFTLCD 通过 RS 信号来决定传送的数据是数据还是命令,本质上可以理解为一个地址信号,比如我们把 RS 接在 A0 上面,那么当 FSMC 控制器写地址 0 的时候,会使得 A0 变为 0,对 TFTLCD 来说, 就是写命令。 而 FSMC 写地址 1 的时候, A0 将会变为 1, 对 TFTLCD 来说,就是写数据了。这样,就把数据和命令区分开了,他们其实就是对应 SRAM 操作的两个连续地址。
外部器件地址映射
从FSMC的角度,外部存储器被划分为4个固定大小的存储区域,每个区域的大小为256MB,如下图:
● 存储区域 1 可连接多达 4 个 NOR Flash 或 PSRAM 存储器器件。此存储区域被划分为 4 个
NOR/PSRAM 区域,带 4 个专用片选信号。
● 存储区域 2 和 3 用于连接 NAND Flash 器件(每个存储区域一个器件)
● 存储区域 4 用于连接 PC 卡设备
从上图可知FSMC总共管理1GB空间,拥有4个存储块(Bank),这里我们讨论存储块1(Bank1),Bank1分为4个区,每个区64M字节空间,每个区都有独立的寄存器对所连接的存储器进行配置。Bank1的256M字节空间由28根地址线(HADDR[27:0])寻址。
这里HADDR是内部AHB地址总线,其中HADDR[25:0]来自外部存储器地址FSMC_A[25:0],而HADDR[26:27]对4个区进行寻址,如下图:
HARRD[25:0]包含外部存储器地址,由于HARRD为字节地址,而存储器按字寻址,所以根据存储器数据的宽度的不同,实际向存储器发送的地址也将有所不同,如下图:
当 Bank1 接的是 16 位宽度存储器的时候:HADDR[25:1]-->FSMC[24:0]。
当 Bank1 接的是 8 位宽度存储器的时候:HADDR[25:0]-->FSMC[25:0]。
不论外部接 8 位/16 位宽设备,FSMC_A[0] 永远接在外部设备地址 A[0] 。
TFTLCD使用的是 16 位数据宽度,所以 HADDR[0]并没有用到,只有HADDR[25:1]是有效的,对应关系变为:HADDR[25:1]-->FSMC[24:0],相当于右移了一位,这里请大家特别留意。另外,HADDR[27:26]的设置,是不需要我们干预的,比如:当你选择使用 Bank1 的第三个区,即使用 FSMC_NE3 来连接外部设备的时候,即对应了 HADDR[27:26]=10,我们要做的就是配置对应第3区的寄存器组, 来适应外部设备即可。
STM32F4的FSMC各Bank配置寄存器如表
对于NOR FLASH控制器,主要是通过FSMC_BCRx、FSMC_BTRx和FSMC_BWTRx寄存器设置(其中x=1~4,对应4个区)。通过这3个寄存器,可以设置FSMC访问外部存储器的时序参数、拓宽了可以选用的外部存储器的速度范围。FSMC的NOR FLASH控制器支持同步和异步突发两种访问方式。选用同步突发访问方式时,FSMC将HCLK(系统时钟)分频后,发送给外部存储器作为同步时钟信号FSMC_CLK。此时需要的设置的时间参数有2个:
①:HCLK与FSMC_CLK的分频系数(CLKDIV),可以为2~16;
②:同步突发访问中获得第1个数据所需要的等待延迟(DATLAT)。
对于异步突发访问方式,FSMC主要设置3个时间参数:地址建立时间(ADDSET)、数据建立时间(DATSET)和地址保持时间(ADDHLD)。
FSMC 综合了 SRAM/ROM、 PSRAM 和 NOR Flash 产品的信号特点,定义了 4 种不同的异步时序模型。选用不同的时序模型时,需要设置不
同的时序参数,如表
在实际扩展时,根据选用存储器的特征确定时序模型,从而确定各时间参数与存储器读/写周期参数指标之间的计算关系;利用该计算关系和存储芯片数据手册中给定的参数指标,可计算出 FSMC 所需要的各时间参数,从而对时间参数寄存器进行合理的配置。
我们使用异步模式 A(ModeA)方式来控制 TFTLCD,模式 A 的读操作时序如图所示
模式 A 读操作时序图
模式 A 支持独立的读写时序控制, 这个对我们驱动 TFTLCD 来说非常有用,
因为 TFTLCD在读的时候,一般比较慢,而在写的时候可以比较快,如果读写用一样的时序,那么只能以读的时序为基准,从而导致写的速度变慢,或者在读数据的时候,重新配置 FSMC 的延时,在读操作完成的时候,再配置回写的时序,这样虽然也不会降低写的速度,但是频繁配置,比较麻烦。而如果有独立的读写时序控制,那么我们只要初始化的时候配置好,之后就不用再配置,既可以满足速度要求,又不需要频繁改配置。
模式 A 的写操作时序如图所示:
模式 A 写操作时序
图中ADDSET与DATASET,是通过不同的寄存器设置的。
SRAM/NOR闪存片选控制寄存器:FSMC_BCRx(x=1~4),该寄存器各个位如图:
EXTMOD:扩展模式使能位,也就是是否允许读写不同的时序
WREN:写使能位。我们需要向 TFTLCD 写数据,故该位必须设置为 1。
MWID[1:0]:存储器数据总线宽度。00,表示 8 位数据模式;01 表示 16 位
数据模式;10和 11 保留。我们的 TFTLCD 是 16 位数据线,
所以设置 WMID[1:0]=01。
MTYP[1:0]:存储器类型。 00 表示 SRAM、 ROM; 01 表示 PSRAM; 10
表示 NOR FLASH;11保留。前面提到,我们把 TFTLCD 当成
SRAM 用,所以需要设置 MTYP[1:0]=00。
MBKEN:存储块使能位。这个容易理解,我们需要用到该存储块控制 TFTLCD,
当然要使能这个存储块了。
SRAM/NOR 闪存片选时序寄存器:FSMC_BTRx(x=1~4)
这个寄存器包含了每个存储器块的控制信息, 可以用于SRAM、 ROM和NOR闪存存储器。如果 FSMC_BCRx 寄存器中设置了 EXTMOD 位,则有两个时序寄存器分别对应读(本寄存器)和写操作(FSMC_BWTRx 寄存器)。因为我们要求读写分开时序控制,所以 EXTMOD 是使能了的, 也就是本寄存器是读操作时序寄存器, 控制读操作的相关时序。 本章我们要用到的设置有:
ACCMOD、DATAST 和 ADDSET 这三个设置。
ACCMOD[1:0]:访问模式。 00 表示访问模式 A; 01 表示访问模式 B; 10
表示访问模式 C;11 表示访问模式 D,本章我们用到模式 A,
故设置为 00。
DATAST[7:0]:数据保持时间。0 为保留设置,其他设置则代表保持时间为:
DATAST 个HCLK 时钟周期, 最大为 255 个 HCLK 周期。
对 ILI9341 来说, 其实就是 RD 低电平持续时间,一般为
355ns。而一个 HCLK 时钟周期为 6ns 左右(1/168Mhz) ,
为了兼容其他屏,我们这里设置 DATAST 为 60,也就是 60 个
HCLK 周期,时间大约是 360ns。
ADDSET[3:0]:地址建立时间。 其建立时间为: ADDSET 个 HCLK 周期,
最大为 15 个 HCLK周期。对 ILI9341 来说,这里相当于 RD
高电平持续时间,为 90ns,我们设置 ADDSET 为 15,
即 15*6=90ns。
SRAM/NOR 闪写时序寄存器:FSMC_BWTRx(x=1~4) ,该寄存器各
位描述如图
该寄存器用作写操作时序控制寄存器, 我们需要用到的设置同样是: ACCMOD、 DATAST和 ADDSET 这三个设置。这三个设置的方法同FSMC_BTRx 一模一样,只是这里对应的是写操作的时序,ACCMOD 设置同 FSMC_BTRx 一模一样,同样是选择模式 A,另外 DATAST 和ADDSET 则对应低电平和高电平持续时间,对 ILI9341 来说,这两个时间只需要 15ns 就够了,比读操作快得多。所以我们这里设置 DATAST 为 2,即 3 个 HCLK 周期,时间约为 18ns。然后ADDSET 设置为 3,即 3 个 HCLK 周期,时间为 18ns。至此,我们对 STM32F4 的 FSMC 介绍就差不多了,通过以上两个小节的了解,我们可以开始写 LCD 的驱动代码了。不过,这里还要给大家做下科普,在 MDK 的寄存器定义里面,并没有定义 FSMC_BCRx、FSMC_BTRx、FSMC_BWTRx 等这个单独的寄存器,而是将他们进行了一些组合。
FSMC_BCRx 和 FSMC_BTRx,组合成 BTCR[8]寄存器组,他们的对应关系如下:
BTCR[0]对应 FSMC_BCR1,BTCR[1]对应 FSMC_BTR1
BTCR[2]对应 FSMC_BCR2,BTCR[3]对应 FSMC_BTR2
BTCR[4]对应 FSMC_BCR3,BTCR[5]对应 FSMC_BTR3
BTCR[6]对应 FSMC_BCR4,BTCR[7]对应 FSMC_BTR4
FSMC_BWTRx 则组合成 BWTR[7],他们的对应关系如下:
BWTR[0]对应 FSMC_BWTR1,BWTR[2]对应 FSMC_BWTR2,
BWTR[4]对应 FSMC_BWTR3,BWTR[6]对应 FSMC_BWTR4,
BWTR[1]、BWTR[3]和 BWTR[5]保留,没有用到。
FSMC初始化过程
①:FSMC的时钟使能用
RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE);
②:GPIO口的时钟使能,设置相关IO口为复用推挽输出
③:配置FSMC接口
①:选择存储器类型(SRAM要有选择块的区(1~4))
②:配置读写时序
③:延时,以待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手册)。
FMSC--SRAM
与彩屏控制类似,但是多了高字节控制和低字节控制,具体可以看看手册,由硬件自动控制。
首先说一个前提:STM32 单片机的一个地址(如:0x20000000)是一个字节
也就是说如果定义一个16位数组 u16 temp[5] 如果temp对应的地址是0x00000000 那么temp+1对应的地址是0x00000002 (地址是加2)
NBL[1:0]中NBL[1]为高字节使能,NBL[0]为低字节使能(都是低电平有效)。
这里有一点要注意,如果以8位模式对外设进行操作,HADDR[25:0]对应STM32芯片引脚A[25:0],因为MPU内部的地址增长规律是每8位增长1;而对于16位模式,HADDR[25:1]对应于芯片引脚的A[24:0],这也刚好符合MPU地址增长规律(每16位增长2),那么这时候并不是说HADDR[0]没有用处了,实际上它这时用于决定NBL[1:0]。
如果HADDR[0]=0,NBL[1:0]=01B,这时候访问的是外设16位中的低8位。
如果HADDR[0]=1,NBL[1:0]=10B,这时候访问的就是高8位了。
说白了,这里也就是一个译码器,HADDR[0]为译码器输入,NBL[1:0]是输出。
这就可以看出,虽然使用了不同的模式,但是对于MPU内部的地址增长却没有影响。