STM32学习(一)----LCD屏幕(FSMC)
FSMC简述
大容量,且引脚数在 100 脚以上的 STM32F103 芯片都带有 FSMC 接口。
FSMC,即灵活的静态存储控制器flexible static memory controller。
扩展内存
- STM32 的 FSMC 接口支持包括 SRAM、NAND FLASH、NOR FLASH 和 PSRAM 等存储器。
- FSMC就是一个MCU与外部存储器(SRAM,FLASH等)读写数据的一个接口
FSMC内部原理
FSMC 的框图
- NE[4-1] 片选,用来区分不同设备
- NWE为写。
- NOE为读
- n低电平有效
- o output
- e 使能
驱动SRAM
- FSMC驱动外部SRAM时,外部SRAM的控制一般有
- 地址线(如A0-A25)
- 数据线(如D0-D15)
- 写信号(WE,即WR)
- 读信号(OE,即RD)
- 片选信号(CS)
- 如果SRAM支持字节控制,那么还有UB/LB信号。
驱动TFTLCD
- 真正在操作LCD的时候需要用到的就只有:
- RS、D0~D15、WR、RD和CS。
- 其操作时序和SRAM的控制完全类似,唯一不同就是TFTLCD有RS信号,但是没有地址信号。(所以将RS当做地址线来用)
(该表格为F407的,与103不太一样,仅看个大概意思)
- TFTLCD通过RS信号来决定传送的数据是数据还是命令,本质上可以理解为一个地址信号
- 比如我们把*RS接在A0上面
- 那么当FSMC控制器写地址0的时候,会使得A0变为0,对TFTLCD来说,就是写命令。而FSMC写地址1的时候,A0将会变为1,对TFTLCD来说,就是写数据了
- 当然RS也可以接在其他地址线上
- 因此,可以把TFTLCD当成一个SRAM来用,只不过这个SRAM有2个地址,这就是FSMC可以驱动LCD的原理。
FSMC内存划分
FSMC的分块(存储块一的介绍)
STM32的 FSMC将外部存储器划分为固定大小为 256M 字节的四个存储块(Bank),FSMC 总共管理 1GB 空间.如下为FSMC在CPU中的地址映射划分。
各个模块的控制范围:
NOR和PSRAM地址映像
HADDR[27:26]位用于选择四个存储块之一:
HADDR[27:26] | 选择的存储块 |
---|---|
00 | 存储块1 NOR/PSRAM 1 |
01 | 存储块1 NOR/PSRAM 2 |
10 | 存储块1 NOR/PSRAM 3 |
11 | 存储块1 NOR/PSRAM 3 |
不同数据宽度对存储块1寻址的影响
HADDR是需要转换到外部存储器的内部AHB地址线。HADDR[25:0]包含外部存储器地址。HADDR是字节地址,而存储器访问不都是按字节访问,因此接到存储器的地址线依存储器的数据宽度有所不同,如下表:
需要或者可以访问的地址空间大小。
- 当Bank1接的是16位宽度存储器的时候:HADDR[25:1],FSMC_A[24:0]
- 当Bank1接的是8位宽度存储器的时候:HADDR[25:0],FSMC_A[25:0]
不论外部接8位/16位宽设备,FSMC_A[0]永远接在外部设备地址A[0]
这里需要注意的是:
这个地址映射,指的是你选择的数据宽度是哪种,然后对应会映射到哪种
- 数据宽度为8位时:比如HADDR映射的基地址是0x68000000,那么对于FSMC来说,也就是外部存储器就是0x00000000的地址,若HADDR内部地址+1变成0x68000001,那么外部地址也随着+1,变成0x00000001
- 数据宽度16位:比如HADDR映射的基地址是0x68000000,那么对于FSMC来说,也就是外部存储器就是0x00000000的地址,若HADDR内部地址+1变成0x68000001,但是由于HADDR的HADDR[1]与FSMC[0]相邻,反而右移一位,映射到外部存储器的地址依旧是0x00000000,同理,若内部+2,则外部就映射到0x00000002,
这就是为什么64要除以2
FSMC中地址与外设地址的对应关系
FSMC中的1G空间存储的是外设地址,当我们在存储块中的访问单元序号+1,对应的外设存储单元的访问地址就自加8(如果外设数据存储的数据宽度为8b的话)
STM32 的FSMC 模拟8080 接口时序
ILI9341 的 8080 通讯接口时序可以由 STM32 使用普通 I/O 接口进行模拟,但这样效率太低,STM32 提供了一种特别的控制方法——使用 FSMC 接口实现 8080 时序。
FSMC控制异步NORFLASH的时序
FSMC 外设支持输出多种不同的时序以便于控制不同的存储器,它具有 ABCD 四种模式,下面我们仅针对控制异步 NOR FLASH 使用的模式 B 进行讲解,见图FSMC写NOR_FLASH的时序图 。
- 读时序
- 写时序
当内核发出访问某个指向外部存储器地址时,FSMC 外设会根据配置控制信号线产生时序访问存储器,上图中的是访问外部异步 NOR FLASH(模式 B)时 FSMC 外设的读写时序。
以读时序为例,该图表示一个存储器操作周期由地址建立周期 (ADDSET)、数据建立周期(DATAST) 以及 2 个 HCLK 周期组成。在地址建立周期中,地址线发出要访问的地址,数据掩码信号线指示出要读取地址的高、低字节部分,片选信号使能存储器芯片;地址建立周期结束后读使能信号线发出读使能信号,接着存储器通过数据信号线把目标数据传输给 FSMC,FSMC 把它交给内核。
写时序类似,区别是它的一个存储器操作周期仅由地址建立周期 (ADDSET) 和数据建立周期(DATAST) 组成,且在数据建立周期期间写使能信号线发出写信号,接着 FSMC 把数据通过数据线传输到存储器中。
根据 STM32 对寻址空间的地址映射,地址 0x6000 0000 ~0x9FFF FFFF 是映射
到外部存储器的,而其中的0x6000 0000 ~0x6FFF FFFF 则是分配给 NOR FLASH、PSRAM 这类可直接寻址的器件。
当 FSMC 外设被配置成正常工作,并且外部接了 NOR FLASH 时,若向 0x60000000 地址写入数据如 0xABCD,FSMC 会自动在各信号线上产生相应的电平信号,写入数据。FSMC 会控制片选信号 NE1 选择相应的 NOR 芯片,然后使用地址线 A[25:0] 输出 0x60000000,在 NWE 写使能信号线上发出低电平的写使能信号,而要写入的数据信号 0xABCD 则从数据线 D[15:0] 输出,然后数据就被保存到 NOR FLASH 中了。
用FSMC模拟8080时序
对比 FSMC NOR/PSRAM 中的模式 B 时序与 ILI9341液晶控制器芯片使用的 8080 时序可发现,这两个时序是十分相似的 (除了 FSMC 的地址线 A 和8080 的 D/CX 线,可以说是完全一样)。
对于 FSMC 和 8080 接口,前四种信号线都是完全一样的,仅仅是 FSMC 的地址信号线 A[25:0] 与8080 的数据/命令选择线 D/CX 有区别。而对于 D/CX 线,它为高电平的时候表示数值,为低电平的时候表示命令,如果能使用 FSMC 的 A 地址线根据不同的情况产生对应的电平,那么就完全可以使用 FSMC 来产生 8080 接口需要的时序了。
为了模拟出 8080 时序,我们可以把 FSMC 的 A0 地址线 (也可以使用其它 A1/A2 等地址线) 与ILI9341 芯片 8080 接口的 D/CX 信号线连接,那么当 A0 为高电平时 (即 D/CX 为高电平),数据线 D[15:0] 的信号会被 ILI9341 理解为数值,若 A0 为低电平时 (即 D/CX 为低电平),传输的信号则会被理解为命令。
- 当使用 FSMC 向 0x6xxx xxx1、0x6xxx xxx3、0x6xxx xxx5…这些奇数地址写入数据时,地址最低位的值均为 1,所以它会控制地址线 A0(D/CX) 输出高电平,那么这时通过数据线传输的信号会被理解为数值;
- 若向 0x6xxx xxx0 、0x6xxx xxx2、0x6xxx xxx4…这些偶数地址写入数据时,地址最低位的值均为 0,所以它会控制地址线 A0(D/CX) 输出低电平,因此这时通过数据线传输的信号会被理解为命令
见表使用 *FSMC* 输出地址示例 :
注意:在实际控制时,以上地址计算方式还不完整,还需要注意 HADDR 内部地址与 FSMC 地址信号线的转换。
FSMC结构体
NORFLASH时序结构体
控制 FSMC 使用 NOR FLASH 存储器时主要是配置时序寄存器以及控制寄存器,利用 ST 标准库的时序结构体以及初始化结构体可以很方便地写入参数。
1 | typedef struct |
FSMC初始化结构体
1 | typedef struct |
(1) FSMC_Bank
本成员用于选择 FSMC 映射的存储区域,它的可选参数以及相应的内核地址映射范围见表可以选择的存储器区域及区域对应的地址范围
(2)FSMC_ExtendedMode本成员用于设置是否使用扩展模式(FSMC_ExtendedMode_Enable/Disable),在非扩展模式下,对存储器读写的时序都只使用 FSMC_BCR 寄存器中的配置,即下面的FSMC_ReadWriteTimingStruct 结构体成员;在扩展模式下,对存储器的读写时序可以分开配置,读时序使用 FSMC_BCR 寄存器,写时序使用 FSMC_BWTR 寄存器的配置,即后面的 FSMC_WriteTimingStruct 结构体成员。
FSMC—-液晶显示(野火板子)
使用 FSMC 外设控制实验板配套的 3.2 寸 ILI9341 液晶屏,见图 27-21,该液晶屏的分辨率为 320x240,支持 RGB565 格式。
硬件设计
图 27-21液晶屏背面的 PCB 电路对应图 27-22、图 27-23、图 27-24 中的原理图,分别是屏幕 PCB 底板原理图、触摸部分原理图、液晶排针接口线序图。
图 27-24 表示的是 PCB 底板引出的排针线序,屏幕整体通过这些引出的排针与开发板或其它控制器连接。
注意:其中请着重关注图中液晶屏 LCD_CS 及 LCD_RS(即 DC 引脚)与 FSMC 存储区选择引脚 FSMC_NE 及地址信号 FSMC_A 的编号,它们会决定 STM32 要使用什么内存地址来控制与液晶屏的通讯。
软件设计
编程要点
(1) 初始化通讯使用的目标引脚及端口时钟;
(2) 使能 FSMC 外设的时钟;
(3) 配置 FSMC 为异步 NOR FLASH 模式以仿真 8080 时序;
(4) 建立机制使用 FSMC 向液晶屏发送命令及数据;
(5) 发送控制命令初始化液晶屏;
(6) 编写液晶屏的绘制像素点函数;
(7) 利用描点函数制作各种不同的液晶显示应用。
配置GPIO引脚和FSMC的配置同SRAM一样,唯一不同的只有以下几条:
1 | readWriteTiming.FSMC_AccessMode = FSMC_AccessMode_B;//配置成模式B |
这里的建立时间和保持时间是通过经验值,具体计算也可以看ili9341的数据手册配置,如图27-26和27-27。
计算控制液晶屏时使用的地址
初始化完 FSMC 后,即可使用类似扩展外部 SRAM 中的读取方式:通过访问某个地址,由 FSMC 产生时序与外部存储器通讯,进行读写。
可以往上看原理不同数据宽度寻址影响,只要访问对应的地址,那么就能模拟出8080时序,从而对液晶屏进行访问,但是由于选择是十六位数据通信,就会存在地址偏移的问题,只要多左移动一位即可,:
例如液晶屏的CS引脚连接的是FSMC_NE1,而RS引脚是连接FSMC_A[16],那么只需要将基地址(0X6000 0000 |(1<<16+1))就可以在FSMC_A[16]输出高电平,从而表示数据,若(0X6000 0000 &(~(1<<16+1))),则表示清零,FSMC_A[16]输出低电平,从而表示命令
这样就能完成对ili9341的读写:
1 | /*************** ILI9341 显示屏的 FSMC 参数定义 ****************/ |
向液晶屏发送命令及发送数据的操作:
1 | /** |
ILI9341重要命令
- 画图的流程图
- 0x2A命令
- 前两个字节表示X轴起始位置的地方,后两个字节表示X轴末尾位置的地方
- 0x2B命令
- 前两个字节表示Y轴起始位置的地方,后两个字节表示Y轴末尾位置的地方
- 0x2C命令
- 发送n个数据,每个数据都是16位,表示一个格子的填充内容,用的是RGB565格式
颜色转换
红色 -> RGB888 -> 0xFF 00 00
红色 -> RBG565 -> 0x1F 00 00
计算公式为:
RGB565 = (R &(0x1F)<<11)|(G &(0x3F)<<5)|(B &(0x1F))
其中,R,G,B,分别为RBG888格式的数据,带入即可得到转换的数据
设置液晶的扫描方向
通过0x36命令就能设置液晶的扫描方向,分别设置三个位,MY,MX,MV。其中MY指的就是Y轴扫描方向,MX就是X轴扫描方向,MV就是XY轴兑换,一共有8种组合方式,如下图:
代码:
1 |
|
到这里,ILI9341驱动LCD就结束啦,可能还有一些没讲好哈,多多包涵。