LCD编程_LCD控制器
CLKVAL :
VCLK = HCLK / [(CLKVAL+1) x 2]--------> CLKVAL = HCLK/VCLK/2-1
在这个地方HCLK=100M,那么VLCK等于多少呢?需要打开lcd的芯片手册
从中可以看出,5<= vclk<=12,正常情况是取9.
当VCLK =9 时,CLKVAL = 4.5 。取一个整数为5。当CLKVAL取为5时,再判断一下,VCLK是否在5到12之间。
PNRMODE:取11 = TFT LCD panel
BPPMODE :只支持8bpp/16bpp/24bpp
ENVID:LCD video output and the logic enable/disable. 用来使能LCD控制器本身,是否输出信号。在这个地方暂不设置,后面初始化函数中再进行设置。
将上一篇博客中led.h文件中的time_sequence增加一个数据成员vclk。
因此就有了下面这样的代码:
2、垂直方向和水平方向上一些参数的设置
垂直:
水平:
从上面的图可以看出:
垂直:
VBPD+1 = tvb -------->VBPD = tvb - 1
VFPD+1 = tvf --------->VFPD = tvf - 1
VSPW+1 = tvp --------->VSPW = tvp - 1
LINEVAL+1 = line ----->LINEVAL = line -1
水平:
HBPD+1 = thb
HBPD+1 = thb -------->HBPD= thb - 1
HFPD+1 = thf --------->HFPD = thf - 1
HOZVAL +1 = line ----->HOZVAL = 列 -1
注意在这个地方水平方向的同步脉冲宽度并没有设置,别急它是在另一个寄存器中设置的。
HSPW+1 = thp ------>HSPW = thp - 1
因此有了下面的代码:
3、
BPP24BL : This bit determines the order of 24 bpp video memory 。这一位只对24bpp中数据的存放格式有影响,对16bpp/8bpp都是没有影响的。
如果采用的是24bpp,在这里我们采用第一种方式,即将BPP24BL设置为0
那如果是16bpp,应该设置什么东西,使其指定数据的存放格式呢?
对于16bpp来说,是通过HWSWP来进行指定数据存放格式的,在此将HWSWP取为1
对于8bpp来说,又是通过什么来进行指定呢?
对于8bpp来说,是通过BSWP来进行指定数据存放格式的,在此将BSWP取为1
在这个地方,我们用pixelplace来指定数据存放的格式。
FRM565 : This bit selects the format of 16 bpp output video data. 用来设置16bpp数据输出的格式的,采用565格式。
INVVCLK:This bit controls the polarity of the VCLK active edge 。这一位控制着VCLK是上升沿有效还是下降沿有效。
INVVLINE :水平同步信号的极性
INVVFRAME:垂直同步信号的极性
INVVD :数据的极性
INVVDEN :数据使能信号的极性
INVPWREN :电源信号的极性
因此有了下面的程序:
4、framebuffer地址
至此,根据传入的LCD参数设置LCD控制器就已经完成了。
5、
接下来完成s3c2440_lcd_controller_enalbe,首先来看一下,lcd的原理图。
LED是lCD的背光驱动的电源。LED的背光驱动电路:
当KEYBOARD为高电平时,它可以给背光驱动电路提供电源,此时LCD才会亮起来。
那KEYBOARD又接在哪里呢?搜索一下:
可以看到KEYBOARD接的是GPB0,用于控制背光灯。需要设置为输出,需要设置GPBCON寄存器
使GPB0输出为1,需要设置GPBDAT寄存器
LCDCON1中的bit0,用来使能LCD控制器本身,是否输出信号。需要设置为1
LCDCON5中的PWREN
PWREN:LCD_PWREN output signal enable/disable.
6、
再看一下lcd的原理图,对于lcd用到的那些引脚也需要进行设置。
比如说VD19这样的引脚,搜索VD19
从这个图可以看出,对于VD[23:0],用到了两组寄存器 GPD和GPC。
对于VM,需要设置GPC4;
对于VLINE,需要设置GPC2
对于LCD_LPCREVB,需要设置GPC7
对于LCD_LPCREV,需要设置GPC6
对于VFRAME,需要设置GPC3
对于VCLK,需要设置GPC1
对于LEND,需要设置GPC0
打开GPDCON和GPCCON寄存器,看一下:
可以看到相邻的两位取10即可。
可以看到相邻的两位取10即可。
对于LCD_PWREN,需要设置GPG4。
因此就有了下面的代码:
现将整个代码贴出来:
1 #define HCLK 100
2
3 void jz2440_lcd_pin_init(void)
4 {
5 /* 初始化引脚 : 背光引脚 */
6 GPBCON &= ~0x3;
7 GPBCON |= 0x01;
8
9 /* LCD专用引脚 */
10 GPCCON = 0xaaaaaaaa;
11 GPDCON = 0xaaaaaaaa;
12
13 /* PWREN */
14 GPGCON |= (3<<8);
15 }
16
17
18 /* 根据传入的LCD参数设置LCD控制器 */
19 void s3c2440_lcd_controller_init(p_lcd_params plcdparams)
20 {
21 int pixelplace;
22 unsigned int addr;
23
24 jz2440_lcd_pin_init();
25
26 /* [17:8]: clkval, vclk = HCLK / [(CLKVAL+1) x 2]
27 * 9 = 100M /[(CLKVAL+1) x 2], clkval = 4.5 = 5
28 * CLKVAL = 100/vclk/2-1
29 * [6:5]: 0b11, tft lcd
30 * [4:1]: bpp mode
31 * [0] : LCD video output and the logic enable/disable
32 */
33 int clkval = (double)HCLK/plcdparams->time_seq.vclk/2-1+0.5;
34 int bppmode = plcdparams->bpp == 8 ? 0xb :\
35 plcdparams->bpp == 16 ? 0xc :\
36 0xd; /* 0xd: 24bpp */
37 LCDCON1 = (clkval<<8) | (3<<5) | (bppmode<<1) ;
38
39 /* [31:24] : VBPD = tvb - 1
40 * [23:14] : LINEVAL = line - 1
41 * [13:6] : VFPD = tvf - 1
42 * [5:0] : VSPW = tvp - 1
43 */
44 LCDCON2 = ((plcdparams->time_seq.tvb - 1)<<24) | \
45 ((plcdparams->yres - 1)<<14) | \
46 ((plcdparams->time_seq.tvf - 1)<<6) | \
47 ((plcdparams->time_seq.tvp - 1)<<0);
48
49 /* [25:19] : HBPD = thb - 1
50 * [18:8] : HOZVAL = 列 - 1
51 * [7:0] : HFPD = thf - 1
52 */
53 LCDCON3 = ((plcdparams->time_seq.thb - 1)<<19) | \
54 ((plcdparams->xres - 1)<<8) | \
55 ((plcdparams->time_seq.thf - 1)<<0);
56
57 /*
58 * [7:0] : HSPW = thp - 1
59 */
60 LCDCON4 = ((plcdparams->time_seq.thp - 1)<<0);
61
62 /* 用来设置引脚极性, 设置16bpp, 设置内存中象素存放的格式
63 * [12] : BPP24BL
64 * [11] : FRM565, 1-565
65 * [10] : INVVCLK, 0 = The video data is fetched at VCLK falling edge
66 * [9] : HSYNC是否反转
67 * [8] : VSYNC是否反转
68 * [7] : INVVD, rgb是否反转
69 * [6] : INVVDEN
70 * [5] : INVPWREN
71 * [4] : INVLEND
72 * [3] : PWREN, LCD_PWREN output signal enable/disable
73 * [2] : ENLEND
74 * [1] : BSWP
75 * [0] : HWSWP
76 */
77
78 pixelplace = plcdparams->bpp == 24 ? (0<<12) : |\
79 plcdparams->bpp == 16 ? (1<<0) : |\
80 (1<<1); /* 8bpp */
81 LCDCON5 = (plcdparams->pins_pol.vclk<<10) |\
82 (plcdparams->pins_pol.rgb<<7) |\
83 (plcdparams->pins_pol.hsync<<9) |\
84 (plcdparams->pins_pol.vsync<<8) |\
85 (plcdparams->pins_pol.de<<6) |\
86 (plcdparams->pins_pol.pwren<<5) |\
87 (1<<11) | pixelplace;
88
89 /* framebuffer地址 */
90 /*
91 * [29:21] : LCDBANK, A[30:22] of fb
92 * [20:0] : LCDBASEU, A[21:1] of fb
93 */
94 addr = plcdparams->fb_base & ~(1<<31);
95 LCDSADDR1 = (addr >> 1);
96
97 /*
98 * [20:0] : LCDBASEL, A[21:1] of end addr
99 */
100 addr = plcdparams->fb_base + plcdparams->xres*plcdparams->yres*plcdparams->bpp/8;
101 addr >>=1;
102 addr &= 0x1fffff;
103 LCDSADDR2 = addr;//
104 }
105
106 void s3c2440_lcd_controller_enalbe(void)
107 {
108 /* 背光引脚 : GPB0 */
109 GPBDAT |= (1<<0);
110
111 /* pwren : 给LCD提供AVDD */
112 LCDCON5 |= (1<<3);
113
114 /* LCDCON1'BIT 0 : 设置LCD控制器是否输出信号 */
115 LCDCON1 |= (1<<0);
116 }
117
118 void s3c2440_lcd_controller_disable(void)
119 {
120 /* 背光引脚 : GPB0 */
121 GPBDAT &= ~(1<<0);
122
123 /* pwren : 给LCD提供AVDD */
124 LCDCON5 &= ~(1<<3);
125
126 /* LCDCON1'BIT 0 : 设置LCD控制器是否输出信号 */
127 LCDCON1 &= ~(1<<0);
128 }
129
130 struct lcd_controller s3c2440_lcd_controller = {
131 .init = s3c2440_lcd_controller_init,
132 .enalbe = s3c2440_lcd_controller_enalbe,
133 .disable = s3c2440_lcd_controller_disable,
134 };