15.eLcdIF驱动

一、LCD液晶屏

​ 由玻璃板夹液晶盒,外加偏光片,滤光片等组成。液晶本是不会发光的,所以还要加一个背光灯,通过层层材料处理最后得到图像。

​ RGB888液晶屏,每个像素点是三个小灯,红绿蓝三原色可以组合很多颜色。其像素格式是8bit,那么三个灯就是24bit。2^24=1677w种颜色。现在还有10bit的HDR10的屏幕。

二、eLCDIF

​ 时钟信号,RGB信号线,水平同步信号,垂直同步信号,数据线。

​ VSYNC是垂直同步信号,当HSYNC信号出现时表示一帧像素点信号传输结束。

​ HSYNC是水平同步信号,当出现HSYNC信号时表示一行的像素点传输开始。

查询LCD的手册看时序图了解LCD的各个时间参数。

2.显存

​ 显示存储空间,存储一帧的图像空间。

三、寄存器

​ 我们使用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下一帧数据首地址。

四、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,作为之前配置的那一路时钟源。

在这里插入图片描述

五、LCD程序

1.elcdif初始化

​ 初始化配置DATA00-DATA23位。

​ 初始化配置LCD_HSYNC,LCD_VSYNC,LCD_ENABLE,LCD_CLK引脚,包括复用和电气配置(0xb9)。

2.lcd控制器接口

​ 创建lcd接口相关的结构体,写入一些LCD必须的信息。

bsp_lcd.h
/*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);
bsp_lcd.c
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);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BUS CLOCK(apb_clk)是指eLCDIF外设的根时钟LCDIF_CLK_ROOT,它给eLCDIF提供驱动的时钟源。在时钟树中,LCDIF_CLK_ROOT可以选择多种输入时钟源,包括PLL2、PLL2 PFD0、PLL2 PFD1、PLL3 PFD3、PLL3 PFD1和PLL5。预选择器会根据需要对时钟进行分频配置,然后将分频后的时钟作为LCDIF_CLK_ROOT的默认时钟源。此外,还有一些其他可选的输入时钟,如ipp_di0_clk、ipp_di1_clk、ldb_di0_clk和ldb_di1_clk,但在参考手册和寄存器中并没有对这些时钟源的配置进行介绍。因此,我们可以直接选择预选择器得到的时钟作为LCDIF_CLK_ROOT的输入时钟源。\[1\] #### 引用[.reference_title] - *1* *3* [eLCDIF—液晶显示](https://blog.csdn.net/weixin_42892101/article/details/104204598)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [DW_apb_i2c 使用介绍2--i2c初始化以及读写eeprom测试](https://blog.csdn.net/weixin_49259827/article/details/128223996)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值