历史上的今天
今天是:2025年03月05日(星期三)
2020年03月05日 | 【ARM裸板】LCD硬件原理、时序及初始化
2020-03-05 来源:eefocus
1.LCD与OLED的区别
LCD背光源与OLED自发光
LCD无机材料,LCD寿命较长。OLED广视角、几乎无穷高的对比度、可以弯曲、较低耗电优点。

2.LCD原理
屏幕上的每一个点称为像素
每个像素点由RGB三原色组成

2.1 颜色如何确定?
由RGB三组信号线组成
由下原理图可知:R5条、G6条,B5条,即RGB565(彩色模式, 一个像素占两个字节)
因此其每个像素占用多少位(BBP:bit per piexl)为2个字节

2.2 LCD如何“行扫描”?
有一条CLK时钟线与LCD相连,每发出一次CLK(高低电平),就移动一个像素。
2.3 如何跳到下一行进行“行扫描”?
有一条HSYNC(水平同步信号)信号线与LCD相连,每发出一次脉冲(高低电平),行扫描跳到下一行的起始位置。
2.4 如何进行下一个“场扫描”?
有一条VSYNC(垂直同步信号)信号线与LCD相连,每发出一次脉冲(高低电平),就跳到原点。
注意:RGB数据线上的数据从何而来?
内存里面手动划分一块显存(FrameBuffer),里面存放了要显示的数据,LCD控制器从里面将数据读出来,通过RGB三组线传给LCD,再依次打到显示屏上。

3.LCD时序
分辨率 = Hsync的个数 * 一行中的有效CLK
完整时序图:

形象时序图:

以上两张图可以解释LCD控制时序中的Hsync与Vsync的协同(可以理解 一帧是一个垂直同步信号、一行是一个水平同步信号)
1.首先一帧(Vsync)中有若干个行(Hsync),设为y,Vsync发出帧脉冲宽度Tvp
2.经过 Tvb 时间,才可以发送一帧的数据,从第一行开始
3.其次一行(Hsync)中有若干个时钟信号(CLK),有效的设为x,Hsync发出脉冲宽度Thp
4.经过 Thb 时间,才可以发送一行的数据
5.直到发送到一行的最后一个像素,经过 Thf 时间,才会有下一个水平同步信号(Hsync)
6.直到发送到最后一行,经过 Tvf 时间,才会有下一个垂直同步信号(Vsync)
由上可知几个重要的信号引脚:Hsync、Vsync 、CLK、Dn
由上可知几个重要的时间参数:Tvp、Tvb 、Thp、Thb、Thf 、Tvf
4.LCD控制器
思路:
1.取数据:把FrameBuffer的地址、bpp、分辨率告诉LCD控制器
2.发数据:把时序告诉LCD控制器、并设置引脚的极性(本款是下降沿取数据,但是有的LCD是上升沿有效,因此需要设置极性)

4.1 像素数据格式
使用的像素数格式如下:16BPP

565数据格式引脚连接图:

4.2 调色板
本应该用FrameBuffer中用16bit表示1像素,可以用8bit存放在FrameBuffer来省空间
8bit存放的是调色板中颜色的索引(共256中16bit颜色)
那么当使用像素深度为8pp时候,像素深度和我们的带宽不一致,我们的颜色要用16位表示,如果直接用上肯定不可能,那我们就可以选择用调色板,调色板中存放了256种16bpp的颜色,这时候我们color存放的就不是真实的颜色值了,而是存放的是调色板中256种颜色的索引,成线性关系一一对应,这样我们大大减轻了系统的负担。用16bpp还是8bpp这得取决实际情况,16bpp肯定比8pp清晰,但同时带来的负荷也更加重。
调色板工作示意图


5.编程框架

面向对象编程
参数层:
1.抽象出(不同设备)共同的参数结构体
2.上层的设备结构体指针指向所需的参数结构体
驱动层
1.抽象不同平台的LCD控制器结构体
2.上层的LCD控制器结构体指针指向所需的结构体
6. 结构体参数
6.1 引脚极性结构体
由上3.LCD时序可知几个重要的信号引脚:Hsync、Vsync 、CLK、Dn:Hsync、Vsync 、CLK、Dn

/* 引脚极性结构体
* NORMAL:正常极性
* INVERT:反转极性
*/
typedef struct pins_polarity{
int vclk; /* normal:下降沿获取数据 */
int rgb; /* normal:高电平表示1 */
int hsync; /* normal:高脉冲 */
int vsync; /* normal:高脉冲 */
}pins_polarity, *p_pins_polarity;
6.2 时序结构体
由上3.LCD时序可知几个重要的时间参数:Tvp、Tvb 、Thp、Thb、Thf 、Tvf
/* 时序结构体
* NORMAL:正常极性
* INVERT:反转极性
*/
typedef struct time_sequence{
/* 垂直方向 */
int tvp; /* Vsync脉冲宽度 */
int tvb; /* 上边黑框 Vertical Back porch */
int tvf; /* 下边黑框 Vertical Front porch */
/* 水平方向 */
int thp; /* Hsync脉冲宽度 */
int thb; /* 左边黑框 Horizontal Back porch*/
int tvf; /* 右边黑框 Horizontal Front porch */
}time_sequence,*p_time_sequence;
6.3 LCD控制器结构体
包含初始化、使能、禁止函数
/* 抽象LCD控制器结构体
* 向上:接收不同的LCD参数
* 向下:使用这些参数设置对应的LCD Controller
*/
typedef struct lcd_controller{
void (*init)(p_lcd_params plcdparams); //初始化
void (*enable)(void); //使
void (*disable)(void); //禁止
}lcd_controller,*p_lcd_controller;
7.初始化LCD引脚
初始LCD专用引脚,配置其模式:LCD Data 与 LCD Control
/* 初始化LCD引脚 */
void jz2440_pin_init(void)
{
/* 初始化 背光引脚: GPB0 */
GPBCON &= ~0x03;
GPBCON |= 0x01; //输出模式
/* 初始化LCD专用引脚 */
GPCCON = 0xAAAAAAAA;
GPDCON = 0xAAAAAAAA;
/* 电源引脚 LCD_PWRDN */
GPGCON |= (3<<8);
}
为了方便GPC、GPD两组,都设置为LCD专用引脚为 0xAAAAAAAA




由下图S3C2440 LCD控制器时序可得,在设置寄存器时需要在时间参数上-1

8.LCD控制器初始化

8.1 LCDCON1
/* LCDCON1[17:8] : CLKVAL, vclk = HCLK/[(CLKVAL+1)*2]
* = 100M/[(CLKVAL+1)*2]
* CLKVAL = 100/vclk/2 - 1 , vclk
* [6:5]:0b11,TFT LCD
* [4:1]:bpp mode
* [0] :LCD video output and the logic enable(1)/disable(0)
*/
int clkval = (double)100/plcdparams->time_seq.vclk/2 - 1 + 0.5;
int bppmode = (plcdparams == 8) ? 0x0B : //8bpp
(plcdparams == 16) ? 0x0C : //16bpp
0x0D; //24bpp
LCDCON1 = (clkval << 8) | (3 << 5) | (bppmode << 1);

8.2 LCDCON2
/* 垂直
* [31:24] :VBPD = Tvb - 1
* [23:14] :LINEVAL = line - 1 行数值
* [13:6] :VFPD = Tvf - 1
* [5:0] :VSPW = Tvp -1
*/
LCDCON2 = ((plcdparams->time_seq.tvb -1) << 24) |
((plcdparams->yres -1) << 14) |
((plcdparams->time_seq.tvf -1) << 6 ) |
((plcdparams->time_seq.tvp -1) << 0 );

8.3 LCDCON3
/* 水平
* [31:19] :HBPD = Thb - 1
* [18:8] :HOZVAL = 列 - 1 横向像素点
* [7:0] :HFPD = Thf - 1
*/
LCDCON3 = ((plcdparams->time_seq.thb -1) << 19) |
((plcdparams->xres -1) << 8) |
((plcdparams->time_seq.thf -1) << 0 );

8.4 LCDCON4
/* [23:14] :HSPW = thp - 1 行脉冲宽度
*/
LCDCON4 = ((plcdparams->time_seq.thp -1) << 0 );

8.5 LCDCON5
/* 用来设置引脚极性, 设置16bpp数据格式, 设置内存中象素存放的格式
* [12] : BPP24BL,This bit determines the order of 24 bpp video memory.
* [11] : FRM565, 1-565
* [10] : INVVCLK, 0 = The video data is fetched at VCLK falling edge
* [9] : HSYNC是否反转
* [8] : VSYNC是否反转
* [7] : INVVD, rgb是否反转
* [6] : INVVDEN
* [5] : INVPWREN
* [4] : INVLEND
* [3] : PWREN, LCD_PWREN output signal enable/disable
* [2] : ENLEND
* [1] : BSWP
* [0] : HWSWP
*/
pixelformat = plcdparams->pins_pol.bpp == 24 ? (1<<12) : //24bpp
plcdparams->pins_pol.bpp == 16 ? (1) : //16bpp
(1<<1);//8ppp
LCDCON5 = (plcdparams->pins_pol.vclk<<10) |
(plcdparams->pins_pol.hsync<<9) |
(plcdparams->pins_pol.vsync<<8) |
(plcdparams->pins_pol.rgb<<7) |
(plcdparams->pins_pol.de<<6) |
(plcdparams->pins_pol.pwren<<5) |
(1<<11) | pixelformat;


8.6 LCDSADDR
由下图可知:是将fb_base的[30:1]直接写入LCDSADDR1寄存器
起始地址

结束地址 = 起始地址 + x * y * bpp/8
即为:起始地址+一帧所占空间大小

9.构造LCD参数结构体
对于该款4.3寸LCD而言的参数设置
/* 该款4.3寸 LCD参数结构体 */
lcd_params lcd_4_3_params{
.name = "lcd4.3",
.pins_pol = {
vclk = NORMAL, /* normal:下降沿获取数据 */
hsync = INVERT, /* normal:高脉冲 */
vsync = INVERT, /* normal:高脉冲 */
rgb = NORMAL, /* normal:高电平表示1 */
de = NORMAL, /* normal:高电平使能 data enable */
pwren = NORMAL, /* normal:高电平使能power enable */
},
.time_seq = {
/* 垂直方向 */
tvp = 10, /* Vsync脉冲宽度 */
tvb = 2, /* 上边黑框 Vertical Back porch */
tvf = 2, /* 下边黑框 Vertical Front porch */
/* 水平方向 */
thp = 41, /* Hsync脉冲宽度 */
thb = 2, /* 左边黑框 Horizontal Back porch*/
thf = 2, /* 右边黑框 Horizontal Front porch */
vlck = 9,/* MHz */
}.
.xres = 480,
.yres = 272,
.bpp = 16, /* 16bit */
.fb_base,
};
史海拾趣
|
ARM,DSP,FPGA,CPLD,SOPC,SOC之间的联系和区别 arm是一种嵌入式芯片,比单片机功能强,可以针对需要增加外设。类似于通用cpu,但是不包括桌面计算机。 DSP主要用来计算,计算功能很强悍,一般嵌入式芯片用来控制,而DSP用来计算,譬如一般手机有一个arm芯片,主要用来跑界面,应用程序,DSP可能 ...… 查看全部问答> |
|
我想在eboot中加入USB中断的方式下载功能。现在遇到这么一个问题,中断触发时,响应中断,进入中断处理函数,然后退出中断。等下一个中断到来时,就无法响应中断了。中断处理函数退出时,已经开了中断。也就是说,只响应一次中断,请问,这是什么原 ...… 查看全部问答> |
|
wince下的驱动程序的编写是不是都可以用流驱动来做,, 我知道像键盘.显示.电源都是本机驱动... 想问一下打印机驱动可以用流驱动来做不??怎样实现与具体的硬件相连呢?… 查看全部问答> |
|
用DSP2812的捕捉口来捕捉过零点检测,但是捕捉到的脉冲信号不稳定,过零点后的脉冲方波已经加了低通滤波器和施密特触发器了,但是DSP捕捉到的信号仍不稳定怎么办啊!!!… 查看全部问答> |




