原贴链接:http://www.openedv.com/forum.php?mod=viewthread&tid=27
3.10 TFTLCD显示实验上一节我们介绍了OLED模块及其显示,但是该模块只能显示单色/双色,不能显示彩色,这一节我们将介绍ALIENTEK TFT LCD模块,该模块采用TFTLCD面板,可以显示16位色的真彩图片。本节将利用TFTLCD来显示字符和数字,并显示各种颜色。本节分为如下几个部分: 3.10.1 TFTLCD简介 3.10.2 硬件设计 3.10.3 软件设计 3.10.4 下载与测试
3.10.1 TFTLCD简介 TFT-LCD即薄膜晶体管液晶显示器。其英文全称为:Thin Film Transistor-Liquid Crystal Display。TFT-LCD与无源TN-LCD、STN-LCD的简单矩阵不同,它在液晶显示屏的每一个象素上都设置有一个薄膜晶体管(TFT),可有效地克服非选通时的串扰,使显示液晶屏的静态特性与扫描线数无关,因此大大提高了图像质量。TFT-LCD也被叫做真彩液晶显示器。 上一节介绍了OLED模块,这一节,我们给大家介绍ALIENTEK TFTLCD模块,该模块有如下特点: 1,2.4’/2.8’两种大小的屏幕可选。 2,320×240的分辨率。 3,16位真彩显示。 4,自带触摸屏,可以用来作为控制输入。 5,通用的接口,除了ALIENTEK MiniSTM32开发板,该液晶模块还可以使用在优异特、STMSKY、红牛等开发板上。 本节,我们以2.8寸的ALIENTEK TFTLCD模块为例介绍,该模块采用的是显尚光电的DST2001PH TFTLCD,DST2001PH的控制器为ILI9320,采用26万色的TFTLCD屏,分辨率为320×240,采用16位的80并口。 该模块的外观图如下:
图3.10.1.1 ALIENTEK 2.8寸TFTLCD外观图 模块原理图如下:
图3.10.1.2 ALIENTEK 2.8寸TFTLCD模块原理图 TFTLCD模块采用2*17的2.54公排针与外部连接,接口图如下:
图3.10.1.3 ALIENTEK 2.8寸TFTLCD模块接口图 该接口同目前主流的几款STM32开发板的接口完全兼容,所以模块除了用在ALIENTEK MiniSTM32开发板上,也可以用在其他开发板上,当然你也可以使用其他接口一样的LCD模块放到我们的ALIENTEK MiniSTM32开发板上使用。ALIENTEK TFTLCD模块采用80并口口方与外部链接,采用16位数据线(低了速度太慢,用彩色就没什么效果了)。该模块的80并口有如下一些信号线: CS:TFTLCD片选信号。 WR:向TFTLCD写入数据。 RD:从TFTLCD读取数据。 D[15:0]:16位双向数据线。 RST:硬复位TFTLCD。 RS:命令/数据标志(0,读写命令;1,读写数据)。 80并口在上一节我们已经有详细的介绍了,这里我们就不在介绍,需要说明的是,TFTLCD模块的RST信号线和OLED模块一样,也是直接接到STM32的复位脚上,并不由软件控制,这样可以省下来一个IO口。另外我们还需要一个背光控制线来控制TFTLCD的背光。所以,我们总共需要的IO口数目为21个。 模块的控制器为ILI9320,该控制器自带显存,其显存总大小为172820(240*320*18/8),即18位模式(26万色)下的显存量。模块的16位数据线与显寸的对应关系为565方式,如下图所示:
图3.10.1.4 16位数据与显存对应关系图 最低5位代表蓝色,中间6位为绿色,最高5位为红色。数值越大,表示该颜色越深。 接下来,我们介绍一下ILI9320的几个重要命令,因为ILI9320的命令很多,我们这里不可能一一介绍,有兴趣的大家可以找到ILI9320的datasheet看看。里面对这些命令有详细的介绍。这里我们要介绍的命令列表如下:
表3.10.1.1 ILI9320常用命令表 R0,这个命令,有两个功能,如果对它写,则最低位为OSC,用于开启或关闭振荡器。而如果对它读操作,则返回的是控制器的型号。这个命令最大的功能就是通过读它可以得到控制器的型号,而我们代码在知道了控制器的型号之后,可以针对不同型号的控制器,进行不同的初始化。因为93xx系列的初始化,其实都比较类似,我们完全可以用一个代码兼容好几个控制器。 R3,入口模式命令。我们重点关注的是I/D0、I/D1、AM这3个位,因为这3个位控制了屏幕的显示方向。 AM:控制GRAM更新方向。当AM=0的时候,地址以行方向更新。当AM=1的时候,地址以列方向更新。 I/D[1:0]:当更新了一个数据之后,根据这两个位的设置来控制地址计数器自动增加/减少1, 其关系如下图:
图3.10.1.5 GRAM显示方向设置图 通过这几个位的设置,我们就可以控制屏幕的显示方向了。 R7,显示控制命令。该命令CL位用来控制是8位彩色,还是26万色。为0时26万色,为1时八位色。D1、D0、BASEE这三个位用来控制显示开关与否的。当全部设置为1的时候开启显示,全0是关闭。我们一般通过该命令的设置来开启或关闭显示器,以降低功耗。 R32,R33,设置GRAM的行地址和列地址。R32用于设置列地址(X坐标,0~239),R33用于设置行地址(Y坐标,0~319)。当我们要在某个指定点写入一个颜色的时候,先通过这两个命令设置到改点,然后写入颜色值就可以了。 R34,写数据到GRAM命令,当写入了这个命令之后,地址计数器才会自动的增加和减少。该命令是我们要介绍的这一组命令里面唯一的单个操作的命令,只需要写入该值就可以了,其他的都是要先写入命令编号,然后写入操作数。 R80~R83,行列GRAM地址位置设置。这几个命令用于设定你显示区域的大小,我们整个屏的大小为240*320,但是有时候我们只需要在其中的一部分区域写入数据,如果用先写坐标,后写数据这样的方式来实现,则速度大打折扣。此时我们就可以通过这几个命令,在其中开辟一个区域,然后不停的丢数据,地址计数器就会根据R3的设置自动增加/减少,这样就不需要频繁的写地址了,大大提高了刷新的速度。 命令部分,我们就为大家介绍到这里,我们接下来看看要如何才能驱动ALIENTEK TFTLCD模块,这里TFTLCD模块的初始化和我们前面介绍的OLED模块的初始化框图是一样的,只是初始化代码部分不同。接下来我们也是将该模块用来来显示字符和数字。通过以上介绍,我们可以得出TFTLCD显示需要的相关设置步骤如下: 1)设置STM32与TFTLCD模块相连接的IO。 这一步,先将我们与TFTLCD模块相连的IO口设置为输出,具体使用哪些IO口,这里需要根据连接电路以及TFTLCD模块的设置来确定。 2)初始化TFTLCD模块。 其实这里就是上和上面OLED模块的初始化过程差不多。通过向TFTLCD写入一系列的设置,来启动TFTLCD的显示。为后续显示字符和数字做准备。 3)通过函数将字符和数字显示到TFTLCD模块上。 这里就是通过我们设计的程序,将要显示的字符送到TFTLCD模块就可以了,这些函数将在软件设计部分向大家介绍。 通过以上三步,我们就可以使用ALIENTEK TFTLCD模块来显示字符和数字了, 并且可以显示各种颜色的背景。
3.10.2 硬件设计 TFTLCD模块的电路在上一部分已有详细说明了,这里我们介绍TFTLCD模块与ALIETEK MiniSTM32开发板的连接,MiniSTM32开发板底板的LCD接口和ALIENTEK TFTLCD模块直接可以对插,连接如下图:
图3.10.2.1 TFTLCD与开发板连接示意图 图中绿色线圈出来的部分就是连接TFTLCD模块的接口,这里在硬件上,TFTLCD模块与MiniSTM32开发板的IO口对应关系如下: LCD_LED对应PC10; LCD_CS对应PC9; LCD _RS对应PC8; LCD _WR对应PC7; LCD _RD对应PC6; LCD _D[17:1]对应PB[15:0]; 这些线的连接,MiniSTM32的内部已经连接好了,我们只需要将TFTLCD模块插上去就好了。实物连接如下图所示:
图3.10.2.2 TFTLCD与开发板连接实物图
3.10.3 软件设计
软件设计我们依旧在之前的工程上面增加,首先在HARDWARE文件夹下新建一个LCD的文件夹。然后打开USER文件夹下的工程,新建一个ILI93xx.c的文件和lcd.h的头文件,保存在LCD文件夹下,并将LCD文件夹加入头文件包含路径。 在ILI93xx.c里面要输入的代码比较多,我们这里就不完全列出来了,只针对几个重要的函数进行讲解。完整版的代码见光盘->ALIENTEK MiniSTM32开发板例程->实验10的ILI93xx.c文件。 第一个是LCD_WR_DATA函数,该函数通过80并口向LCD模块写入一个16位的数据,使用频率是最高的,这里我们采用了宏定义的方式,以提高速度。其代码如下: #define LCD_WR_DATA(data){\ LCD_RS=1;\ LCD_CS=0;\ DATAOUT(data);\ LCD_WR=0;\ LCD_WR=1;\ LCD_CS=1;\ } 第二个是LCD_WR_REG函数,该函数也是通过80并口向LCD模块写入8位的寄存器命令,因为该函数使用频率不是很高,我们不采用宏定义来做(宏定义占用FLASH较多),通过LCD_RS来标记是写入命令(LCD_RS=0)还是数据(LCD_RS=1)。该函数代码如下: void LCD_WR_REG(u8 data) { LCD_RS=0;//写地址 LCD_CS=0; DATAOUT(data); LCD_WR=0; LCD_WR=1; LCD_CS=1; } 既然有写命令/数据的函数,那就有读命令/数据的函数。接下来介绍LCD_ReadReg函数,该函数用来读取某个寄存器的值。在读某个寄存器的值之前,先要写入该寄存器的编号(命令号),然后设置D[15:0]为输入,在读取该改寄存器的值,读完数据之后,我们再设置IO口为输出。其代码如下: u16 LCD_ReadReg(u8 LCD_Reg) { u16 t; LCD_WR_REG(LCD_Reg); //写入要读的寄存器号 GPIOB->CRL=0X88888888; //PB0-7 上拉输入 GPIOB->CRH=0X88888888; //PB8-15 上拉输入 GPIOB->ODR=0XFFFF; //全部输出高 LCD_RS=1; LCD_CS=0; //读取数据(读寄存器时,并不需要读2次) LCD_RD=0; LCD_RD=1; t=DATAIN; LCD_CS=1; GPIOB->CRL=0X33333333; //PB0-7 上拉输出 GPIOB->CRH=0X33333333; //PB8-15 上拉输出 GPIOB->ODR=0XFFFF; //全部输出高 return t; }
|