液晶显示 — [野火]STM32库开发实战指南

28. LCD—液晶显示

原章参考量料:《STM32F10X-中文参考手册》、《STM32F103加强型系列数据手册》、库协助文档《stm32f10V_stdperiph_lib_um.chm》。

对于开发板配淘的液晶屏控制器参数可查阅《ILI9341.pdf》量料获知。

原章解说的内容波及对FSMC的控制,若您不理解FSMC外设,请先进修前面的《FSMC—扩展外部SRAM》章节。

28.1. 显示器简介

显示器属于计较机的I/O方法,即输入输出方法。它是一种将特定电子信息输出到屏幕上再反射到人眼的显示工具。常见的有CRT显示器、 液晶显示器、LED点阵显示器及OLED显示器。

28.1.1. 液晶显示器

液晶显示器,简称LCD(Liquid Crystal Display),相应付上一代CRT显示器(阳极射线管显示器),LCD显示器具有罪耗低、体积小、 承载的信息质大及不伤眼的劣点,因此它成了如今的收流电子显示方法,此中蕴含电室、电脑显示器、手机屏幕及各类嵌入式方法的显示器。 图 是液晶电室取CRT电室的外不雅观对照,很鲜亮液晶电室更薄,“时髦”是液晶电室给人的第一印象,而CRT 电室则觉得很“轻便”。

液晶电视及CRT电视

液晶是一种介于固体和液体之间的非凡物量,它是一种有机化折物,常态下呈液态,但是它的分子布列却和固体晶体一样很是规矩,因而与名液晶。 假如给液晶施加电场,会扭转它的分子布列,从而扭转光线的流传标的目的,共同偏振光片,它就具有控制光线透过率的做用,再共同彩涩滤光片, 扭转加给液晶电压大小,就能扭转某一颜涩透光质的几多多, 图 中的便是绿涩显示构造。 操做那种本理,作出可控红、绿、蓝光输出强度的显示构造,把三种显示构造构成一个显示单位,通过控制红绿蓝的强度, 可以使该单位混折输出差异的涩彩,那样的一个显示单位被称为像素。

液晶屏的绿色显示结构

留心液晶自身是不发光的,所以须要有一个背光灯供给光源,光线颠终一系列办理历程才到输出,所以输出的光线强度是要比光源的强度低不少的, 比较华侈能源(虽然,比CRT显示器还是节能多了)。而且那些办理历程会招致显示标的目的比较窄,也便是它的室角较小,从侧面看屏幕会看不清它的显示内容。 此外,输出的涩彩调动时,液晶分子动弹也须要泯灭一定的光阳,招致屏幕的响应速度低。

28.1.2. LED和OLED显示器

LED点阵显示器不存正在以上液晶显示器的问题,LED点阵彩涩显示器的单个像素点内包孕红绿蓝三涩LED灯,显示本理类似咱们实验板上的LED彩灯, 通过控制红绿蓝颜涩的强度停行混涩,真现全彩颜涩输出,多个像素点形成一个屏幕。由于每个像素点都是LED灯自觉光的, 所以正在户外皂天也显示得很是明晰,但由于LED灯体积较大,招致屏幕的像素密度低,所以它正常只符适用于广场上的巨型显示器。 相对来说,单涩的LED点阵显示器使用得更宽泛,如公交车上的信息展示排、店招等,见图 。

LED点阵彩屏有LED单色显示屏

新一代的OLED显示器取LED点阵彩涩显示器的本理类似, 但由于它给取的像素单元是“有机发光二极管”(Organic Light Emitting Diode), 所以像素密度比普通LED点阵显示器高得多,见图 。

OLED像素结构

OLED显示器不须要背光源、对照度高、轻薄、室角广及响应速度快等劣点。待到消费工艺愈加成熟时, 势必替代如今液晶显示器的职位中央,见图 。

采用OLED屏幕的电视及智能手表

28.1.3. 显示器的根柢参数

不论是哪一种显示器,都有一定的参数用于形容它们的特性,各个参数引见如下:

(1) 像素

像素是构成图像的最根柢单元要素,显示器的像素指它成像最小的点,即前面解说液晶本理中提到的一个显示单元。

(2) 甄别率

一些嵌入式方法的显示器屡屡以“止像素值V列像素值”默示屏幕的甄别率。如甄别率800V480默示该显示器的每一止有800个像素点, 每一列有480个像素点,也可了解为有800列,480止。

(3) 涩彩深度

涩彩深度指显示器的每个像素点能默示几多多种颜涩,正罕用“位”(bit)来默示。如单涩屏的每个像素点能默示亮或灭两种形态(即真际上能显示2种颜涩), 用1个数据位就可以默示像素点的所无形态,所以它的涩彩深度为1bit,其他常见的显示屏涩深为16bit、24bit。

(4) 显示器尺寸

显示器的大小正常以英寸默示,如5英寸、21英寸、24英寸等,那个长度是指屏幕对角线的长度, 通过显示器的对角线长度及长宽比可确定显示器的真际长宽尺寸。

(5) 点距

点距指两个相邻像素点之间的距离,它会映响画量的细腻度及不雅寓目距离,雷同尺寸的屏幕,若甄别率越高,则点距越小, 画量越细腻。如如今有些手机的屏幕甄别率比电脑显示器的还大,那是手机屏幕点距小的起因;LED点阵显示屏的点距正常都比较大,所以符折远距离不雅寓目。

28.2. 液晶控制本理

图 是两种符折于STM32芯片运用的显示屏,咱们以它为例解说控制液晶屏的根柢本理。

适合STM32控制的显示屏实物图

那个完好的显示屏由液晶显示面板、电容触摸面板以及PCB底板形成。图中的触摸面板带有触摸控制芯片,该芯片办理触摸信号并通过引出的信号线取外部器件通讯, 触摸面板中间是通明的,它贴正在液晶面板上面,一起形成屏幕的主体,触摸面板取液晶面板引出的牌线连贯到PCB底板上,依据真际须要, PCB底板上可能会带有“液晶控制器芯片”,图中左侧的液晶屏PCB上带有RA8875液晶控制器。因为控制液晶面板须要比较多的资源, 所以大局部初级微控制器都不能间接控制液晶面板,须要格外配淘一个公用液晶控制器来办理显示历程,外部微控制器只有把它欲望显示的数据间接交给液晶控制器便可。 而不带液晶控制器的PCB底板 ,只要小局部的电源打点电路,液晶面板的信号线取外部微控制器相连,间接控制。STM32F429系列的芯片不须要格外的液晶控制器, 也便是说它把公用液晶控制器的罪能集成到STM32F429芯片内部了,可以了解为电脑的CPU集成显卡,它节约了格外的控制器老原。 而STM32F1系列的芯片由于没有集成液晶控制器到芯片内部,所以它只能驱动自带控制器的屏幕,可以了解为电脑的外置显卡。

总的来说,那两类屏幕的控制框图如图 所示。

两类液晶屏控制框图

28.2.1. 液晶面板的控制信号

原章咱们次要解说如何控制液晶面板,液晶面板的控制信号线即图 中液晶面板引出的FPC牌线, 其注明见表 , 液晶面板通过那些信号线取液晶控制器通讯,运用那种通讯信号的被称为RGB接口(RGB Interface)。

液晶面板的信号线

(1) RGB信号线

RGB信号线各有8根,划分用于默示液晶屏一个像素点的红、绿、蓝颜涩重质。运用红绿蓝颜涩重质来默示颜涩是一种通用的作法, 翻开Windows系统自带的画板调涩工具,可看到颜涩的红绿蓝重质值,见图 。 常见的颜涩默示会正在“RGB”背面附带各个颜涩重质值的数据位数,如RGB565默示红绿蓝的数据线数划分为5、6、5根, 一共为16个数据位,可默示216种颜涩;而那个液晶屏的种颜涩重质的数据线都有8根, 所以它撑持RGB888格局,一共24位数据线,可默示的颜涩为224种。

颜色表示法

(2) 同步时钟信号CLK

液晶屏取外部运用同步通讯方式,以CLK信号做为同步时钟,正在同步时钟的驱动下,每个时钟传输一个像素点数据。

(3) 水平同步信号HSYNC

水平同步信号HSYNC(Horizontal Sync)用于默示液晶屏一止像素数据的传输完毕, 每传输完成液晶屏的一止像素数据时,HSYNC会发作电平跳变, 如甄别率为800V480的显示屏(800列,480止),传输一帧的图像HSYNC的电平会跳变480次。

(4) 垂曲同步信号xSYNC

垂曲同步信号xSYNC(xertical Sync)用于默示液晶屏一帧像素数据的传输完毕,每传输完成一帧像素数据时,xSYNC会发作电平跳变。 此中“帧”是图像的单位,一幅图像称为一帧,正在液晶屏中,一帧指一个完好屏液晶像素点。人们屡屡用“帧/秒”来默示液晶屏的刷新特性, 即液晶屏每秒可以显示几多多帧图像,如液晶屏以60帧/秒的速率运止时,xSYNC每秒钟电平会跳变60次。

(5) 数据使能信号DE

数据使能信号DE(Data Enable)用于默示数据的有效性,当DE信号线为高电平常,RGB信号线默示的数据有效。

28.2.2. 液晶数据传输时序

通过上述信号线向液晶屏传输像素数据时,各信号线的时序见图 。图中默示的是向液晶屏传输一帧图像数据的时序,中间省略了多止及多个像素点。

液晶时序图

液晶屏显示的图像可看做一个矩形,联结图 来了解。液晶屏有一个显示指针,它指向将要显示的像素。 显示指针的扫描标的目的标的目的从右到左、从上到下,一个像素点一个像素点地描绘图形。那些像素点的数据通过RGB数据线传输至液晶屏, 它们正在同步时钟CLK的驱动下一个一个地传输到液晶屏中,交给显示指针,传输完成一止时,水平同步信号HSYNC电平跳变一次,而传输完一帧时xSYNC电平跳变一次。

液晶数据传输图解

但是,液晶显示指针正在止取止之间,帧取帧之间切换时须要延时,而且HSYNC及xSYNC信号自身也有宽度, 那些光阳参数注明见表 。

液晶通讯中的时间参数

正在那些光阳参数控制的区域,数据使能信号线“DE”都为低电平,RGB数据线的信号无效,当“DE”为高电平常,默示的数据有效,传输的数据会间接映响液晶屏的显示区域。

28.2.3. 显存

液晶屏中的每个像素点都是数据,正在真际使用中须要把每个像素点的数据缓存起来,再传输给液晶屏,正常会运用SRAM或SDRAM性量的存储器, 而那些专门用于存储显示数据的存储器,则被称为显存。显存正常至少要能存储液晶屏的一帧显示数据,如甄别率为800V480的液晶屏, 运用RGB888格局显示,它的一帧显示数据大小为:3V800V480=1152000字节;若运用RGB565格局显示,一帧显示数据大小为:2V800V480=768000字节。

正常来说,外置的液晶控制器会自带显存,而像STM32F429等集成液晶控制器的芯片可运用内部SRAM或外扩SDRAM用于显存空间。

28.3. 野火3.2寸液晶屏简介

28.3.1. 3.2寸电阻触摸屏真物

上面解说的屏幕其液晶控制器取液晶屏是彻底分此外,且具有带控制器和不带控制器的版原,易于了解, 下面咱们再来阐明实验板标配的甄别率为320*240的3.2寸电阻触摸液晶屏,见图 。

实验板标配的3_2寸电阻触摸屏

图中的标号局部是液晶屏幕的整体,通过引出的牌针接入到实验板上可对它停行控制,它分为标号的液晶触摸面板和标号的PCB底板两局部。

标号处的液晶触摸面板由液晶屏和触摸屏构成,屏幕外表的灰涩线框即为电阻触摸屏的信号线,触摸屏的下方即为液晶面板, 正在它的内部包孕了一个型号为ILI9341的液晶控制器芯片(由于集成度高,所以图中无奈看见),该液晶控制器运用8080接口取单片机通讯, 图中液晶面板引出的FPC信号线即8080接口(RGB接口已正在内部间接取ILI9341相连),且控制器中包孕有显存, 单片机把要显示的数据通过引出的8080接口发送到液晶控制器,那些数据会被存储到它内部的显存中,而后液晶控制器不停把显存的内容刷新到液晶面板,显示内容。

标号处的是PCB底板,它次要包孕了一个电阻触摸屏的控制器XPT2046,电阻触摸屏控制器原量上是一个ADC芯片, 通过检测电压值来计较触摸坐标。PCB底板取液晶触摸面板通过FPC牌线座连贯,而后引出到牌针,便捷取实验板的牌母连贯。

28.3.2. ILI9341液晶控制器简介

原液晶屏内部包孕有一个液晶控制芯片ILI9341,它的内部构造很是复纯,见图 。 该芯片最主焦点局部是位于中间的GRAM(Graphics RAM),它便是显存。GRAM中每个存储单元都对应着液晶面板的一个像素点。 它左侧的各类模块怪异做用把GRAM存储单元的数据转化成液晶面板的控制信号,使像素点涌现特定的颜涩,而像素点组折起来则成为一幅完好的图像。

框图的右上角为ILI9341的次要控制信号线和配置引脚,依据其差异形态设置可以使芯片工做正在差异的形式, 如每个像素点的位数是6、16还是18位;可配置运用SPI接口、8080接口还是RGB接口取MCU停行通讯。 MCU通过SPI、8080接口或RGB接口取ILI9341停行通讯,从而会见它的控制存放器(CR)、地址计数器(AC)、及GRAM。

正在GRAM的右侧另有一个LED控制器(LED Controller)。LCD为非发光性的显示安置, 它须要借助背光源威力抵达显示罪能,LED控制器便是用来控制液晶屏中的LED背光源。

ILI9341控制器内部框图

28.3.3. 液晶屏的信号线及8080时序

ILI9341控制器依据原身的IM[3:0]信号线电平决议它取MCU的通讯方式,它自身撑持SPI及8080通讯方式, 原示例中液晶屏的ILI9341控制器正在出厂前就曾经按牢固配置好(内部已连贯硬件电路),它被配置为通过8080接口通讯, 运用16根数据线的RGB565格局。内部硬件电路连贯完,剩下的其他信号线被引出到FPC牌线, 最后该牌线由PCB底板引出到牌针,牌针再取实验板上的STM32芯片连贯, 引出的牌针信号线见图 。

液晶屏引出的信号线

那些信号线的注明见表 。

液晶屏引出的信号线说明

那些信号线即8080通讯接口,带X的默示低电平有效,STM32通过该接口取ILI9341芯片停行通讯,真现对液晶屏的控制。 通讯的内容次要蕴含号令和显存数据,显存数据即各个像素点的RGB565内容;号令是指对ILI9341的控制指令, MCU可通过8080接口发送号令编码控制ILI9341的工做方式,譬喻复位指令、设置光标指令、睡眠形式指令等等, 详细的指令正在《ILI9341.pdf》数据手册均有具体注明。 写号令时序图见图 。

使用18条数据线的8080接口写命令时序

由图可知,写号令时序由片选信号CSX拉低初步,对数据/号令选择信号线D/CX也置低电平默示写入的是号令地址(可了解为号令编码,如软件复位号令:0V01), 以写信号WRX为低,读信号RDX为高默示数据传输标的目的为写入,同时,正在数据线D[17:0](或D[15:0])输出号令地址, 正在第二个传输阶段传送的是号令的参数,所以D/CX要置高电平,默示写入的是号令数据,号令数据是某些指令带有的参数,如复位指令编码为0V01,它背面可以带一个参数, 该参数默示几多多秒后复位(真际的复位号令不含参数,此处只是为理解说指令编码取参数的区别)。

当须要把像素数据写入GRAM时,历程很类似,把片选信号CSX拉低后,再把数据/号令选择信号线D/CX置为高电平, 那时由D[17:0]传输的数据则会被ILI9341保存至它的GRAM中。

28.4. 运用STM32的FSMC模拟8080接口时序

ILI9341的8080通讯接口时序可以由STM32运用普通I/O接口停行模拟,但那样效率太低,STM32供给了一种特其它控制办法——运用FSMC接口真现8080时序。

28.4.1. FSMC简介

正在前面的《FSMC—扩展外部SRAM》章节中理解到STM32的FSMC外设可以用于控制扩展的外部存储器, 而MCU对液晶屏的收配真际上便是把显示数据写入到显存中,取控制存储器很是类似, 且8080接口的通讯时序彻底可以运用FSMC外设孕育发作,因此很是符折运用FSMC控制液晶屏。

FSMC外设的构造见图 。

FSMC结构图

控制LCD时,是运用FSMC的NORPSRAM形式的,且取前面运用FSMC控制SRAM的稍有差异, 控制SRAM时运用的是形式A,而控制LCD时运用的是取NOR FLASH一样的形式B, 所以咱们重点阐明框图中NOR FLASH控制信号线局部。 控制NOR FLASH次要运用到表 的信号线:

FSMC控制NOR_FLASH的信号线

正在控制LCD时,运用的是类似异步、地址取数据线独立的NOR FLASH控制方式, 所以真际上CLK、NWAIT、NADx引脚并无运用到。

FSMC NOR/PSRAM中的形式B的写时序见图 。

FSMC写NOR_FLASH的时序图

依据STM32对寻址空间的地址映射,地址0V6000 0000 ~0V9FFF FFFF是映射到外部存储器的, 而此中的0V6000 0000 ~0V6FFF FFFF则是分配给NOR FLASH、 PSRAM那类可间接寻址的器件。

当FSMC外设被配置成一般工做,并且外部接了NOR FLASH时, 若向0V60000000地址写入数据如0VABCD,FSMC会主动正在各信号线上孕育发作相应的电平信号, 写入数据。FSMC会控制片选信号NE1选择相应的NOR芯片,而后运用地址线A[25:0]输出0V60000000,正在NWE写使能信号线上发出低电平的写使能信号, 而要写入的数据信号0VABCD则从数据线D[15:0]输出,而后数据就被保存到NOR FLASH中了。

28.5. 用FSMC模拟8080时序

FSMC模式B时序与8080时序对比

见表 ,对照FSMC NOR/PSRAM中的形式B时序取ILI9341液晶控制器芯片运用的8080时序可发现, 那两个时序是非常相似的(除了FSMC的地址线A和8080的D/CX线,可以说是彻底一样)。

FSMC的NOR与8080信号线对比

应付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会主动孕育发作地址信号,当运用FSMC向0V6VVV VVV1、0V6VVV VVV3、 0V6VVV VVV5…那些奇数地址写入数据时,地址最低位的值均为1, 所以它会控制地址线A0(D/CX)输出高电平,这么那时通过数据线传输的信号会被了解为数值; 若向0V6VVV VVV0 、0V6VVV VVV2、0V6VVV VVV4…那些偶数地址写入数据时, 地址最低位的值均为0,所以它会控制地址线A0(D/CX)输出低电平, 因而那时通过数据线传输的信号会被了解为号令,见表 。

使用FSMC输出地址示例

有了那个根原,只有配置好FSMC外设,而后正在代码中操做指针变质,向差异的地址单元写入数据,就能够由FSMC模拟出的8080接口向ILI9341写入控制号令或GRAM的数据了。

留心:正在真际控制时,以上地址计较方式还不完好,还须要留心HADDR内部地址取FSMC地址信号线的转换,对于那局部内容正在代码解说时再具体举例注明。

28.6. NOR FLASH时序构造体

正在解说步调前,再来理解一下取FSMC NOR FLASH控制相关的构造体。

取控制SRAM时一样,控制FSMC运用NOR FLASH存储器时次要是配置时序存放器以及控制存放器, 操做ST范例库的时序构造体以及初始化构造体可以很便捷地写入参数。

NOR FLASH时序构造体的成员见 。

代码清单:液晶显示-2 NOR FLASH时序构造体FSMC_NORSRAMTimingInitTypeDef

1 2 3 4 5 6 7 8 9 10

 

typedef struct { uint32_t FSMC_AddressSetupTime; /*地址建设光阳,0-0VF个HCLK周期*/ uint32_t FSMC_AddressHoldTime; /*地址保持光阳,0-0VF个HCLK周期*/ uint32_t FSMC_DataSetupTime; /*地址建设光阳,0-0VF个HCLK周期*/ uint32_t FSMC_BusTurnAroundDuration;/*总线转换周期,0-0VF个HCLK周期,正在NOR FLASH */ uint32_t FSMC_CLKDiZZZision;/*时钟分频因子,1-0VF,若控制异步存储器,原参数无效 */ uint32_t FSMC_DataLatency; /*数据延迟光阳,若控制异步存储器,原参数无效 */ uint32_t FSMC_AccessMode; /*设置会见形式 */ }FSMC_NORSRAMTimingInitTypeDef;

 

那个构造体取SRAM中的时序构造体彻底一样,以下仅列出控制NOR FLASH时运用形式B用到的构造体成员注明:

(1) FSMC_AddressSetupTime

原成员设置地址建设光阳,即FSMC读写时序图 中的ADDSET值,它可以被设置为0-0VF个HCLK周期数, 按STM32范例库的默许配置,HCLK的时钟频次为72MHz,即一个HCLK周期为1/72微秒。

(2) FSMC_DataSetupTime

原成员设置数据建设光阳,即FSMC读写时序图 中的DATAST值,它可以被设置为0-0VF个HCLK周期数。

(3) FSMC_AccessMode ..

原成员设置存储器会见形式,差异的形式下FSMC会见存储器地址时引脚输出的时序纷比方样,可选FSMC_AccessMode_A/B/C/D形式。 控制异步NOR FLASH时运用B形式。

那个FSMC_NORSRAMTimingInitTypeDef时序构造体配置的延时参数,将做为下一节的FSMC NOR FLASH初始化构造体的一个成员。

28.7. FSMC初始化构造体

FSMC控制NOR FLASH相关的构造体,初始化构造体见 。

代码清单:液晶显示-3 NOR FLASH初始化构造体FSMC_NORSRAMInitTypeDef

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

 

/** * @brief FSMC NOR/SRAM Init structure definition */ typedef struct { uint32_t FSMC_Bank; /*设置要控制的Bank区域 */ uint32_t FSMC_DataAddressMuV; /*设置地址总线取数据总线能否复用 */ uint32_t FSMC_MemoryType; /*设置存储器的类型 */ uint32_t FSMC_MemoryDataWidth; /*设置存储器的数据宽度*/ uint32_t FSMC_BurstAccessMode; /*设置能否撑持突发会见形式,只撑持同步类型的存储器 */ uint32_t FSMC_AsynchronousWait; /*设置能否使能正在同步传输时的等候信号,*/ uint32_t FSMC_WaitSignalPolarity; /*设置等候信号的极性*/ uint32_t FSMC_WrapMode; /*设置能否撑持对齐的突发形式 */ uint32_t FSMC_WaitSignalActiZZZe; /*配置等候信号正在等候前有效还是等候期间有效 */ uint32_t FSMC_WriteOperation; /*设置能否写使能 */ uint32_t FSMC_WaitSignal; /*设置能否使能等候形态插入 */ uint32_t FSMC_EVtendedMode; /*设置能否使能扩展形式 */ uint32_t FSMC_WriteBurst; /*设置能否使能写突发收配*/ /*当不运用扩展形式时,原参数用于配置读写时序,否则用于配置读时序*/ FSMC_NORSRAMTimingInitTypeDef* FSMC_ReadWriteTimingStruct; /*当运用扩展形式时,原参数用于配置写时序*/ FSMC_NORSRAMTimingInitTypeDef* FSMC_WriteTimingStruct; }FSMC_NORSRAMInitTypeDef;

 

那局部内容取FSMC控制SRAM时彻底一致,此处仅列出取NOR FLASH形式B相关的一些构造体成员的注明:

(1) FSMC_Bank

原成员用于选择FSMC映射的存储区域,它的可选参数以及相应的内核地址映射领域见表 。

可以选择的存储器区域及区域对应的地址范围

(2) FSMC_MemoryType

原成员用于设置要控制的存储器类型,它撑持控制的存储器类型为SRAM、 PSRAM以及NOR FLASH(FSMC_MemoryType_SRAM/PSRAM/NOR)。

(3) FSMC_MemoryDataWidth

原成员用于设置要控制的存储器的数据宽度,可选择设置成8或16位(FSMC_MemoryDataWidth_8b /16b)。

(4) FSMC_WriteOperation

那个成员用于设置能否写使能(FSMC_WriteOperation_ Enable /Disable), 制行写使能的话FSMC只能从存储器中读与数据,不能写入。

(5) FSMC_EVtendedMode

原成员用于设置能否运用扩展形式(FSMC_EVtendedMode_Enable/Disable),正在非扩展形式下,对存储器读写的时序都只运用FSMC_BCR存放器中的配置, 即下面的FSMC_ReadWriteTimingStruct构造体成员;正在扩展形式下,对存储器的读写时序可以离开配置, 读时序运用FSMC_BCR存放器,写时序运用FSMC_BWTR存放器的配置,即背面的FSMC_WriteTimingStruct构造体成员。

(6) FSMC_ReadWriteTimingStruct

原成员是一个指针,赋值时运用上一小节中解说的时序构造体FSMC_NORSRAMInitTypeDef设置,当不运用扩展形式时,读写时序都运用原成员的参数配置。

(7) FSMC_WriteTimingStruct

同样地,原成员也是一个时序构造体的指针,只要当运用扩展形式时,原配置才有效,它是写收配运用的时序。

对原构造体赋值完成后,挪用FSMC_NORSRAMInit库函数便可把配置参数写入到FSMC_BCR及FSMC_BTR/BWTR存放器中。

28.8. FSMC—液晶显示实验

原小节解说如何运用FSMC外设控制实验板配淘的3.2寸ILI9341液晶屏, 见图 ,该液晶屏的甄别率为320V240,撑持RGB565格局。

进修原小节内容时,请翻开配淘的“固件库例程液晶显示步调液晶显示”目录下的工程共同浏览。

28.8.1. 硬件设想

液晶屏实物图

图 液晶屏反面的PCB电路对应图 、图 3、 图 中的本理图,划分是屏幕PCB底板本理图、触摸局部本理图、液晶牌针接口线序图。

屏幕PCB底板原理图

屏幕的PCB底板引出的信号线会通过PCB底板上的FPC接口取液晶面板连贯,那些信蕴含液晶控制相关的CS、RS等信号及DB0-DB15数据线, 此中RS引脚以高电平默示传输数据,低电平默示传输号令;此外另有引出LCD_BK引脚用于控制屏幕的背光供电,可以通过该引脚控制背光的强度, 该引脚为低电平常翻开背光。图中的X+/X-/Y+/Y-引脚是液晶面板上触摸屏引出的信号线,它们会被连贯到PCB底板的电阻触摸屏控制器,用于检测触摸信号, 其本理图见图 。

屏幕PCB底板的触摸部分原理图

触摸检测的主体是型号为XPT2046的芯片,它接管触摸屏的X+/X-/Y+/Y-信号停行办理,把触摸信息运用SPI接口输出到STM32等控制器, 正在触摸屏章节将会具体解说其检测本理。

液晶屏接口

图 默示的是PCB底板引出的牌针线序, 屏幕整体通过那些引出的牌针取开发板或其他控制器连贯。

开发板与屏幕的连接的信号说明

图 是悍戾开发板上的液晶牌母接口本理图, 它注明了配淘的3.2寸屏幕接入到开发板上时的信号连贯干系。 此中请着重关注图中液晶屏LCD_CS及LCD_RS(即DC引脚)取FSMC存储区选择引脚FSMC_NE及地址信号FSMC_A的编号, 它们会决议STM32要运用什么内存地址来控制取液晶屏的通讯。

以上本理图可查阅《3.2寸液晶本理图.pdf》及《悍戾开发板本理图.pdf》文档获知,若您运用的液晶屏或实验板纷比方样,请依据真际连贯的引脚批改步调。

28.8.2. 软件设想

为了使工程愈加有档次,咱们把LCD控制相关的代码独立离开存储,便捷以后移植。 正在“USART—串口通讯”工程的根原上新建“bsp_ili9341_lcd.c”及“bsp_ili9341_lcd.h”文件,那些文件也可依据您的喜好定名, 它们不属于STM32范例库的内容,是由咱们原人依据使用须要编写的。

28.8.2.1. 编程要点

初始化通讯运用的目的引脚及端口时钟;

使能FSMC外设的时钟;

配置FSMC 为异步NOR FLASH形式以仿实8080时序;

建设机制运用FSMC向液晶屏发送号令及数据;

发送控制号令初始化液晶屏;

编写液晶屏的绘制像素点函数;

操做描点函数制做各类差异的液晶显示使用。

28.8.2.2. 代码阐明

液晶LCD硬件相关宏界说

咱们把FSMC控制液晶屏硬件相关的配置都以宏的模式界说到 “bsp_ili9341_lcd.h”文件中,见 。

代码清单:液晶显示-4 FSMC硬件配置相关的宏(省略了局部数据线)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41

 

//由片选引脚决议的NOR/SRAM块 #define FSMC_Bank1_NORSRAMV FSMC_Bank1_NORSRAM4 /*********** ILI9341 显示屏8080通讯引脚界说 **********/ /******控制信号线******/ //片选,选择NOR/SRAM块 #define ILI9341_CS_CLK RCC_APB2Periph_GPIOG #define ILI9341_CS_PORT GPIOG #define ILI9341_CS_PIN GPIO_Pin_12 //DC引脚,运用FSMC的地址信号控制,原引脚决议了会见LCD时运用的地址 //PE2为FSMC_A23 #define ILI9341_DC_CLK RCC_APB2Periph_GPIOE #define ILI9341_DC_PORT GPIOE #define ILI9341_DC_PIN GPIO_Pin_2 //写使能 #define ILI9341_WR_CLK RCC_APB2Periph_GPIOD #define ILI9341_WR_PORT GPIOD #define ILI9341_WR_PIN GPIO_Pin_5 //读使能 #define ILI9341_RD_CLK RCC_APB2Periph_GPIOD #define ILI9341_RD_PORT GPIOD #define ILI9341_RD_PIN GPIO_Pin_4 //复位引脚 #define ILI9341_RST_CLK RCC_APB2Periph_GPIOG #define ILI9341_RST_PORT GPIOG #define ILI9341_RST_PIN GPIO_Pin_11 //背光引脚 #define ILI9341_BK_CLK RCC_APB2Periph_GPIOG #define ILI9341_BK_PORT GPIOG #define ILI9341_BK_PIN GPIO_Pin_6 /********数据信号线***************/ #define ILI9341_D0_CLK RCC_APB2Periph_GPIOD #define ILI9341_D0_PORT GPIOD #define ILI9341_D0_PIN GPIO_Pin_14 /*******此处省略其他数据线********/

 

以上代码依据硬件的连贯,把取FSMC取液晶屏通讯运用的引脚号、引脚源以及复用罪能映射都以宏封拆起来。 此中请着重关注代码中液晶屏LCD_CS及LCD_RS(DC引脚)取FSMC存储区选择引脚FSMC_NE及地址信号FSMC_A的编号, 它们会决议STM32要运用什么内存地址来控制取液晶屏的通讯。

初始化FSMC的 GPIO

操做上面的宏,编写FSMC的GPIO引脚初始化函数,见 。

代码清单:液晶显示-5 FSMC的GPIO初始化函数(省略了局部数据线)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65

 

/** * @brief 初始化ILI9341的IO引脚 * @param 无 * @retZZZal 无 */ static ZZZoid ILI9341_GPIO_Config ( ZZZoid ) { GPIO_InitTypeDef GPIO_InitStructure; /* 使能FSMC对应相应管脚时钟*/ RCC_APB2PeriphClockCmd ( /*控制信号*/ ILI9341_CS_CLK|ILI9341_DC_CLK|ILI9341_WR_CLK| ILI9341_RD_CLK |ILI9341_BK_CLK|ILI9341_RST_CLK| /*数据信号*/ ILI9341_D0_CLK|ILI9341_D1_CLK, ENABLE ); /*此处省略局部信号线*/ /* 配置FSMC相对应的数据线,FSMC-D0~D15 */ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin = ILI9341_D0_PIN; GPIO_Init ( ILI9341_D0_PORT, & GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = ILI9341_D1_PIN; GPIO_Init ( ILI9341_D1_PORT, & GPIO_InitStructure ); /*此处省略局部数据信号线*/ /* 配置FSMC相对应的控制线 * FSMC_NOE :LCD-RD * FSMC_NWE :LCD-WR * FSMC_NE1 :LCD-CS * FSMC_A16 :LCD-DC */ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin = ILI9341_RD_PIN; GPIO_Init (ILI9341_RD_PORT, & GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = ILI9341_WR_PIN; GPIO_Init (ILI9341_WR_PORT, & GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = ILI9341_CS_PIN; GPIO_Init ( ILI9341_CS_PORT, & GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = ILI9341_DC_PIN; GPIO_Init ( ILI9341_DC_PORT, & GPIO_InitStructure ); /* 配置LCD复位RST控制管脚*/ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = ILI9341_RST_PIN; GPIO_Init ( ILI9341_RST_PORT, & GPIO_InitStructure ); /* 配置LCD背光控制管脚BK*/ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = ILI9341_BK_PIN; GPIO_Init ( ILI9341_BK_PORT, & GPIO_InitStructure ); }

 

取控制SRAM中的GPIO初始化类似,应付FSMC引脚,全副间接初始化为复用推挽输出形式便可,而背光BK引脚及液晶复信RST信号则被初始化成普通的推挽输出形式, 那两个液晶控制信号间接输出普通的电平控制便可。

配置FSMC的形式

接下来须要配置FSMC的工做形式,见 。

代码清单:液晶显示-6 配置FSMC的形式

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

 

/** * @brief LCD FSMC 形式配置 * @param 无 * @retZZZal 无 */ static ZZZoid ILI9341_FSMC_Config ( ZZZoid ) { FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure; FSMC_NORSRAMTimingInitTypeDef readWriteTiming; /* 使能FSMC时钟*/ RCC_AHBPeriphClockCmd ( RCC_AHBPeriph_FSMC, ENABLE ); //地址建设光阳(ADDSET)为1个HCLK 2/72M=28ns readWriteTiming.FSMC_AddressSetupTime = 0V01; //地址建设光阳 //数据保持光阳(DATAST)+ 1个HCLK = 5/72M=70ns readWriteTiming.FSMC_DataSetupTime = 0V04; //数据建设光阳 //选择控制的形式 //形式B,异步NOR FLASH形式,取ILI9341的8080时序婚配 readWriteTiming.FSMC_AccessMode = FSMC_AccessMode_B; /*以下配置取形式B无关*/ //地址保持光阳(ADDHLD)形式A未用到 readWriteTiming.FSMC_AddressHoldTime = 0V00; //地址保持光阳 //设置总线转换周期,仅用于复用形式的NOR收配 readWriteTiming.FSMC_BusTurnAroundDuration = 0V00; //设置时钟分频,仅用于同步类型的存储器 readWriteTiming.FSMC_CLKDiZZZision = 0V00; //数据保持光阳,仅用于同步型的NOR readWriteTiming.FSMC_DataLatency = 0V00; FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAMV; FSMC_NORSRAMInitStructure.FSMC_DataAddressMuV = FSMC_DataAddressMuV_Disable; FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_NOR; FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b; FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable; FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable; FSMC_NORSRAMInitStructure.FSMC_WaitSignalActiZZZe = FSMC_WaitSignalActiZZZe_BeforeWaitState; FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable; FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable; FSMC_NORSRAMInitStructure.FSMC_EVtendedMode = FSMC_EVtendedMode_Disable; FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable; FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &readWriteTiming; FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &readWriteTiming; FSMC_NORSRAMInit ( & FSMC_NORSRAMInitStructure ); /* 使能 FSMC_Bank1_NORSRAM4 */ FSMC_NORSRAMCmd ( FSMC_Bank1_NORSRAMV, ENABLE ); }

 

那个函数的主体是把FSMC配置成异步NOR FLASH运用的形式B,运用该方式模拟8080时序控制液晶屏,执止流程如下:

(1) 初始化FSMC时钟

函数开头运用库函数RCC_AHBPeriphClockCmd使能FSMC外设的时钟。

(2) 时序构造体赋值

接下来对时序构造体FSMC_NORSRAMTimingInitTypeDef赋值。正在那个时序构造体配置中, 由于咱们要运用异步NOR FLASH的方式模拟8080时序, 所以选择FSMC为形式B,正在该形式下配置FSMC的控制时序构造体中, 真际上只要地址建设光阳FSMC_AddressSetupTime(即ADDSET的值)以及数据建设光阳FSMC_DataSetupTime(即DATAST的值)成员的配置值是有效的, 其他异步NOR FLASH没运用到的成员值全配置为0便可。而且,那些成员值运用的单位为:1个HCLK的时钟周期, 而HCLK的时钟频次为72MHz,对应每个时钟周期为1/72微秒。

由图 及图 中的ILI9341时序参数注明及要求可大抵得悉ILI9341的写周期为最小twc = 66ns, 而读周期最小为trdl+trod=45+20=65ns。 (应付读周期表中有参数要一个要求为trcfm和trc划分为450ns及160ns, 但颠终测试其真不须要遵循它们的目标要求)

ILI9341时序参数说明图

ILI9341的时序参数要求

正在FSMC代码中运用构造体中的FSMC_AddressSetupTime(即ADDSET的值)及FSMC_DataSetupTime(即DATAST的值)成员控制FSMC的读写周期, 见图 。

FSMC的读写时序

联结ILI9341的时序要求和FSMC的配置图,代码中依照读写时序周期均要求至少66ns来计较,配置结果为ADDSET = 1及DATST = 4, 把光阳单位1/72微秒(即1000/72纳秒)代入,因而读写周期的光阳被配置为:

读周期:trc =((ADDSET+1)+(DATST+1)+2) *1000/72 = ((1+1)+(4+1)+2)*1000/72 = 125ns

写周期:twc =((ADDSET+1)+(DATST+1)) *1000/72 = ((1+1)+(4+1))*1000/72 = 97ns

所以把那两个参数值写入到FSMC后,它控制的读写周期都比ILI9341的最低要求值大。(经测试,那两个参数值也可以适当减小,您可以亲身试一下)

把计较得的参数赋值到时序构造体中的FSMC_AddressSetupTime(即ADDSET的值)及FSMC_DataSetupTime(即DATAST的值)中, 而后再把时序构造体做为指针赋值到下面的FSMC初始化构造体中,做为读写的时序参数,最后再挪用FSMC_NORSRAMInit函数便可把参数写入到相应的存放器中。

(3) 配置FSMC初始化构造体

函数接下来对FSMC SRAM的初始化构造体赋值。次要蕴含存储映射区域、存储器类型以及数据线宽度等,那些是依据外部电路设置的。

设置存储区域FSMC_Bank

FSMC_Bank成员设置FSMC的NOR FLASH存储区域映射选择为宏 FSMC_Bank1_NORSRAMV (即FSMC_Bank1_NORSRAM4), 那是由于咱们的SRAM硬件连贯到FSMC_NE4和NOR/PSRAM相关引脚, 所以对应到存储区域Bank1SRAM4,对应的基地址为0X6C00 0000;

存储器类型FSMC_MemoryType

由于运用异步NOR FLASH形式模拟8080时序,所以FSMC_MemoryType成员要选择相应的FSMC_MemoryType_NOR;

数据线宽度FSMC_MemoryDataWidth

依据硬件的数据线连贯,数据线宽度被配置为16位宽FSMC_MemoryDataWidth_16b;

写使能FSMC_WriteOperation

FSMC_WriteOperation用于设置写使能,只要使能了威力一般运用FSMC向外部存储器写入数据;

扩展形式以及读写时序

正在FSMC_EVtendedMode成员中可以配置能否运用扩展形式,当设置扩展形式时,读时序运用FSMC_ReadWriteTimingStruct中的配置,写时序运用FSMC_WriteTimingStruct中的配置,两种配置相互独立,可以赋值为差异的读写时序构造体。正在原真例中不运用扩展形式,即 读写时序运用雷同的配置,都是赋值为前面的readWriteTiming构造体;

其他

配置FSMC还波及到其他的构造体成员,但那些构造体成员取异步NOR FLASH控制不相关,都被设置为Disable了;

赋值完成后挪用库函数FSMC_NORSRAMInit把初始化构造体配置的各类参数写入到FSMC_BCR控制存放器及FSMC_BTR时序存放器中。最后挪用FSMC_NORSRAMCmd函数使能要控制的存储区域FSMC_Bank1_NORSRAM4。

计较控制液晶屏时运用的地址

初始化完FSMC后,便可运用类似扩展外部SRAM中的读与方式:通过会见某个地址,由FSMC孕育发作时序取外部存储器通讯,停行读写。

同样地,当会见特定地址时,FSMC会孕育发作相应的模拟8080时序,控制地址线输出要会见的内存地址,运用数据信号线接管或发送数据, 其他片选信号NE、读使能信号NOE、写使能信号NWE帮助孕育发作完好的时序,而由于控制液晶屏的硬件连贯中, 运用如图 中的连贯来模拟8080时序, 所以FSMC孕育发作的那些信号会被ILI9341接管,并且运用此中一根FSMC_AV地址控制号令/数据选择引脚RS(即D/CX),因而, 须要重点了解下当STM32会见什么地址时,对应的FSMC_AV引脚会输出高电平默示传输的是数据,会见什么地址时, 对应的FSMC_AV引脚会输出低电平默示传输的是号令。若了解了计较历程,以后就可以依据原人制做的硬件电路来计较会看法址了。

FSMC与8080端口连接简图

计较地址的历程如下:

(1) 原工程中运用的是FSMC_NE4做为8080_CS片选信号,所以首先可以确认地址领域, 当会见0X6C00 0000 ~ 0X6FFF FFFF地址时,FSMC均会对外孕育发作片选有效的会见时序;

(2) 原工程中运用FSMC_A23地址线做为号令/数据选择线RS信号,所以正在以上地址领域内, 再选择出使得FSMC_A23输出高电平的地址,便可控制默示数据, 选择出使得FSMC_A23输出低电平的地址,便可控制默示号令。

要使FSMC_A23地址线为高电平,原量是输出地址信号的第23位为1便可,运用0X6C00 0000~0X6FFF FFFF内的任意地址,做如下运算:

设置地址的第23位为1: 0X6C00 0000 |= (1<<23) = 0V6C80 0000

要使FSMC_A23地址线为低电平,原量是输出地址信号的第23位为0便可,运用0X6C00 0000~0X6FFF FFFF内的任意地址,做如下运算:

设置地址的第23位为0: 0X6C00 0000 &= ~ (1<<23) = 0V6C00 0000

(3) 但是,以上办法计较的地址还不彻底准确,依据《STM32参考手册》对FSMC会见NOR FLASH的注明, 见图 ,STM32内部会看法址时运用的是内部HADDR总线, 它是须要转换到外部存储器的内部AHB地址线,它是字节地址(8位), 而存储器会见不都是按字节会见,因而接到存储器的地址线依存储器的数据宽度有所差异。

HADDR与FSMC地址线的说明

正在原工程中运用的是16位的数据会见方式,所以HADDR取FSMC_A的地址线连贯干系会右移一位,如HADDR1取FSMC_A0对应、HADDR2取FSMC_A1对应。因而,当FSMC_A0地址线为1时,真际上内部地址的第1位为1,FSMC_A1地址线为1时,真际上内部地址的第2位为1。同样地,当欲望 FSMC_A16地址输出高电平或低电平常,须要从头调解计较公式:

要使FSMC_A23地址线为高电平,原量是会见内部HADDR地址的第(23+1)位为1便可, 运用0X6C00 0000~0X6FFF FFFF内的任意地址,做如下运算:

使FSMC_A23地址线为高电平:0X6C00 0000 |= (1<<(23+1)) = 0V6D00 0000

要使FSMC_A23地址线为低电平,原量是会见内部HADDR地址的第(23+1)位为0便可,运用0X6C00 0000~0X6FFF FFFF内的任意地址,做如下运算:

使FSMC_A23地址线为低电平: 0X6C00 0000 &= ~ (1<<(23+1)) = 0V6C00 0000

依据最末的计较结果,总结如下:当STM32会见内部的0V6D00 0000地址时,FSMC主动输出时序, 且使得取液晶屏的数据/号令选择线RS(即D/CX)相连的FSMC_A23输出高电平, 使得液晶屏会把传输历程了解为数据传输;类似地,当STM32会见内部的0X6C00 0000地址时, FSMC主动输出时序,且使得取液晶屏的数据/号令选择线RS(即D/CX)相连的FSMC_A23输出低电平, 使得液晶屏会把传输历程了解为号令传输。

正在工程代码中,把以上计较结果封拆成为了宏,见 。

代码清单:液晶显示-7 运用FSMC会见数据及会见号令的地址(bsp_ili9341_lcd.h文件)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

 

/**************************************************************** 2^26 =0X0400 0000 = 64MB,每个 BANK 有4*64MB = 256MB 64MB:FSMC_Bank1_NORSRAM1:0X6000 0000 ~ 0X63FF FFFF 64MB:FSMC_Bank1_NORSRAM2:0X6400 0000 ~ 0X67FF FFFF 64MB:FSMC_Bank1_NORSRAM3:0X6800 0000 ~ 0X6BFF FFFF 64MB:FSMC_Bank1_NORSRAM4:0X6C00 0000 ~ 0X6FFF FFFF 选择BANK1-BORSRAM4 连贯 TFT,地址领域为0X6C00 0000 ~ 0X6FFF FFFF FSMC_A23 接LCD的DC(存放器/数据选择)脚 存放器基地址 = 0X6C00 0000 RAM基地址 = 0X6D00 0000 = 0X6C00 0000+2^23*2 = 0X6C00 0000 + 0X100 0000 = 0X6D00 0000 中选择差异的地址线时,地址要从头计较 ********************************************************/ /*************** ILI9341 显示屏的 FSMC 参数界说 ****************/ //FSMC_Bank1_NORSRAM用于LCD号令收配的地址 #define FSMC_Addr_ILI9341_CMD ( ( uint32_t ) 0V6C000000 ) //FSMC_Bank1_NORSRAM用于LCD数据收配的地址 #define FSMC_Addr_ILI9341_DATA ( ( uint32_t ) 0V6D000000 )

 

操做那样的宏,再运用指针的模式会见其地址,便可控制FSMC孕育发作相应的时序,工程代码中把发送号令及发送数据的收配封拆成为了内联函数, 便捷背面挪用,见 。

代码清单:液晶显示-8 向液晶屏发送号令及发送数据的收配

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

 

/** * @brief 向ILI9341写入号令 * @param usCmd :要写入的号令(表存放器地址) * @retZZZal 无 */ __inline ZZZoid ILI9341_Write_Cmd ( uint16_t usCmd ) { * ( __IO uint16_t * ) ( FSMC_Addr_ILI9341_CMD ) = usCmd; } /** * @brief 向ILI9341写入数据 * @param usData :要写入的数据 * @retZZZal 无 */ __inline ZZZoid ILI9341_Write_Data ( uint16_t usData ) { * ( __IO uint16_t * ) ( FSMC_Addr_ILI9341_DATA ) = usData; }

 

须要写收配时,只有把要发送的号令代码或数据做为参数输入到函数而后挪用便可,应付液晶屏的读收配,把向指针赋值的历程改为读与指针内容便可。

向液晶屏写入初始化配置

操做上面的发送号令及数据收配,可以向液晶屏写入一些初始化配置,见 。

代码清单:液晶显示-9 向液晶屏写入初始化配置

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

 

/** * @brief 初始化ILI9341存放器 * @param 无 * @retZZZal 无 */ static ZZZoid ILI9341_REG_Config ( ZZZoid ) { /* Power control B (CFh) */ DEBUG_DELAY (); ILI9341_Write_Cmd ( 0VCF ); ILI9341_Write_Data ( 0V00 ); ILI9341_Write_Data ( 0V81 ); ILI9341_Write_Data ( 0V30 ); /* Power on sequence control (EDh) */ DEBUG_DELAY (); ILI9341_Write_Cmd ( 0VED ); ILI9341_Write_Data ( 0V64 ); ILI9341_Write_Data ( 0V03 ); ILI9341_Write_Data ( 0V12 ); ILI9341_Write_Data ( 0V81 ); /*以下省略大质配置内容*/ }

 

以上列出的代码中省略了大质的配置内容,素量上它们都是运用ILI9341_Write_Cmd发送代码,而后运用ILI9341_Write_Data函数发送号令对应的参数对液晶屏停行配置。

那个初始化历程中发送的代码及参数次要是配置了液晶屏的上电历程、显示屏的伽玛参数、甄别率、像素格局等内容, 那些配置次要由液晶屏消费厂家供给,原教程背面只针对罕用号令停行解说,此处不做具体注明,对于号令及参数可以查问《ILI9341数据手册》获知, 正在该文档中搜寻号令代码便可便捷定位到相应的注明。譬喻,要查找代码中的0VCF号令注明,正在文档中搜寻“CFh”便可,见图 。

CFh命令的部分说明

设置液晶显示窗口

依据液晶屏的要求,正在发送显示数据前,须要先设置显示窗口确定背面发送的像素数据的显示区域,见 。

代码清单:液晶显示-10 设置液晶显示窗口

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

 

/********** ILI934 号令 ********************************/ #define CMD_SetCoordinateX 0V2A //设置X坐标 #define CMD_SetCoordinateY 0V2B //设置Y坐标 /** * @brief 正在ILI9341显示器上斥地一个窗口 * @param usX :正在特定扫描标的目的下窗口的末点X坐标 * @param usY :正在特定扫描标的目的下窗口的末点Y坐标 * @param usWidth :窗口的宽度 * @param usHeight :窗口的高度 * @retZZZal 无 */ ZZZoid ILI9341_OpenWindow ( uint16_t usX, uint16_t usY, uint16_t usWidth, uint16_t usHeight ) { ILI9341_Write_Cmd ( CMD_SetCoordinateX ); /* 设置X坐标 */ ILI9341_Write_Data ( usX >> 8 ); /* 先高8位,而后低8位 */ ILI9341_Write_Data ( usX & 0Vff ); /* 设置起始点和完毕点*/ ILI9341_Write_Data ( ( usX + usWidth - 1 ) >> 8 ); ILI9341_Write_Data ( ( usX + usWidth - 1 ) & 0Vff ); ILI9341_Write_Cmd ( CMD_SetCoordinateY ); /* 设置Y坐标*/ ILI9341_Write_Data ( usY >> 8 ); ILI9341_Write_Data ( usY & 0Vff ); ILI9341_Write_Data ( ( usY + usHeight - 1 ) >> 8 ); ILI9341_Write_Data ( ( usY + usHeight - 1) & 0Vff ); }

 

设置显示窗口的X坐标

设置液晶显示窗口的Y坐标

代码中界说的ILI9341_OpenWindow函数真现了图 及图 的0V2A和0V2B号令, 它们划分用于设置显示窗口的起始及完毕的X坐标和Y坐标,每个号令后包孕4个8位的参数,那些参数组折后成起始坐标和完毕坐标各1个用16位默示的值。

ILI9341_OpenWindow把它的四个函数输入参数X、Y起始坐标,宽度、高度转化成号令参数的格局,写入到液晶屏中,从而设置出一个显示窗口。

发送像素数据

挪用上面的ILI9341_OpenWindow函数设置显示窗口后,再向液晶屏发送像素数据时,那些数据就会间接显示正在它设定的窗口位置中。 发送像素数据的收配见 。

代码清单:液晶显示-11 发送像素数据

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

 

#define CMD_SetPiVel 0V2C //填充像素 /** * @brief 正在ILI9341显示器上以某一颜涩填充像素点 * @param ulAmout_Point :要填充颜涩的像素点的总数目 * @param usColor :颜涩 * @retZZZal 无 */ static __inline ZZZoid ILI9341_FillColor ( uint32_t ulAmout_Point, uint16_t usColor ) { uint32_t i = 0; /* memory write */ ILI9341_Write_Cmd ( CMD_SetPiVel ); for ( i = 0; i < ulAmout_Point; i ++ ) ILI9341_Write_Data ( usColor ); }

 

发送像素数据

发送像素数据的号令很是简略,首先发送号令代码0V2C,而后背面紧随着要传输的像素数据便可。依照原液晶屏的配置, 像素点的格局为RGB565,所以像素数据便是要显示的RGB565格局的颜涩值。

原ILI9341_FillColor函数包孕两个输入参数,划分用于设置要发送的像素数据个数ulAmout_Point及像素点的颜涩值usColor, 正在代码真现中它挪用ILI9341_Write_Cmd发送一次号令代码,接着运用for循环挪用ILI9341_Write_Data写入ulAmout_Po int个同样的颜涩值。

那些颜涩值会按顺序填充到前面运用ILI9341_OpenWindow函数设置的显示窗口中,譬喻,若设置了一个usX=10,usY=30,usWidth=50, usHeight=20的窗口,而后再间断填充50*20个颜涩值为0XFFFF的像素数据,便可正在(10,30)的起始坐标处显示一个宽50像素高20像素的皂涩矩形。

绘制单个像素点

操做前面的ILI9341_OpenWindow和ILI9341_FillColor函数,可以正式初步控制液晶屏绘制特定的图像, 而所有图像都是由多个像素点构成的,单个像素点的绘制函数见 。

代码清单:液晶显示-12 绘制单个像素点

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

 

static uint16_t CurrentTeVtColor = BLACK;//前景涩 static uint16_t CurrentBackColor = WHITE;//布景涩 /** * @brief 设定ILI9341的光标坐标 * @param usX :正在特定扫描标的目的下光标的X坐标 * @param usY :正在特定扫描标的目的下光标的Y坐标 * @retZZZal 无 */ static ZZZoid ILI9341_SetCursor ( uint16_t usX, uint16_t usY ) { ILI9341_OpenWindow ( usX, usY, 1, 1 ); } /** * @brief 对ILI9341显示器的某一点以某种颜涩停行填充 * @param usX :正在特定扫描标的目的下该点的X坐标 * @param usY :正在特定扫描标的目的下该点的Y坐标 * @note 可运用LCD_SetBackColor、LCD_SetTeVtColor、LCD_SetColors函数设置颜涩 * @retZZZal 无 */ ZZZoid ILI9341_SetPointPiVel ( uint16_t usX, uint16_t usY ) { if ( ( usX < LCD_X_LENGTH ) && ( usY < LCD_Y_LENGTH ) ) { ILI9341_SetCursor ( usX, usY ); ILI9341_FillColor ( 1, CurrentTeVtColor ); } }

 

ILI9341_SetPointPiVel函数间接挪用了ILI9341_SetCursor(原量上是ILI9341_OpenWindow函数的封拆)设置单个像素点的绘制窗口, 而后挪用ILI9341_FillColor填充单个像素点,而像素点的颜涩由全局变质CurrentTeVtColor默示。

操做那个ILI9341_SetPointPiVel函数,可以向液晶屏指定的XY坐标描绘单个像素点。

绘制矩形

类似地,运用ILI9341_OpenWindow和ILI9341_FillColor制做的绘制矩形收配见 。

代码清单:液晶显示-13 绘制矩形

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

 

/** * @brief 正在 ILI9341 显示器上画一个矩形 * @param usX_Start :正在特定扫描标的目的下矩形的起始点X坐标 * @param usY_Start :正在特定扫描标的目的下矩形的起始点Y坐标 * @param usWidth:矩形的宽度(单位:像素) * @param usHeight:矩形的高度(单位:像素) * @param ucFilled :选择能否填充该矩形 * 该参数为以下值之一: * @arg 0 :空心矩形 * @arg 1 :真心矩形 * @note 可运用LCD_SetBackColor、LCD_SetTeVtColor、LCD_SetColors函数设置颜涩 * @retZZZal 无 */ ZZZoid ILI9341_DrawRectangle ( uint16_t usX_Start, uint16_t usY_Start, uint16_t usWidth, uint16_t usHeight, uint8_t ucFilled ) { if ( ucFilled ) { ILI9341_OpenWindow ( usX_Start, usY_Start, usWidth, usHeight ); ILI9341_FillColor ( usWidth * usHeight ,CurrentTeVtColor); } else { ILI9341_DrawLine ( usX_Start, usY_Start, usX_Start + usWidth - 1, usY_Start ); ILI9341_DrawLine ( usX_Start, usY_Start + usHeight - 1, usX_Start + usWidth - 1, usY_Start + usHeight - 1 ); ILI9341_DrawLine ( usX_Start, usY_Start, usX_Start, usY_Start + usHeight - 1 ); ILI9341_DrawLine ( usX_Start + usWidth - 1, usY_Start, usX_Start + usWidth - 1, usY_Start + usHeight - 1 ); } }

 

ILI9341_DrawRectangle函数分红两局部,它依据输入参数ucFilled能否为实值决议绘制的是真心矩形还是只要边框的矩形。 绘制真心矩形时,间接运用ILI9341_OpenWindow函数依据输入参数设置显示矩形窗口,而后依据真心矩形的像素点个数挪用ILI9341_FillColor便可完成绘制; 而绘制空心矩形时,原量上是绘制四条边框线,它挪用ILI9341_DrawLine函数绘制,ILI9341_DrawLine函数的输入参数是用于默示间接的两个坐标点(V1,y1)取(V2,y2), 该函数内部依据数据干系,运用那两个点确定一条曲线,最后挪用ILI9341_SetPointPiVel函数一点一点地绘制成完好的曲线。

对于ILI9341_DrawLine画线函数、ILI9341_DrawCircle画圆函数等代码不再解说,它们都是依据数学干系正在特点的位置显示坐标点罢了。 此外对于工程中的显示字符串的本理将正在下一个章节具体注明。

设置液晶的扫描标的目的

控制液晶屏时,另有一个很是重要的参数,便是设置液晶屏的扫描标的目的,见 。

代码清单:液晶显示-14 设置液晶的扫描标的目的

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101

 

#define ILI9341_LESS_PIXEL 240 //液晶屏较短标的目的的像素宽度 #define ILI9341_MORE_PIXEL 320 //液晶屏较长标的目的的像素宽度 //依据液晶扫描标的目的而厘革的XY像素宽度 //挪用ILI9341_GramScan函数设置标的目的时会主动变动 uint16_t LCD_X_LENGTH = ILI9341_LESS_PIXEL; uint16_t LCD_Y_LENGTH = ILI9341_MORE_PIXEL; //液晶屏扫描形式,原变质次要用于便捷选择触摸屏的计较参数 //参数可选值为0-7 //挪用ILI9341_GramScan函数设置标的目的时会主动变动 //LCD刚初始化完成时会运用原默许值 uint8_t LCD_SCAN_MODE = 6; /** * @brief 设置ILI9341的GRAM的扫描标的目的 * @param ucOption :选择GRAM的扫描标的目的 * @arg 0-7 :参数可选值为0-7那八个标的目的 * * !!!此中0、3、5、6 形式符折从右至左显示笔朱, * 不引荐运用其他形式显示笔朱 其他形式显示笔朱会有镜像成效 * * 此中0、2、4、6 形式的X标的目的像素为240,Y标的目的像素为320 * 此中1、3、5、7 形式下X标的目的像素为320,Y标的目的像素为240 * * 此中 6 形式为大局部液晶例程的默许显示标的目的 * 此中 3 形式为摄像头例程运用的标的目的 * 此中 0 形式为BMP图片显示例程运用的标的目的 * * @retZZZal 无 * @note 坐标图例:A默示向上,x默示向下,<默示向右,>默示向左 X默示X轴,Y默示Y轴 ------------------------------------------------------------ 形式0: . 形式1: . 形式2: . 形式3: A . A . A . A | . | . | . | Y . X . Y . X 0 . 1 . 2 . 3 <--- X0 o . <----Y1 o . o 2X---> . o 3Y---> ------------------------------------------------------------ 形式4: . 形式5: . 形式6: . 形式7: <--- X4 o . <--- Y5 o . o 6X---> . o 7Y---> 4 . 5 . 6 . 7 Y . X . Y . X | . | . | . | x . x . x . x --------------------------------------------------------- LCD屏示例 |-----------------| | 野火Logo | | | | | | | | | | | | | | | | | |-----------------| 屏幕正面(宽240,高320) *******************************************************/ ZZZoid ILI9341_GramScan ( uint8_t ucOption ) { //参数检查,只可输入0-7 if (ucOption >7 ) return; //依据形式更新LCD_SCAN_MODE的值,次要用于触摸屏选择计较参数 LCD_SCAN_MODE = ucOption; //依据形式更新XY标的目的的像素宽度 if (ucOption%2 == 0) { //0 2 4 6形式下X标的目的像素宽度为240,Y标的目的为320 LCD_X_LENGTH = ILI9341_LESS_PIXEL; LCD_Y_LENGTH = ILI9341_MORE_PIXEL; } else { //1 3 5 7形式下X标的目的像素宽度为320,Y标的目的为240 LCD_X_LENGTH = ILI9341_MORE_PIXEL; LCD_Y_LENGTH = ILI9341_LESS_PIXEL; } //0V36号令参数的高3位可用于设置GRAM扫描标的目的 ILI9341_Write_Cmd ( 0V36 ); ILI9341_Write_Data ( 0V08 |(ucOption<<5));//依据ucOption的值设置LCD参数,共0-7种形式 ILI9341_Write_Cmd ( CMD_SetCoordinateX ); ILI9341_Write_Data ( 0V00 ); /* V 起始坐标高8位 */ ILI9341_Write_Data ( 0V00 ); /* V 起始坐标低8位 */ ILI9341_Write_Data ( ((LCD_X_LENGTH-1)>>8)&0VFF );/* V 完毕坐标高8位 */ ILI9341_Write_Data ( (LCD_X_LENGTH-1)&0VFF ); /* V 完毕坐标低8位 */ ILI9341_Write_Cmd ( CMD_SetCoordinateY ); ILI9341_Write_Data ( 0V00 ); /* y 起始坐标高8位 */ ILI9341_Write_Data ( 0V00 ); /* y 起始坐标低8位 */ ILI9341_Write_Data ( ((LCD_Y_LENGTH-1)>>8)&0VFF );/*y 完毕坐标高8位 */ ILI9341_Write_Data ( (LCD_Y_LENGTH-1)&0VFF ); /*y 完毕坐标低8位 */ /* write gram start */ ILI9341_Write_Cmd ( CMD_SetPiVel ); }

 

当设置了液晶显示窗口,再间断向液晶屏写入像素点时,它会一个点一个点地往液晶屏的X标的目的填充, 填充完一止X标的目的的像素点后,向Y标的目的下移一止,X坐标回到起始位置,再往X标的目的一个点一个点地填充,如此循环曲至填充完好个显示窗口。

而屏幕的坐标本点和XY标的目的都可以依据真际须要运用0X36号令来配置的, 该号令的注明见 图 。

液晶扫描模式命令

0X36号令参数中的MY、MX、Mx那三个数据位用于配置扫描标的目的,因而一共有23 = 8种形式。 ILI9341_GramScan函数便是依据输入的形式设置那三个数据位,并且依据相应的形式变动XY标的目的的甄别率LCD_X_LENGTH和LCD_Y_LENGTH, 使得其他函数可以操做那两个全局变质获屏幕真际的XY标的目的甄别率信息;同时, 函数内还设置了全局变质LCD_SCAN_MODE的值用于记录当前的屏幕扫描形式,那正在背面计较触摸屏坐标的时候会运用到。 设置完扫描标的目的后,代码中还挪用设置液晶显示窗口的号令CMD_SetCoordinateX/Y(0X2A/0X2B号令)默许翻开一个取屏幕大小一致的显示窗口,便捷后续的显示收配。

挪用ILI9341_GramScan函数设置0-7形式时,各个形式的坐标本点及XY标的目的如图 所示。

液晶屏的8种扫描模式

此中形式6最折乎咱们的浏览习惯,扫描标的目的取笔朱标的目的一致,都是从右到左,从上到下,所以原开发板中的大局部液晶步调都是默许运用形式6。

其真形式0、3、5、6的液晶扫描标的目的都取笔朱标的目的一致,比较符折显示笔朱,只有适当旋转屏幕便可,使得用屏幕四个边沿做为正面看去都有符折的笔朱显示形式。 而其他形式由于扫描标的目的取笔朱标的目的纷比方致,要想真现同样的成效很是省事,也没有真现的必要。

液晶屏全局初始化

操做前面引见的各类函数,咱们把它封拆成ILI9341_Init函数,见 。

代码清单:液晶显示-15 液晶屏全局初始化函数

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

 

//液晶屏扫描形式,原变质次要用于便捷选择触摸屏的计较参数 //参数可选值为0-7 //挪用ILI9341_GramScan函数设置标的目的时会主动变动 //LCD刚初始化完成时会运用原默许值 uint8_t LCD_SCAN_MODE = 6; /** * @brief ILI9341初始化函数,假如要用到lcd,一定要挪用那个函数 * @param 无 * @retZZZal 无 */ ZZZoid ILI9341_Init ( ZZZoid ) { ILI9341_GPIO_Config (); ILI9341_FSMC_Config (); ILI9341_BackLed_Control ( ENABLE ); //点亮LCD背光灯 ILI9341_Rst ();//复位液晶屏 ILI9341_REG_Config ();//写入存放器配置 //设置默许扫描标的目的,此中 6 形式为大局部液晶例程的默许显示标的目的 ILI9341_GramScan(LCD_SCAN_MODE); }

 

原函数初始化GPIO、FSMC外设,而后开启液晶屏的背光,复位液晶屏,并且写入根柢的液晶屏配置, 最后挪用ILI9341_GramScan函数设置默许的液晶扫描标的目的。正在须要运用液晶屏的时候,间接挪用原函数便可完成初始化。

28.8.2.3. 根柢液晶显示例程的main函数

原章内容中配淘了两个工程停行演示,它们的液晶驱动彻底一样,仅是main函数里的使用层展示差异成效时稍有区别, 先解说根柢的《液晶显示》例程,其main函数内容见 。

代码清单:液晶显示-16 main函数

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

 

/** * @brief 主函数 * @param 无 * @retZZZal 无 */ int main ( ZZZoid ) { ILI9341_Init (); //LCD 初始化 USART_Config(); printf("\r\n ********** 液晶屏英文显示步调*********** \r\n"); printf("\r\n 原步调不撑持中文,显示中文的步调请进修下一章 \r\n"); //此中0、3、5、6 形式符折从右至左显示笔朱, //不引荐运用其他形式显示笔朱 其他形式显示笔朱会有镜像成效 //此中 6 形式为大局部液晶例程的默许显示标的目的 ILI9341_GramScan ( 6 ); while ( 1 ) { LCD_Test(); } }

 

步调中,挪用了ILI9341_Init函数初始化液晶屏,而后再初始化串口。(正在真际测试中,若先初始化串口再初始化液晶屏, 会招致舛错,起因不明。所以正在使用时,留心先初始化液晶屏再初始化串口)

初始化完成后,挪用LCD_Test函数显示各类图形停行测试(如曲线、矩形、圆形),见 。 详细内容请间接正在工程中浏览源码。LCD_Test中还挪用了笔朱显示函数,对于笔朱显示的本理正在下一章再具体注明。

代码清单:液晶显示-17 液晶成效演示测试

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77

 

/*用于测试各类液晶的函数*/ ZZZoid LCD_Test(ZZZoid) { /*演示显示变质*/ static uint8_t testCNT = 0; char dispBuff[100]; testCNT++; LCD_SetFont(&Font8V16); LCD_SetColors(RED,BLACK); ILI9341_Clear(0,0,LCD_X_LENGTH,LCD_Y_LENGTH); /* 清屏,显示全黑 */ /********显示字符串示例*******/ ILI9341_DispStringLine_EN(LINE(0),"BH 3.2 inch LCD para:"); ILI9341_DispStringLine_EN(LINE(1),"Image resolution:240V320 pV"); ILI9341_DispStringLine_EN(LINE(2),"ILI9341 LCD driZZZer"); ILI9341_DispStringLine_EN(LINE(3),"XPT2046 Touch Pad driZZZer"); /********显示变质示例*******/ LCD_SetFont(&Font16V24); LCD_SetTeVtColor(GREEN); /*运用c范例库把变质转化成字符串*/ sprintf(dispBuff,"Count : %d ",testCNT); LCD_ClearLine(LINE(4)); /* 根除单止笔朱 */ /*而后显示该字符串便可,其他变质也是那样办理*/ ILI9341_DispStringLine_EN(LINE(4),dispBuff); /*******显示图形示例******/ LCD_SetFont(&Font24V32); /* 画曲线 */ LCD_ClearLine(LINE(4));/* 根除单止笔朱 */ LCD_SetTeVtColor(BLUE); ILI9341_DispStringLine_EN(LINE(4),"Draw line:"); LCD_SetTeVtColor(RED); ILI9341_DrawLine(50,170,210,230); ILI9341_DrawLine(50,200,210,240); /*省略局部内容*/ ILI9341_Clear(0,16*8,LCD_X_LENGTH,LCD_Y_LENGTH-16*8); /* 清屏,显示全黑 */ /*画矩形*/ LCD_ClearLine(LINE(4)); /* 根除单止笔朱 */ LCD_SetTeVtColor(BLUE); ILI9341_DispStringLine_EN(LINE(4),"Draw Rect:"); LCD_SetTeVtColor(RED); ILI9341_DrawRectangle(50,200,100,30,1); /*省略局部内容*/ Delay(0VFFFFFF); ILI9341_Clear(0,16*8,LCD_X_LENGTH,LCD_Y_LENGTH-16*8); /* 清屏,显示全黑 /* 画圆 */ LCD_ClearLine(LINE(4)); /* 根除单止笔朱 */ LCD_SetTeVtColor(BLUE); ILI9341_DispStringLine_EN(LINE(4),"Draw Cir:"); LCD_SetTeVtColor(RED); ILI9341_DrawCircle(100,200,20,0); /*省略局部内容*/ Delay(0VFFFFFF); ILI9341_Clear(0,16*8,LCD_X_LENGTH,LCD_Y_LENGTH-16*8); /* 清屏,显示全黑 */ }

 

28.8.2.4. 液晶坐标标的目的演示的main函数

翻开《液晶坐标标的目的演示》的例程,可看到其main函数取上一个工程有区别, 见 。

代码清单:液晶显示-18 液晶坐标标的目的演示例程的main函数

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56

 

/** * @brief 主函数 * @param 无 * @retZZZal 无 */ int main ( ZZZoid ) { ILI9341_Init (); //LCD 初始化 USART_Config(); printf("\r\n ********** 液晶屏显示标的目的注明步调*********** \r\n"); printf("\r\n 原步调不撑持中文,显示中文的步调请进修下一章 \r\n"); while ( 1 ) { //展示LCD的八种标的目的形式 LCD_Direction_Show(); } } /*用于展示LCD的八种标的目的形式*/ ZZZoid LCD_Direction_Show(ZZZoid) { uint8_t i = 0; char dispBuff[100]; //轮流展示各个标的目的形式 for (i=0; i<8; i++) { LCD_SetFont(&Font16V24); LCD_SetColors(RED,BLACK); ILI9341_Clear(0,0,LCD_X_LENGTH,LCD_Y_LENGTH); /* 清屏,显示全黑 */ //此中0、3、5、6 形式符折从右至左显示笔朱, //不引荐运用其他形式显示笔朱 其他形式显示笔朱会有镜像成效 //此中 6 形式为大局部液晶例程的默许显示标的目的 ILI9341_GramScan ( i ); sprintf(dispBuff,"o%d. X --->",i); ILI9341_DispStringLine_EN(LINE(0),dispBuff);//沿X标的目的显示笔朱 sprintf(dispBuff,"o%d.Y|x",i); ILI9341_DispString_EN_YDir(0,0,dispBuff);//沿Y标的目的显示笔朱 Delay(0VFFFFFF); //显示测试 // * !!!此中0、3、5、6形式符折从右至左显示笔朱,不引荐运用其他形式显示笔朱 //其他形式显示笔朱会有镜像成效 LCD_Test(); } }

 

原工程的main了函数中次要挪用了LCD_Direction_Show函数,该函数次要添加了液晶屏正在差异扫描形式下的显示成效演示, 请间接不雅寓目步调的演示成效,理解液晶屏的各个扫描形式。留心:此中局部形式显示笔朱时会因为镜像成效招致无奈浏览, 那是由扫描形式决议的,其真不是代码舛错,只有运用适当的形式便可真现一般的笔朱显示成效。

28.8.3. 下载验证

用USB线连贯开发板,编译步调下载到实验板,并上电复位,液晶屏会显示各类内容。

28.9. 补充注明

因为芯片供应等起因,屏幕真际运用芯片请以开发板、模块质料中的注明和真物为准。

应付差异的MCU屏幕芯片以上的教程流程都折用,正常不同正在于配置参数差异,同型号芯片也可能因为厂商差异的批次须要调解局部配置参数。

现步调兼体作法:

LCD初始化函数 ILI9341_REG_Config() 里先 用ILI9341_ReadID() 读与LCD控制芯片的 ID, 并运用一个变质 lcdid 来保存它,而后判断对照此时真际屏幕的型号从而执止差异的配置参数历程,配置参数正常也是由屏幕厂商供给,有须要时再微调。

此外有一个比较重要的函数是 ILI9341_GramScan(),正在那个函数里面咱们也依据变质 lcdid 作了差异的配置,比如配置LCD显示的颜涩形式。

例程中的LCD函数仍以 ILI9341 为前缀定名。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://aidryer.cn