在STM32上开发LCD显示,可以有两种方式来对LCD进行操作,一种是通过普通的IO口,连接LCM的相应引脚来进行操作,第2种是通过FSMC来进行操作。
1. LCD/LCM的基本概念
液晶显示器(Liquid Crystal Display: LCD)的构造是在两片平行的玻璃当中放置液态的晶体,两片玻璃中间有许多垂直和水平的细小电线,透过通电与否来控制杆状水晶分子改变方向,将光线折射出来产生画面。
LCM(LCD Module)即LCD显示模组、液晶模块,是指将液晶显示器件,连接件,控制与驱动等外围电路,PCB电路板,背光源,结构件等装配在一起的组件。
在平时的学习开发中,我们一般使用的是LCM,带有驱动IC和LCD屏幕等多个模块。
2.存储器的概念
存储器(Memory)是现代信息技术中用于保存信息的记忆设备。其概念很广,有很多层次,在数字系统中,只要能保存二进制数据的都可以是存储器;在集成 电路中,一个没有实物形式的具有存储功能的电路也叫存储器,如RAM、FIFO等;在系统中,具有实物形式的存储设备也叫存储器,如内存条、TF卡等。计 算机中全部信息,包括输入的原始数据、计算机程序、中间运行结果和最终运行结果都保存在存储器中。它根据控制器指 定的位置存入和取出信息。有了存储器,计算机才有记忆功能,才能保证正常工作。计算机中的存储器按用途存储器可分为主存储器(内存)和辅助存储器(外 存),也有分为外部存储器和内部存储器的分类方法。外存通常是磁性介质或光盘等,能长期保存信息。内存指主板上的存储部件,用来存放当前正在执行的数据和 程序,但仅用于暂时存放程序和数据,关闭电源或断电,数据会丢失。
以存储体(大量存储单元组成的阵列)为核心,加上必要的地址译码、读写控制电路,即为存储集成电路;再加上必要的I/O接口和一些额外的电路如存取策略管 理,则形成存储芯片,比如手机中常用的存储芯片。得益于新的IC制造或芯片封装工艺,现在已经有能力把DRAM和FLASH存储单元集成在单芯片里。存储 芯片再与控制芯片(负责复杂的存取控制、存储管理、加密、与其他器件的配合等)及时钟、电源等必要的组件集成在电路板上构成整机,就是一个存储产品,如U 盘。从存储单元(晶体管阵列)到存储集成电路再到存储设备,都是为了实现信息的存储,区别是层次的不同。
3.FSMC的概念
FSMC(Flexible Static Memory Controller,可变静态存储控制器)是STM32系列中内部集成256 KB以上FlaSh,后缀为xC、xD和xE的高存储密度微控制器特有的存储控制机制。之所以称为“可变”,是由于通过对特殊功能寄存器的设置,FSMC能够根据不同的外部存储器类型,发出相应的数据/地址/控制信号类型以匹配信号的速度,从而使得STM32系列微控制器不仅能够应用各种不同类型、不同速度的外部静态存储器,而且能够在不增加外部器件的情况下同时扩展多种不同类型的静态存储器,满足系统设计对存储容量、产品体积以及成本的综合要求。
FSMC技术优势:
①支持多种静态存储器类型。STM32通过FSMC可以与SRAM、ROM、PSRAM、NOR Flash和NANDFlash存储器的引脚直接相连。
②支持丰富的存储操作方法。FSMC不仅支持多种数据宽度的异步读/写操作,而且支持对NOR/PSRAM/NAND存储器的同步突发访问方式。
③支持同时扩展多种存储器。FSMC的映射地址空间中,不同的BANK是独立的,可用于扩展不同类型的存储器。当系统中扩展和使用多个外部存储器时,FSMC会通过总线悬空延迟时间参数的设置,防止各存储器对总线的访问冲突。
④支持更为广泛的存储器型号。通过对FSMC的时间参数设置,扩大了系统中可用存储器的速度范围,为用户提供了灵活的存储芯片选择空间。
⑤支持代码从FSMC扩展的外部存储器中直接运行,而不需要首先调入内部SRAM。
FSMC内部结构:
FSMC包含两类控制器:1个NOR闪存/SRAM控制器,可以与NOR闪存、SRAM和PSRAM存储器接口。1个NAND闪存/PC卡控制器,可以与NAND闪存、PC卡,CF卡和CF+存储器接口。
STM32微控制器之所以能够支持NOR Flash和NAND Flash这两类访问方式完全不同的存储器扩展,是因为FSMC内部实际包括NOR Flash和NAND/PC Card两个控制器,分别支持两种截然不同的存储器访问方式。在STM32内部,FSMC的一端通过内部高速总线AHB连接到内核Cortex-M3,另一端则是面向扩展存储器的外部总线。内核对外部存储器的访问信号发送到AHB总线后,经过FSMC转换为符合外部存储器通信规约的信号,送到外部存储器的相应引脚,实现内核与外部存储器之间的数据交互。FSMC起到桥梁作用,既能够进行信号类型的转换,又能够进行信号宽度和时序的调整,屏蔽掉不同存储类型的差异,使之对内核而言没有区别。
FSMC映射地址空间:
FSMC管理1 GB的映射地址空间。该空间划分为4个大小为256 MB的BANK,每个BANK又划分为4个64 MB的子BANK。FSMC的2个控制器管理的映射地址空间不同。NOR Flash控制器管理第1个BANK,NAND/PC Card控制器管理第2~4个BANK。由于两个控制器管理的存储器类型不同,扩展时应根据选用的存储设备类型确定其映射位置。其中,BANK1的4个子BANK拥有独立的片选线和控制寄存器,可分别扩展一个独立的存储设备,而BANK2~BANK4只有一组控制寄存器。
FSMC 包括4个模块:
(1)AHB接口(包括FSMC配置寄存器)
(2)NOR闪存和PSRAM控制器(驱动LCD的时候LCD就好像一个PSRAM的里面只有2个16位的存储空间,一个是DATA RAM 一个是CMD RAM)
(3)NAND闪存和PC卡控制器
(4)外部设备接口
小结:
FSMC是一种用于为STM32扩展外部存储器的控制器,它是一种控制器!
FSMC控制器,包括AHB接口及两个控制器,NOR Flash和NAND/PC Card两个控制器。
FSMC分为4个BANK,其中NOR Flash(BANK1),NAND/PC Card(BANK2-4)。
控制器产生所有驱动这些存储器的信号时序:
1. 16位数据线,用于连接8位或16位的存储器;
2. 26位地址线,最多可连续64MB的存储器(这里不包括片选线);
3. 5位独立的片选信号线;
4. 1组适合不同类型存储器的控制信号线。
控制读/写操作:
- 与存储器通信,提供就绪/繁忙信号和中断信号。
- 与所用配置的PC卡接口:PC存储卡、PC I/O卡和真正的IDE接口。
从FSMC的角度看,可以把外部存储器划分为固定大小为256MB的4个存储块:
· 存储块1用于访问最多4个NOR闪存或者PSRAM存储设备。这个存储区被划分为4个NOR/PSRAM区,并有4个专用的片选。
· 存储块2和3用于访问NAND闪存设备,每个存储块连接一个NAND闪存。
· 存储块4用于访问PC卡设备。
每一个存储块上的存储器类型是由用户在配置寄存器中定义的。
注意:FSMC只是提供了一个控制器,并不提供相应的存储设备,至于外设接的是什么设备,完全是由用户自己选择,只要能用于FSMC控制,就可以,像本次实验中,我们接的就是LCM。
FSMC对外部设备的地址映像从0x6000 0000开始,到0x9FFF FFFF结束,共分4个地址块,每个地址块256M字节。可以看出,每个地址块又分为4个分地址块,大小64M。对NOR的地址映像来说,我们可以通过选 择HADDR[27:26]来确定当前使用的是哪个64M的分地址块,如下页表格。而这四个分存储块的片选,则使用NE[4:1]来选择。数据线/地址线 /控制线是共享的。
NE1 ->Bank1 NE2->Bank2NE3->Bank3NE4->Bank4
若 NE1 连接, 则:
每小块NOR/PSRAM 64M。
第一块:6000 0000h--63ff ffffh (DATA长度为8位情况下,由地址线FSMC_A[25:0]决定;DATA长度为16位情况下,由地址线FSMC_A[24:0]决定)。
第二块:6400 0000h--67ff ffffh。
第二块:6800 0000h--6bff ffffh。
第三块:6c00 0000h--6fff ffffh。
注:这里的HADDR是需要转换到外部设备的内部AHB地址线,每个地址对应一个字节单元。因此,若外部设备的地址宽度是8位的,则 HADDR[25:0]与STM32的CPU引脚FSMC_A[25:0]一一对应,最大可以访问64M字节的空间。若外部设备的地址宽度是16位的,则 是HADDR[25:1]与STM32的CPU引脚FSMC_A[24:0]一一对应。在应用的时候,可以将FSMC_A总线连接到存储器或其他外设的地 址总线引脚上。
使用FSMC控制器后,可以把FSMC提供的FSMC_A[25:0]作为地址线,而把FSMC提供的FSMC_D[15:0]作为数据总线。
(1)当存储数据设为8位时,(FSMC_NANDInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_8b)
地址各位对应FSMC_A[25:0],数据位对应FSMC_D[7:0]
(2)当存储数据设为16位时,(FSMC_NANDInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b)
地址各位对应FSMC_A[24:0],数据位对应FSMC_D[15:0]
4.ILI9325
ILI9325的功能很多,在此无法一一说明,但是参考ILI9325的Datasheet我们发现有几个引脚还是非常重要的,而只要操作好了这几个引脚,基本上就可以实现简单的对LCM的控制了。
nCS: IC的片选信号。如果是低电平,则ILI9325是被选中,并且可以进行操作,如果是高电平,这不被选中。
RS: 寄存器选择信号。如果是低电平,则选择的是索引或者状态寄存器,如果是高电平,则选择控制寄存器。
nWR/SCL: 写使能信号,低电平有效。
nRD: 读使能信号,低电平有效。
5. 电路设计
1. 信号线的连接
STM32F10x FSMC有4个不同的banks,每一个64MB,可支持NOR以及其他类似的存储器。这些外部设备的地址线、数据线和控制线是共享的。每个设备的访问时通过片选信号来决定的,而每次只能访问一个设备。我们的LCM就是连接在NOR的bank上面。
FSMC_D[15:0]:16bit的数据总线,连接ILI9325的数据线; FSMC_NEx:分配给NOR的256MB的地址空间还可以分为4个banks,每一个区用来分配一个外设,这4个外设分别就是NE1-NE4; FSMC_NOE:输出使能,连接ILI9325的nRD引脚; FSMC_NWE:写使能,连接ILI9325的nWR引脚。
FSMC_Ax:用在LCD显示RAM和寄存器之间进行选择的地址线,这个和ILI9325的RS引脚相连。该线可用任意一根地址线,范围是FSMC_A[25:0]。当RS=0时,表示读写寄存器,RS=1时,表示读写数据RAM。
其实关于RS的表述也并不完全准确,应该这么理解,RS=0的时候,向这个地址写的数表示了选择什么寄存器进行操作,然而要对寄存器进行什么操作,则要看当RS=1时,送入的数据了。
关于地址的计算,如果我们选择NOR的第一个存储区,并且使用FSMC_A16来控制ILI9325的RS引脚,则如果要访问寄存器地址(RS=0),那 么地址是0x6000 0000(起始地址),如果要访问数据区(RS=1),那么基地址应该是0x6002 0000。
有人会问,为什么不是0x6001 0000呢?因为FSMC_A16=1。因为在前文中已经说过,若外部设备的地址宽度是16位的,则是HADDR[25:1]与STM32的CPU引脚 FSMC_A[24:0]一一对应。也就是说,内部产生的地址应该要左移一位,FSMC_A16=1,代表着第17位为1,而不是第16位为1。如果外部 设备的地址宽度是8位的话,则不会出现这个问题。
再举一个例子,如果选择NOR的第4个存储区,使用FSMC_A0来控制RS引脚,则访问数据区的地址为0x6000 0002,访问LCD寄存器的地址为:0x6000 0000。
2. 时序问题
一般使用模式2来做LCD的接口控制,不使用外扩模式。并且读写操作的时序一样。此种情况下,我们需要使用3个参数:ADDSET、DATAST、ADDHOLD。时序的计算需要根据NOR闪存存储器的特性和STM32F10x的时钟HCLK来计算这些参数。
写或读访问时序是存储器片选信号的下降沿与上升沿之间的时间,这个时间可以由FSMC时序参数的函数计算得到:
写/读访问时间 = ((ADDSET + 1) + (DATAST + 1)) × HCLK
在写操作中,DATAST用于衡量写信号的下降沿与上升沿之间的时间参数:
写使能信号从低变高的时间 = t WP = DATAST × HCLK
为了得到正确的FSMC时序配置,下列时序应予以考虑:
最大的读/写访问时间、不同的FSMC内部延迟、不同的存储器内部延迟
因此得到:
((ADDSET + 1) + (DATAST + 1)) × HCLK = max (t WC , t RC )
DATAST × HCLK = tWP
DATAST必须满足:
DATAST = (tAVQV+ tsu(Data_NE) + tv(A_NE) )/HCLK – ADDSET – 4
由于我没有找到ILI9325的这些时序的参数,所以就参考了一些以前别人写的程序里面的时序配置。当 HCLK 的频率是 72MHZ,使用模式 B,则有如下时序:
地址建立时间:0x1
地址保持时间:0x0
数据建立时间:0x5
在论坛上问为什么FSMC调试会进入Handler fault。没人回答。当然也不好回答,这些问题是不可预知,更无法估测。所以自己调来调去。调了整整一天也未见结果。左一右一次的对着寄存器一位一位的设置。后来设计想是不是应该用到库,是不是自己操作寄存器不好。带着苦恼回宿舍睡觉了。(9点了工作室关门了,也没那么牛X学到1,2点,当然我绝对佩服他们)今天早上,我再次对了寄存器,看到了其中有两位会产生AHB硬件fault我则将这两个都使能,结果,结果成功了。不再进入Handler fault了。这让我感觉惭愧,原因昨天晚上想过会不会是这两个问题,但是麻烦的心理让我改了前一个望了后一个,总有一个处于非使能状态。。
一旦通过就写了TFT的驱动,调试发现无法打开TFT DISP。oh 又无语中,不断的调试,找引脚连接图,最终发现数据手册上的引脚标错了。。叹。也怪自己。因为第一处标的是对的,自己看的第二处。。就这样今天一天也算差不多了,写好了TFT驱动显示了字符,可以横屏竖屏,并可以显示满屏,很开心。
而横屏和竖屏很是绕人,也经过了个把小时才弄通了。
这里为了以后不会忘记再次提及一下自己。我用的TFT使用ILI9341和9325不一样,只看到了E文,不过上面寄存器那边的单词还算简单。这里主要用到了0X36,0X2A,0X2B几个寄存器,而其它的不再记录。及ILI9341的使用和坐标" title="关于FSMC驱动LCD的总结,进入HardFault_Handler 及ILI9341的使用和坐标" style="border-width: 0px; list-style: none;">
以左上角为TFT屏的原点,如果置位MY则Y坐标将映射到对面同一条线上的点即319的点上,MX同理也会到对面同一直线的点上为239。(319和239为我屏的尺寸不表多数)如果同时设置了这两个点则原点会到(0,0)的对角线即最大坐标上(239,319)。而MV则是液晶屏的点亮方向(可以这么理解)它的点亮方向即向X方向点亮还是向Y方向点亮。
当然点亮屏幕的像素还和0X2A和0X2B命令有关。及ILI9341的使用和坐标" title="关于FSMC驱动LCD的总结,进入HardFault_Handler 及ILI9341的使用和坐标" style="border-width: 0px; list-style: none;">
0x2A设置列的长度,有4个参数,前两个参数为列的首坐标,后两个参数为列坐标的结束坐标。
及ILI9341的使用和坐标" title="关于FSMC驱动LCD的总结,进入HardFault_Handler 及ILI9341的使用和坐标" action-data="http%3A%2F%2Fs9.sinaimg.cn%2Fmiddle%2F79fbacedn7aaafe89e648%26690" action-type="show-slide" style="border-width: 0px; list-style: none;">
0X2B则是设置页地址即屏幕上到下的大小。设置了2A和2B整个操作只在这个区域才能被实现。
因此我们根据0x36中的MX和MY所设的坐标,和MV所设置的方向设置整个屏的大小。
假设屏水平放置,即水平方向为320,垂直方向为240.屏的左上角为坐标0,0。假设设置MV以X方向向右点亮,假设要点亮整个屏则需要将0X2A设置成319,0x2B设置成213。如果设置反了则 会出现以以下的情况及ILI9341的使用和坐标" title="关于FSMC驱动LCD的总结,进入HardFault_Handler 及ILI9341的使用和坐标" action-data="http%3A%2F%2Fs6.sinaimg.cn%2Fmiddle%2F79fbacedncaae0c593e95%26690" action-type="show-slide" style="border-width: 0px; list-style: none;">
这些都是个人理解。如果你是在调节液晶屏的横竖屏都显示的话你只要设置0X36、0X2A、0X2B这三个寄存器即可。可以自己调试点亮一排像素来得到自己想要的结果。