如何驱动3.2寸TFT ILI9341液晶屏
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何驱动3.2寸TFT ILI9341液晶屏相关的知识,希望对你有一定的参考价值。
参考技术A 这个屏的驱动方式,出厂的,通常都已固化了的。少部分的厂家才会开放更改驱动方式,通常都是通过命令进行更改,请阅读商家提供给 你的资料。SPI驱动,很简单。曾经我也自己写过驱动代码,但是现在更换了电脑,暂时没有代码在手边。如果需要,请到极客工坊上边去搜索。我应该发布在那边了。液晶显示原理与ILI9341的使用
转载自金沙滩工作室《https://mp.weixin.qq.com/s/JME3VArPETgPjD0n_cHKNQ》
液晶显示原理
TFT-LCD(Thin Film Transistor Liquid Crystal Display)即薄膜晶体管液晶显示器,是微电子技术与液晶显示器技术巧妙结合的的一种技术。
CRT显示器的工作原理是通电后灯丝发热,阴极被激发后发射出电子流,电子流受到高电压的金属层的加速,经过透镜聚焦形成极细的电子束打在荧光屏上,使荧光粉发光显示图像。LCD显示器需要来自背后的光源,当光束通过这层液晶时,液晶会呈不规则扭转形状(形状由TFT上的信号与电压改变实现),所以液晶更像是一个个闸门,选择光线穿透与否,这样就可以在屏幕上看到深浅不一,错落有致的图像。目前主流的LCD显示器都是TFT-LCD,是由原有液晶技术发展而来。TFT液晶为每个像素都设有一个半导体开关,以此做到完全的单独控制一个像素点,液晶材料被夹在TFT阵列和彩色滤光片之间,通过改变刺激液晶的电压值就可以控制最后出现的光线强度和色彩,如图所示。
ILI9341硬件接口和像素格式
ILI9341驱动芯片主要由接口电路、显存(GRAM)、LCD驱动电路、背光控制、电源等部分组成,主要结构如图所示。
ILI9341控制器的通信接口支持8/9/16/18-bit 8080并行接口、3/4线SPI串行接口、6/16/18-bit RGB通信接口,这些接口通过TFT-LCD的38~40引脚IM0、IM1、IM2设置,具体如表7-2所示。不同的接口主要是为了适应不同的应用场合。由于STM32的I/O口资源丰富,为了提高数据的读写效率,采用16位的8080并行接口,可以比8位的8080并行接口的传输速率高出一倍(数据线多出一倍),由于是并行接口,比SPI串行接口的传输速率更快,并且通讯时序简单,因此这里将TFT-LCD的IM2~IM0引脚接地。
8080并行总线协议
8080并行总线协议是由Intel公司提出的一种数据传输协议,接口包括:复位(RESET)、片选(CS)、双向数据线(DB0~DB15)、数据/指令选择端(DC)、读使能(RD)、写使能(WR)。
8080并行总线时序分为两部分:“写操作”时序和“读操作”时序,同时“写操作”时序又分为“写命令”操作和“写数据”操作。通过操作DC端口,当DC为低表示“命令”传输,当DC为高表示“数据”传输。
(1)写操作:
写指令时,单片机发送过程为,CS = H→L,DC = H→ L,WR = H→L,RD = H,D[15:0] = Data,此时信号发生变化;当D[15:0]数据稳定后,WR = L→H,ILI9341在WR的上升沿读取D[15:0]总线上的信号。
写数据和写指令的时序唯一差别是:写指令时,DC为低电平;写数据时,DC为高电平。写操作的时序图如图7-5所示。
当命令或数据传输完成,且不再进行“写操作”时,需要将CS置高,失能片选。
(2)读操作:
读数据之前,首先要进行一次写命令操作,通知LCD主机所要读取的数据类别。写命令操作完成后,首先DC= L→H,而后RD = H→L,通知ILI9341输出数据,最终RD = L→H,开始读取D[15:0]上的数据。当读操作完毕后,需要将CS置高,失能片选。读操作的时序图如图7-6所示。
(3)时序特征
编写时序程序时必须严格按照数据手册中要求的时间和顺序,否则容易造成数据通信错误。8080时序的写操作周期为twc=66ns,其中twrl和twrh分别表示主机写周期和ILI9341读周期,即当WR置低时,主机开始写,此时WR至少保持tdst=10ns的低电平,等待总线数据锁存;当数据线输出数据后,如果WR低电平周期低于10ns,有可能在WR置高时,总线上的数据还在变化。当WR置高时,至少保持tdht=10ns的高电平,等待ILI9341读取数据完毕。在执行写操作时,主机可以先发送数据,然后WR = L→H,当WR置高时,数据一定准备好了。因此编写时序程序时,注意加适当延时保证时序的准确性,由于STM32执行一条语句超过10ns,在此并不需要使用延时。
读操作与写操作类似,当RD置低时,ILI9341开始输出数据,此时必须等待tratfm ns,等待ILI9341将数据准备好,其中tratfm最大为340ns,没有规定最小时间。我们取 tratfm大于等于340ns,因为超过340ns,ILI9341一定将数据准备好了,但是少于340ns就不能保证数据完全正确。RD置高时,单片机开始读取数据,此时需要保持RD高电平时间不少于trod=20ns,保证ILI9341将数据输出完毕,8080总线时序参数如图7-7所示。
ILI9341 GRAM指令和像素格式
GRAM(Graphics RAM)——显存,也称作帧存储器,是ILI9341用来存储显示数据的图像RAM。GRAM中一个像素点的颜色数据用18bit表示,GRAM的大小为24032018/8=172800字节,所有像素数据都存储在GRAM中。当TFT-LCD开显示时,LCD源极驱动会根据GRAM中存储的数据对液晶像素进行刷新,从而实现图像显示。如果改变GRAM中单个像素点的数据,刷新显示时,TFT-LCD对应的像素状态也会改变。如何才能准确的向每个像素对应的数据位写入显示数据呢?ILI9341控制器内部设计了一个“控制寄存器”,用户只需要按照要求发送相应的控制指令,“控制寄存器”收到控制指令后,通过“地址计数器”在对应的像素位置写入像素数据,最终通过LCD源极驱动LCD刷新显示,ILI9341控制器内部结构如图7-8所示。
ILI9341控制器共有76条控制指令,每条指令的控制功能在手册中都有详细描述,本书只针对常用指令做重点说明。
1、读取驱动器ID
用于读取TFT-LCD的驱动器的的ID,板载液晶的驱动器是ILI9341,ID固定为0x9341。在读取的过程中,首先通过写命令函数发送指令0xD3,然后连续读取4次数据。其中第1次是无效数据,第二次是版本号,也是无效数据,第三次和第四次的高8位也是无效数据,只有第三次和第四次的低8位才是有效的ID数据,读取ID成功,表明单片机和驱动器通信正常,读ID指令如图7-9所示。
2、设置显示窗口
当用户将一部分要显示的内容填充到液晶显示屏的某一个区域,这个区域的列范围用0x2A这条指令设置,行范围用0x2B这条指令设置。首先通过写命令函数发送指令0x2A,紧跟着列起始地址的高字节、列起始地址的低字节、列结束地址的高字节、列结束地址的低字节;然后通过写命令函数发送指令0x2B,紧跟着行起始地址的高字节、行起始地址的低字节、行结束地址的高字节、行结束地址的低字节。注意:结束地址只能大于等于起始地址,不能小于起始地址。
通过限定这4个角的坐标,就可以从液晶中选取其中一个区域作为显示窗口。指令和地址都只有低8位数据有效,发送过程如图7-10和图7-11所示。
设置光标代码如下:
3、写存储器指令
设置好显示窗口后,在写入数据之前,需要先写入0x2C指令。无论当前行寄存器和列寄存器的地址是多少,写入0x2C后,行寄存器和列寄存器会自动复位,复位值就是通过0x2A和0x2B写入的列起始地址和行起始地址,此时如果发送数据,数据会写入帧存储器对应地址中,数据写入具体流程如图7-12所示。
4、帧存储器扫描方向控制指令
设置显示窗口后,发送0x2C指令开始向内存中写数据,数据是从设置窗口的起始地址开始写入,先写行,行地址自增直至该行的终止地址,然后列地址加1,数据再从下一行的起始地址开始写入,如此循环直至将整个显示窗口的数据写入到帧存储器中。帧存储器读/写扫描方向如图7-13所示,图中B表示起始位置,E表示终止位置。
数据按照上面介绍的顺序写入,但是液晶屏刷新显示时,并不一定按照写入的顺序刷新数据,而是可以通过“存储器访问控制”指令0x36设置帧存储器的扫描方向(即行列方向)。设置帧存储器扫描方向时,先发送指令0x36,紧跟着发送设置参数,参数由18位组成,只有2~7位有效。其中D7:MY-设置行地址方向;D6:MX-设置列地址方向;D5:MV-设置行列地址交换;D4:ML-设置垂直刷新方向;D3:BGR-设置刷新像素格式为BGR或RGB;D2:MH-设置水平刷新方向,存储器访问控制指令如图7-14所示。
其中MY、MX、MV这三位用来设置扫描方向,也是重点介绍的地方,MX和MY分别设置行列扫描方向,MV设置行列交换,它们可以组合成23=8种扫描模式,如图7-15所示。
注意:无论MY、MX、MV设置的存储器扫描方向如何,数据总是以相同的顺序写入帧存储器。设置扫描方向后,还需要通过0x2A、0x2B指令重新设置显示窗口大小。
Kingst-32F1开发板默认扫描方向为“模式0”,其中模式0和3为竖屏显示,模式5和6为横屏显示,这四种模式的扫描方向和稍后所讲的文字取模方向相同,旋转液晶屏即可达到阅读效果,其他模式直接显示时呈现乱码,需要根据扫描方向重新取模。
ML和MH主要设置帧存储器到LCD显示面板的数据刷新方向,就像过年贴春联,可以选择从上向下贴,或者从下向上贴,无论哪种方式,最后的显示效果是不变的,默认ML和MH都为0。
以下是设置液晶扫描方向代码:
/* 设置LCD扫描方向,dir-扫描模式0~7*/
5、像素格式
TFT-LCD的每个像素点由红®、绿(G)、蓝(B)三原色组成,帧存储器为每个像素分配了18bit的存储空间,三原色各用6个数据位表示,也就是常说的RGB666格式,该模式色彩度最大,它们按不同比例的混合可以组成218种颜色,俗称262K色。同时ILI9341还支持16位、9位数据格式。
Kingst-32F1开发板采用16位的8080并行接口与ILI9341通信,GRAM选择16位数据格式,16位数据格式下按照R:G:B =5:6:5格式存储,俗称RGB565格式,此时8080总线单次传输的就是一个像素的数据。由于GRAM为每个像素预留的存储空间是18bit,为了保证写入的16bit像素数据能够正常匹配GRAM中18bit像素存储空间,控制器会自动将RGB565格式转换成RGB666格式,转换后数据存储形式如图7-16所示,空白位置表示没有数据。由于缺少了两位数据,此时TFT-LCD最大支持216种色彩度,也就是65K色。
像素数据在帧存储器按照图7-18的格式存储,即R位于高位,B位于低位。但是像素数据刷新到LCD显示屏上时,可以通过“存储器访问控制(0x36)”指令中的 BGR位选择像素数据写入到显示屏的方向,当BGR位为 0时,数据按照RGB(即R在高位,B在低位)的顺序写入;当BGR位为1时,数据沿BGR(即B在高位,R在低位)的顺序写入到液晶面板中。默认BGR位为1,该模式下写入的颜色与显示效果相同,像素刷新示意图如图7-17所示。
6、读存储器指令
读存储器指令为0x2E,与上面介绍的写存储器指令0x2C类似,首先发送0x2A和0x2B设置行列起始和终止地址,然后发送0x2E,行列地址自动复位。通过读数据函数可以读取帧存储器存储的像素数据,第一次读取的数据无效,之后每一次读取16bit数据,由于帧存储器中每个像素占18位,因此一个像素点的数据需要分两次读取,第一次读取RG的值,第二次读取B值。读数据时行列地址会自增,直至读完整个显示窗口,读存储器指令如图7-18所示。
ILI9341 TFT-LCD 显示操作
画点
画点就是向单个像素点填充颜色,画点主要分为三部分:
第一步、通过窗口设置函数设置像素点的坐标,由于设置的是一个像素点,所以窗口设置函数的起始和终止坐标相同;
第二步、发送写存储器指令0x2C;
第三步、写入像素数据。为了提高速率,通过写指令和数据函数一并将指令和数据写入。画点函数如下:
读点
读点就是读取帧存储器中相应像素点的数据。读点也分为三部分:
第一步、通过窗口设置函数确定像素点的坐标;
第二步、发送读存储器指令0x2E;
第三步、读取像素数据。
由于帧存储中像素数据为18bit,写入帧存储器中的像素数据是RGB565格式,帧存储器中存储的数据是RGB666格式。16位并口模式下读取一个像素点数据需要读两次,数据按照高位在前,低位在后顺序输出。第一次读取的数据无效,之后读取的才是真正的像素数据;第二次读取的是RG值,其中高8位为R值,有效位为[15:11]位,低8位为G值,有效位为[7:2]位,第三次读取的B值位于高8位,有效位为[15:11]位,像素数据读取完毕后还需要转换为RGB565格式。需要注意的是读数据时需要设置数据总线为输入模式,读取完毕后再重新设置为输出模式。读点函数如下:
画线,画矩形,画圆
(1)画线分为画直线和画斜线,同时直线又分为水平线和竖直线。画直线是通过“显示窗口设置函数”设定显示区域为一行或一列,然后发送0x2C写存储器指令,最后通过写数据函数填充颜色。画斜线时相对比较麻烦,需要从起始位置开始,计算斜线上每个像素点的坐标,然后再调用画点函数填充每个像素点的颜色。画线函数如下所示;其中xStart、yStart、xEnd、yEnd分别表示起始和终止坐标,Color表示填充的颜色。
void LcdDrawLine(u16 xStart, u16 yStart, u16 xEnd, u16 yEnd, u16 Color)
(2)画矩形分为填充和非填充两种情况,非填充矩形是由四条线组成,通过矩形的对角坐标,计算每条线的起始坐标和终止坐标,再调用画线函数画出矩形的四条边。填充矩形可以直接使用“显示窗口设置函数”,设置一个矩形窗口,然后发送0x2C指令,最后填充颜色。
画矩形函数如下所示,其中xStart、yStart、xEnd、yEnd表示矩形的对角坐标,Color为填充的颜色,Filled 为0表示非填充,为1表示填充。
void LcdDrawRectangle(u16 xStart,u16 yStart,u16 xEnd,u16 yEnd,u16 Color,u8 Filled)
(3)画圆与画斜线类似,先确定圆心坐标以及半径后,通过公式计算出圆周的位置,最后调用画点函数画出整个圆。画圆函数如下所示,其中xDot、yDot表示圆心坐标,R表示半径,Color表示圆的颜色,Filled为0表示非填充,为1表示填充。
void LcdDrawCircle(u16 xDot, u16 yDot, u8 R, u16 Color, u8 Filled)
填充和清屏
填充是对某一区域填充特定颜色。首先通过“显示窗口设置函数”设置被填充区域范围,然后发送0x2C写存储器指令,最后通过写数据函数写入像素数据。该函数如下所示:其中xStart、yStart、xEnd、yEnd表示填充区域起始和终止坐标,Color表示填充的颜色。
void LcdFill(u16 xStart, u16 yStart, u16 xEnd, u16 yEnd, u16 Color)
清屏函数实际是一个填充函数,只不过清屏函数的显示窗口大小设置为全屏。该函数如下所示,Color表示全屏填充的颜色。
void LcdClear(u16 Color)
以上是关于如何驱动3.2寸TFT ILI9341液晶屏的主要内容,如果未能解决你的问题,请参考以下文章