由玻璃板夹液晶盒,外加偏光片,滤光片等组成。液晶本是不会发光的,所以还要加一个背光灯,通过层层材料处理最后得到图像。
RGB888液晶屏,每个像素点是三个小灯,红绿蓝三原色可以组合很多颜色。其像素格式是8bit,那么三个灯就是24bit。2^24=1677w种颜色。现在还有10bit的HDR10的屏幕。
时钟信号,RGB信号线,水平同步信号,垂直同步信号,数据线。
VSYNC是垂直同步信号,当HSYNC信号出现时表示一帧像素点信号传输结束。
HSYNC是水平同步信号,当出现HSYNC信号时表示一行的像素点传输开始。
查询LCD的手册看时序图了解LCD的各个时间参数。
显示存储空间,存储一帧的图像空间。
我们使用DOTCLK接口,也就是VSYNC、HSYNC、ENABLE、DOTCLK接口
1、LCDIF_CTRLn寄存器,操作液晶屏bit0必须要置1,bit1设置数据格式24位全部有效,bit5设置工作在主机模式下,bit9:8设置输入像素格式位24比特位0x3 ,bit11:10设置数据传输宽度为24写0x3,bit13:12设置数据交换设置为0,bit15:14输入数据交换为0,bit17设置为DOTCLK模式下。bi19必须置1在运行,bit30必须置0,bit31必徐置0
2.LCDIF_CTRL1的bit19-16必须设置为0x7。24位的格式。
3.LCDIF_TRASFER_COUNT寄存器:bit15:0是LCD一行的像素数,1024。
4.LCDIF_VDCTRL0n寄存器,根据屏幕设置。bit17:0为vspw参数。bit20设置VSYNC信号的宽度单位。bit21设置VSYNC的周期单位。bit24设置ENABLE信号极性,bit25设置DOTCLK信号极性,bit26设置HSYNC信号极性,bit27设置VSYNC信号极性。bit28设置使能DOTCLK模式。bit29设置VSYNC输出置0。
5.LCDIF_VDCTRL1寄存器:为VSYNC两个下降沿信号之间的长度。
6.LCDIF_VDCTRL2寄存器:bit17:0设置两个HYSNC信号之间的长度,bit31:18设置HSPW信号的宽度。
7.LCDIF_VDCTRL3寄存器:bit15:0是vbp+vspw , bit27:16是hbp+hspw
8:LCDIF_VDCTRL4寄存器:bit17:0是一行有多少个像素点。1024
9.LCDIF_CUR_BUF寄存器:当前缓存显存首地址。
10.LCDIF_NEXT_BUF寄存器:LCD下一帧数据首地址。
LCDIF_CLK_ROOT=51.2MHz配置,设置VIDEO_PLL为时钟源。
频率设置公式:PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM),根据CCM_ANALOG_PLL_VIDEO寄存器设置。6:0bit 设置DIV_SELECT (27~54)。PLL_VIDEOn寄存器bit20:19,为2表示1分频。CCM_ANALOG_MISC2寄存器的31:30位。CCM_ANALOG_PLL_VIDEO_NUM分子寄存器不设置,设置为0。接下来直接看时钟树图,就不在此详细说明了。
CCM_CSCDR2的寄存17:15设置LCDIF1_PRE_CLK_SEL模式0x2。CSCDR2[LCDIF1_PRED]分频bit14:12,CBCMR[LCDIF1_PODF]分频bit25:23设置二级分频,也为1-8分频。CSCDR2[LCDIF1_CLK_SEL]的多路选择器置为0,作为之前配置的那一路时钟源。
初始化配置DATA00-DATA23位。
初始化配置LCD_HSYNC,LCD_VSYNC,LCD_ENABLE,LCD_CLK引脚,包括复用和电气配置(0xb9)。
创建lcd接口相关的结构体,写入一些LCD必须的信息。
/*LCD frame address*/
#define LCD_FRAMEBUF_ADDR = (0x89000000)
#define LCD_BLACK 0x00000000
#define LCD_WHITE 0x00ffffff
/* LCD屏幕信息结构体 */
struct tftlcd_typedef{
unsigned short height; /* 屏幕高度 */
unsigned short width; /* 屏幕宽度 */
unsigned char pixsize; /* 每个像素所占用的字节数 */
unsigned short vspw;
unsigned short vbpd;
unsigned short vfpd;
unsigned short hspw;
unsigned short hbpd;
unsigned short hfpd;
unsigned int framebuffer; /* 屏幕显存起始地址 */
unsigned int forecolor; /* 前景色 */
unsigned int backcolor; /* 背景色 */
};
void Lcd_Init(void);
void LcdGpio_Init(void);
void Lcdif_reset();
void Lcdif_noreset();
void Lcd_Enabel(void);
void Lcd_ClkInit(unsigned char loopDiv ,unsigned char prediv , unsigned char div);
void Lcd_Init(void)
{
LcdGpio_Init();
Lcdif_reset(); /*Reset*/
delay_ms(10);
Lcdif_noreset(); /*Stop Reset*/
//根据屏幕设置
tftlcd_dev.height = 0;
tftlcd_dev.width = 0;
tftlcd_dev.vspw = 0;
tftlcd_dev.vfpd = 0;
tftlcd_dev.vbpd = 0;
tftlcd_dev.hspw = 0;
tftlcd_dev.hfpd = 0;
tftlcd_dev.hbpd = 0;
tftlcd_dev.pixsize = 4;
tftlcd_dev.framebuffer = LCD_FRAMEBUF_ADDR;
tftlcd_dev.forecolor = LCD_WHITE;
tftlcd_dev.backcolor = LCD_BLACK;
Lcd_ClkInit(32 ,3 ,15); //Lcd clock 51.
LCDIF->CTRL = 0;
LCDIF->CTRL = (1<<5)|(3<<8)|(3<<10)|(1<<17)|(1<<19);
LCDIF->CTRL1 = 0;
LCDIF->CTRL1 |= (7<<16);
LCDIF->TRANSFER_COUNT = 0;
LCDIF->TRANSFER_COUNT = (tftlcd_dev.height << 16)|(tftlcd_dev.width);
LCDIF->VDCTRL0 = 0;
LCDIF->VDCTRL0 |= (tftlcd_dev.vspw<<0)|(1<<20)|(1<<21)|(1<<22)|(1<<24)|(0<<25)|(0<<26)|(0<<27)|(1<<28)|(0<<29);
LCDIF->VDCTRL1 = 0;
LCDIF->VDCTRL1 = tftlcd_dev.vspw+tftlcd_dev.height+tftlcd_dev.vfpd+tftlcd_dev.vbpd;
LCDIF->VDCTRL2 = (tftlcd_dev.hspw+tftlcd_dev.hbpd + tftlcd_dev.width + tftlcd_dev.hfpd)| \
(tftlcd_dev.hspw<<18);
LCDIF->VDCTRL3 = (tftlcd_dev.vspw + tftlcd_dev.vbpd)| \
((tftlcd_dev.hspw +tftlcd_dev.hbpd)<<16);
LCDIF->VDCTRL4 = (tftlcd_dev.width)|(1<<18);
LCDIF->CUR_BUF = (unsigned int )tftlcd_dev.framebuffer;
LCDIF->NEXT_BUF = (unsigned int )tftlcd_dev.framebuffer;
Lcd_Enabel();
delay_ms(20);
Lcd_Clear(LCD_WHITE);
}
void LcdGpio_Init(void)
{
IOMUXC_SetPinMux(IOMUXC_LCD_DATA00_LCDIF_DATA00 , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA01_LCDIF_DATA01 , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA02_LCDIF_DATA02 , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA03_LCDIF_DATA03 , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA04_LCDIF_DATA04 , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA05_LCDIF_DATA05 , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA06_LCDIF_DATA06 , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA07_LCDIF_DATA07 , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA08_LCDIF_DATA08 , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA09_LCDIF_DATA09 , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA10_LCDIF_DATA10 , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA11_LCDIF_DATA11 , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA12_LCDIF_DATA12 , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA13_LCDIF_DATA13 , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA14_LCDIF_DATA14 , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA15_LCDIF_DATA15 , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA16_LCDIF_DATA16 , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA17_LCDIF_DATA17 , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA18_LCDIF_DATA18 , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA19_LCDIF_DATA19 , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA20_LCDIF_DATA20 , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA21_LCDIF_DATA21 , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA22_LCDIF_DATA22 , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_DATA23_LCDIF_DATA23 , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_CLK_LCDIF_CLK , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_ENABLE_LCDIF_ENABLE , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_HSYNC_LCDIF_HSYNC , 0);
IOMUXC_SetPinMux(IOMUXC_LCD_VSYNC_LCDIF_VSYNC , 0);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA00_LCDIF_DATA00 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA01_LCDIF_DATA01 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA02_LCDIF_DATA02 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA03_LCDIF_DATA03 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA04_LCDIF_DATA04 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA05_LCDIF_DATA05 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA06_LCDIF_DATA06 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA07_LCDIF_DATA07 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA08_LCDIF_DATA08 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA09_LCDIF_DATA09 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA10_LCDIF_DATA10 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA11_LCDIF_DATA11 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA12_LCDIF_DATA12 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA13_LCDIF_DATA13 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA14_LCDIF_DATA14 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA15_LCDIF_DATA15 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA16_LCDIF_DATA16 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA17_LCDIF_DATA17 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA18_LCDIF_DATA18 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA19_LCDIF_DATA19 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA20_LCDIF_DATA20 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA21_LCDIF_DATA21 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA22_LCDIF_DATA22 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA23_LCDIF_DATA23 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_CLK_LCDIF_CLK , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA00_LCDIF_DATA00 , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_ENABLE_LCDIF_ENABLE , 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_HSYNC_LCDIF_HSYNC, 0xb9);
IOMUXC_SetPinConfig(IOMUXC_LCD_VSYNC_LCDIF_VSYNC, 0xb9);
/*back light*/
IOMUXC_SetPinMux(IOMUXC_GPIO1_IO08_GPIO1_IO08 , 0);
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO08_GPIO1_IO08 , 0x10b0);
gpio_pin_cfg_t bl_config;
bl_config.Direction = KGPIO_DigitalOutput;
bl_config.OutputLogic = 1;
gpio_init(GPIO1 , 8 , &bl_config);
}
/*
*loopDiv : Set DIV_SELECT ,(27~54)
*prediv : Set first divider ,(1-8)
*div : Set second divider ,(1-8)
*
*LCD_CLK = 24 * loopDiv/prediv/div;
*/
void Lcd_ClkInit(unsigned char loopDiv ,unsigned char prediv , unsigned char div)
{
/*Don't use fractional frequency divider*/
CCM_ANALOG->PLL_AUDIO_NUM = 0;
CCM_ANALOG->PLL_VIDEO_DENOM = 0;
CCM_ANALOG->PLL_VIDEO = (1<<13)|(2<<19)|(loopDiv<<0);
CCM_ANALOG->MISC2 &= ~(3<<30);
CCM->CSCDR2 &= ~(7 << 15);
CCM->CSCDR2 |= (2 << 15);
CCM->CSCDR2 &= ~(7<<12);
CCM->CSCDR2 |= ( (prediv - 1) << 12);
CCM->CBCMR &= ~(7 << 23);
CCM->CBCMR |= ( (div - 1) << 23);
CCM->CSCDR2 &= ~(7 << 9);
CCM->CSCDR2 |= (1 << 9);
}
/*Reset LCD Controller*/
void Lcdif_reset(){
LCDIF->CTRL |= (1<<31);
}
void Lcdif_noreset(){
LCDIF->CTRL &= ~(1<<31);
}
/*Enable LCD Controller*/
void Lcd_Enabel(void){
LCDIF->CTRL |= (1<<0);
}