博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LCD驱动程序设计
阅读量:4285 次
发布时间:2019-05-27

本文共 5068 字,大约阅读时间需要 16 分钟。

摘要

先讲LCD工作原理,分为LCD硬件体系架构,LCD显示流程和显示信号。

LCD硬件体系

其中LCD硬件体系分为LCD控制器,LCD驱动芯片,LCD液晶屏三部分。

这里写图片描述

液晶:液晶属于一种有机化合物,分子形状为长棒状,在不同的电流作用下,分子会做有规律的旋转,这样对光线(背光灯产生)产生了一定的控制,形成一个像素,而很多像素又可构成完整图象。

LCD是Liquid Crystal Display的简称。液晶显示器按驱动方式可分为STN,GF,TFT等种类,其中TFT屏在嵌入式开发中经常使用。
LCD驱动芯片是控制液晶分子发生变化的模块,它为液晶分子的偏转提供电压。通常情况下,LCD驱动芯片都与液晶屏面板做到一个电路板上。

液晶要能正确显示图像,除了要有LCD驱动芯片,还要有LCD控制器来给LCD驱动芯片提供必要的数据和控制信号。多数ARM处理器内部都集成有LCD控制器。

这里写图片描述


S3C2440的lcd控制器的内部架构图为:

这里写图片描述

  1. REGBANK: 由17个可编程的寄存器组和一块256*16的调色板内存组成,通过这些寄存器可以配置LCD控制器。
  2. LCDCDMA: 一个专用的DMA,它能自动地把在帧内存中的视频数据传送到LCD控制器,通过使用这个DMA通道,视频数据在不需要CPU的干预的情况下显示在LCD屏上。
  3. VIDPRCS: 接收来自LCDCDMA的数据,将数据转换为合适的数据格式,比如说4/8位单扫,4位双扫显示模式,然后通过数据端口VD[23:0]传送视频数据到LCD驱动器;
    4.TIMEGEN: 由可编程的逻辑组成,它生成LCD驱动器需要的控制信号,比如VSYNC、HSYNC、VCLK和LEND等,而这些控制信号又与REGBANK寄存器组中的配置密切相关,通过不同的配置,TIMEGEN就能产生这些信号的不同值,从而支持不同的LCD驱动器(即不同 的STN/TFT屏)。

LCD显示流程

1.显示从屏幕左上角第一行的第一个点开始,一个点一个点地在LCD上显示,当显示到屏幕的最右边就结束这一行(Line)。

2.接下来显示指针又回到屏幕的左边从第二行开始显示,显示指针从第一行的右边回到第二行的左边是需要一定的时间的, 我们称之为行切换。

3.以此类推,显示指针就这样一行一行的显示至矩形的右下角才把一幅图像(帧: frame)显示完成。

LCD时序图

这里写图片描述

VSYNC:垂直同步信号

HSYNC:水平同步信号
VCLK:象素时钟信号
VD[23:0]:LCD像素数据输出端口
VDEN:数据使能信号
LEND:行结束信号

1.显示从屏幕左上角第一行的第一个点开始,一个点一个点地在LCD上显示,点与点之间的时间间隔为VCLK(像素时钟信号);当显示到屏幕的最右边就结束这一行(Line),这一行的显示对应时序图上的HSYNC(水平同步信号)

2.接下来显示指针又回到屏幕的左边从第二行开始显示,显示指针从第一行的右边回到第二行的左边是需要一定的时间的, 我们称之为行切换。

3.以此类推,显示指针就这样一行一行的显示至矩形的右下角才把一幅图像(帧: frame)显示完成,这一帧的显示时间在时序图上表示为VSYNC(垂直同步信号)


驱动程序设计

思维导图为:

这里写图片描述

lcd初始化

引脚初始化主要是设置连接的引脚为lcd模式

时序初始化是设置相应寄存器,使lcd控制器输出给lcd驱动芯片的时序符合lcd显示屏的时序要求。需要设置的时序有VSPW、VBPD、LINEVAL、VFPD、CLKVAL、HSPW、HBPD、HOZVAL、HFPD。根据使用的lcd显示屏(TQ043TSCM_V0.1_40P)的数据手册,可得到时序要求:

这里写图片描述

一般取Typ的值。再结合时序图以及相应的寄存器,就可以得到相应的寄存器的值。涉及的寄存器为LCDCON1,LCDCON2,LCDCON3,LCDCON4。

帧缓存初始化

若一块272*480的显示屏要显示一张图像时,该图像的每个像素点的数据为2bytes;则内存分配一个2*272*480bytes的内存空间来存放该图像。该空间就是帧缓存。初始化帧缓存的实质是分配这个内存空间,并该地址传送给lcd控制器。分配内存空间可通过建立一个二维数组unsigned short LCDBUFFER[272][480]完成;与地址有关的寄存器为LCDSADDR1,LCDSADDR2,LCDSADDR3。

杂项初始化

杂项初始化主要是设置LCDCON1,LCDCON5这两个控制寄存器。
LCDCON1要设置的位为PNRMODE,该位选择显示屏类型;BPPMODE用于设置保存一个像素点所用的数据大小;ENVID用于开启或关闭显示屏,配置时先关闭,等配置好后再开启。

这里写图片描述

LCDCON5寄存器要设置的位为FRM565,该位设置分别用几位数据表示红绿蓝,如5:6:5表示5位表示红,6位表示绿,5位表示蓝,一共16位;INVVLINE和INVVFRAME用于选择VLINE/HSYNC ,VFRAME/VSYNC极性(在2440数据手册中,lcd时序图中这几个信号的高低电平与使用的lcd显示屏的数据手册中的时序图高低电平相反,因此这两位都填1);HWSWP位控制半字转换。

除了LCDCON1,LCDCON5外,还需要关闭临时调色板,相关寄存器为Temp Palette Register.


开启显示屏

初始化完成后,可以开启显示屏进行显示了。开启显示屏有三步:

1.与lcd驱动芯片的LCD_PWR管脚相连的gpio口要设置为LCD_PWR模式;
2.LCDCON5[3]使能power;
3.LCDCON1的ENVID位开启。
初始化以及开启显示屏的程序代码为:

#define GPCCON (*(volatile unsigned long *)0x56000020)#define GPDCON (*(volatile unsigned long *)0x56000030)#define GPGCON (*(volatile unsigned long *)0x56000060)#define LCDCON1 (*(volatile unsigned long *)0x4D000000)#define LCDCON2 (*(volatile unsigned long *)0x4D000004)#define LCDCON3 (*(volatile unsigned long *)0x4D000008)#define LCDCON4 (*(volatile unsigned long *)0x4D00000C)#define LCDCON5 (*(volatile unsigned long *)0x4D000010)#define LCDSADDR1 (*(volatile unsigned long *)0x4D000014)#define LCDSADDR2 (*(volatile unsigned long *)0x4D000018)#define LCDSADDR3 (*(volatile unsigned long *)0x4D00001C)#define TPAL (*(volatile unsigned long *)0x4D000050)#define VSPW 9#define VBPD 1#define LINEVAL 271#define VFPD 1#define CLKVAL 4   //10 = 100/((CLKVAL+1)*2)#define HSPW 40#define HBPD 1#define HOZVAL 479#define HFPD 1unsigned short LCDBUFFER[272][480];typedef unsigned int U32;typedef unsigned short U16;typedef unsigned char U8;void lcd_port_init(){    GPDCON = 0xaaaaaaaa;    GPCCON = 0xaaaaaaaa;        }void lcd_control_init(){       LCDCON1 = (CLKVAL<<8)|(0x3<<5)|(0xc<<1)|(0<<0);    LCDCON2 = (VBPD<<24)|(LINEVAL<<14)|(VFPD<<6)|(VSPW);    LCDCON3 = (HBPD<<19)|(HOZVAL<<8)|(HFPD);    LCDCON4 = (HSPW);    LCDCON5 = (1<<11)|(1<<9)|(1<<8);    LCDSADDR1 = (((U32)LCDBUFFER>>22)<<21) | (((U32)LCDBUFFER>>1)&0x1fffff);    LCDSADDR2 = (((U32)LCDBUFFER+272*480*2)>>1)&0x1fffff;    LCDSADDR3 = (0<<11) | (480*2/2);    TPAL = 0;}void lcd_init(){    lcd_port_init();    lcd_control_init();    //打开LCD电源    GPGCON |= (0x3<<8);    LCDCON5 |= (1<<3);       LCDCON1 |= 1;}

LCD显示图像

点亮显示屏最基础的是点亮显示屏某一像素点。要点亮某一点只需要往二维数组LCDBUFFER写入相应数值。 为RGB颜色查询对照表,如红色的数值为0xFF0000,但该数值不能直接写入LCDBUFFER,还需要进行转换才能得到写入LCDBUFFER的数值。从2440数据手册查的转换表:

这里写图片描述

程序为:

void point(unsigned int x,unsigned int y,unsigned int color){    unsigned int red, green, blue;    red = (color>>19) & 0x1f;    green = (color>>10) & 0x3f;    blue = (color>>3) & 0x1f;    LCDBUFFER[y][x] = (unsigned short)((red<<11)|(green<<5)|blue);  }

能显示一个像素点,我们就可以根据这程序显示任意的像素点了。

接下来显示一张特定的图像,这里我们借用一个将图像转换为数值的工具:image2lcd 。该工具可以将一个图像转换为数组,并将数组保存在.c文件下。将得到的数组值写入LCDBUFFER即可。程序代码为:

extern unsigned char bmp[90200];void Paint_Bmp(U16 x0,U16 y0,U16 wide,U16 high,const U8 *bmp){    U16 x,y;    U16 c;    U32 p = 0;    for( y = y0 ; y < y0+high ; y++ )    {        for( x = x0 ; x < x0+wide ; x++ )        {            c = bmp[p] | (bmp[p+1]<<8) ;                                                if ( ( x < 480) && ( y < 272) )            LCDBUFFER[y][x] = c ;        p = p + 2 ;         }    }}

x0,y0表示起始位置,wide表示宽度,high表示高度,该图像宽度220,高度205。

让整个显示屏显示一种颜色,除了给LCDBUFFER全部写入同一数值外,还可以利用调色板进行单色显示。相关寄存器为Temp Palette Register。

void clearSrc(unsigned int color){    TPAL = (1<<24)|(color&0xffffff);    }
你可能感兴趣的文章
异常统一处理的一些思路
查看>>
Android studio中快速try catch的快捷键
查看>>
Dialog 和 Toast
查看>>
队列在Http请求中的一点理解
查看>>
好想在你身边
查看>>
写给还在迷茫中挣扎的你
查看>>
在迷茫中执着前行
查看>>
笔记本连接无线但不能上网,网速极慢
查看>>
小蜗牛,慢慢爬
查看>>
Java关键字 -- Super
查看>>
Java -- 入口函数浅析
查看>>
EventBus 的简单使用
查看>>
Banner 浅析
查看>>
Android Crash框架Recovery
查看>>
限制 EditText 最多输入两位小数
查看>>
Android中attrs.xml文件的使用详解
查看>>
TabLayout 解析
查看>>
android获取屏幕尺寸、密度(判断手机屏幕类型)
查看>>
dpi 、 dip 、分辨率、屏幕尺寸、px、density 关系以及换算
查看>>
Android drawable 目录下不同精度 浅析
查看>>