weiqi7777

STM32驱动TFT屏

0
阅读(4946)

现在开始找工作了,要将以前做过学习的东西要回顾一下,还记着以前用STM32加一个TFT屏,实现了2048游戏。通过按键控制游戏运行,界面通过TFT显示。

要通过TFT显示,就要先实现TFT驱动。TFT本身的驱动是比较麻烦的,要控制各种信号,但是有了TFT驱动芯片,那驱动TFT就相当简单了,只要你会驱动1602,你就会驱动TFT屏了。

我使用的STM32开发板用的是ILI9320的驱动芯片。接口原理图如下:

clip_image002

信号说明

1、LCDCS片选信号,低电平有效

2、LCDRS命令/数据标志,0命令,1数据

3、LCDWR:写数据信号

4、LCDRD读数据信号

5、RESET复位信号

6、DB[15:0]16位真彩色数据

7、SP2CLKSPI协议clk信号

8、SP2MOSISPI协议mosi信号

9、SP2MISOSPI协议miso信号

10TCSSPI协议片选信号

上面这些信号,是不是和LCD1602是相似了。只是多了一个SPI接口,表示可以通过SPI和驱动芯片数据交互的。

下面是时序图:

clip_image004

1、对于写入

WR的上升沿,数据/命令被写入

2、对于读取

RD的上升沿,数据被读取

这时序图是不是也比较熟悉了,和LCD1602也差不多。只是读写信号分开,并且是在上升沿触发。

有了这些基础了,写程序,那就简单了。先实现最底层的三个函数,一个写命令,一个写数据,一个读数据。

1、写数据,写数据是比较常用的,所以使用宏定义,加快写的速度

//写16位数据函数 #define LCD_WR_DATA(data){\ LCD_RS_SET;\ LCD_CS_CLR;\ DATAOUT(data);\ LCD_WR_CLR;\ LCD_WR_SET;\ LCD_CS_SET;\ }

2、写命令,这个就直接用函数是函数实现就可以了

//写命令 void LCD_WR_REG(u16 data) { LCD_RS_CLR; LCD_CS_CLR; DATAOUT(data); LCD_WR_CLR; LCD_WR_SET; LCD_CS_SET; }

3、读数据,首先写命令,然后将数据线设置为输入,在读取数据,读取完毕后,在将数据线设置为输出

//读寄存器 u16 LCD_ReadReg(u8 LCD_Reg) { u16 t; LCD_WR_REG(LCD_Reg); //写入要读的寄存器号 GPIOE->CRL=0X88888888; //PE0-7 上拉输入 GPIOE->CRH=0X88888888; //PE8-15 上拉输入 GPIOE->ODR=0XFFFF; //全部输出高 LCD_RS_SET; LCD_CS_CLR; //读取数据 LCD_RD_CLR; delay_us(5);//FOR 8989,延时5us LCD_RD_SET; t=DATAIN; LCD_CS_SET; GPIOE->CRL=0X33333333; //PE0-7 上拉输出 GPIOE->CRH=0X33333333; //PE8-15 上拉输出 GPIOE->ODR=0XFFFF; //全部输出高 return t; }

以上就是3个底层函数了。其中的SET,CLR都是使用的宏。有了这三个代码,下面就可以封装一个函数,向寄存器写数据。从寄存器读数据,上面已经是实现了。

//写寄存器写数据 void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue) { LCD_WR_REG(LCD_Reg); LCD_WR_DATA(LCD_RegValue); }

以上程序,都没有加延时,那是因为STM32是运行比较慢的,运行起来完全符合芯片规定的时序,所以就不用加延时,但是如果用高速的设备的话,就要考虑芯片的时序了。以下是芯片的时序:

clip_image006

有了向寄存器写数据和从寄存器读取数据,然后就可以封装其他的函数了。比如显示图片,显示数字,画线,画矩形框等。无非就是调用这两个函数,再看数据手册,要往哪些寄存器写数据,往哪些寄存器读数据即可。

我用的TFT是用的16位真彩色,R(5)G(6)B(5)。我们使用的pc机用的是24位真彩色,所以如果我们想要把PC上的某一种颜色给显示到TFT上的话,就要将24位真彩色给转换成16位真彩色。

转换的原则也很简单,在24位真彩色中,RGB都是8位。将RB3位舍弃,G低两位舍弃,然后在按照RGB的顺序组合即可。

以下代码可以实现这个功能:

/********************************************* RGB颜色混合 入口参数:R(红色分量)0-255,G(绿色分量)0-255,B(蓝色分量)0-255 出口参数: 按R5-G6-B5格式混合后的16位颜色码。 说明:将电脑上常见的R8-G8-B8格式转换成16位单片机常用的R5-G6-B5格式。 **********************************************/ u16 RGB(u8 R,u8 G,u8 B) { return((u16)(R&0XF8)<<8|(u16)(G&0XFC)<<3|(u16)(B&0XF8)>>3); }

因为后面实现2048,会在TFT上显示图片,所以,要实现显示图片的函数。以下就是显示图片的函数:

/********************************************************** 显示图片(图标) 入口参数:(x,y)是开始点的坐标,length是图片长度,high是图片高度。//pic 图片数组的指针 出口参数: 无 说明:用指定位置上显示事先定义的图片。 要显示的图片事先定义在bmp pic[]数组中, 如果想修改图片大小、内容,请修改bmp pic[]数组, 建议用Image2Lcd软件将你要显示的图象自动转换为数组数据。 ************************************************************/ void GUI_DisPicture(uchar x, uint y, uchar length, uint high ,const uchar *pic) { u16 temp=0,tmp=0,num=0; u32 address=0; LCD_setwindow(x,y,x+length-1,y+high-1); num=length*high*2; do { temp=pic[tmp]|( pic[tmp+1]<<8); LCD_WR_DATA(temp);//逐点显示 tmp+=2; }while(tmp
       

参数有5个:

x:显示图片的左上角的x坐标

y:显示图片的左上角的y坐标

length:图片的长度(x方向)

high图片的高度(y方向)

pic图片数据的一维数组

首先是使用LCD_setwindow函数,因为是要在一个矩形区域里面显示图片,也就意味着是在这个区域内写数据,如果每次都写一行数据,然后写下一行坐标,再写数据的话,效率就比较低,ILI9320提供了4个寄存器,只要往这4个寄存器里面写入矩形区域的坐标的话,就可以一直写数据,数据会依次的填充矩形区域,就实现在矩形区域显示图片了。

然后就是不断从图片的数组中把数据取出来,因为数据是以8位存储的,所以要读取两个数据再拼接下,再讲数据写入到TFT中。直到图片的数据写完。

所以TFT驱动,核心的还是底层的三个函数,只要底层的三个函数实现了,实现其他的函数也就很简单了。

Baidu
map