IMX6ULL裸机开发之配置eLCDIF点亮RGB液晶屏分析及配置过程

裸机配置RGB液晶屏显示接口

eLCDIF主要特性

  • 总线主接口到源帧缓冲区数据进行显示刷新。这个接口也可以用于驱动显示器的数据。
  • PIO接口,以管理显示器和SoC之间的数据传输。
  • 8/16/18/24位LCD数据总线支持可用,具体取决于I/Omux选项。
  • 可编程定时和参数的MPU、VSYNC和DOTCLKLCD接口,以支持多种显示器。

外部接口

在这里插入图片描述
LCD_DATA0~LCD_DATA23:24根数据线,用来传输数据。双向IO口。

LCD_BUSY:忙信号线。

LCD_CLK:时钟信号线。

LCD_CS:片选信号线。

LCD_ENABLE:LCD使能信号线。

LCD_HSYNC:水平同步信号线。也叫做行同步信号,当产生此信号的话就表示开始显示新的一行。

LCD_RD_E:数据使能线。

LCD_RESET:复位信号线。

LCD_RS:数据/命令控制线。

LCD_VSYNC:垂直同步信号线。当产生此信号的话就表示开始显示新的一帧图像。

LCD_WR_RWN:读写信号线。

时钟

eLCDIF的时钟有两种选择,一般选第二种。
在这里插入图片描述

像素时钟

像素时钟即RGB LCD的时钟信号,显示一帧图像所需要的时钟数计算方法如下:

CLOCK= (VSPW+VBP+LINE+VFP) * (HSPW + HBP + HOZVAL + HFP)

60帧的话就是CLOCK*60。

接口

eLCDIF 支持三种接口:MPU 接口、VSYNC 接口和 DOTCLK 接口。

  1. MPU接口

    MPU 接口用于在 I.MX6U 和 LCD 屏幕直接传输数据和命令,该接口用于 6080/8080 接口的 LCD 屏幕。

  2. VSYNC 接口

    VSYNC 接口时序和 MPU 接口时序基本一样,只是多了 VSYNC 信号来作为帧同步,当LCDIF_CTRL 的位 VSYNC_MODE 为 1 的时候此接口使能。

  3. DOTCLK 接口

    DOTCLK 接口就是用来连接 RGB LCD 接口屏幕的, 它包括 VSYNC、HSYNC、DOTCLK和 ENABLE(可选)这四个信号,这样的接口通常被称为 RGB 接口。

eLCDIF初始化步骤

  1. 配置外部I/O,以正确连接外部显示器。
  2. 启动DISPLAY_CLK时钟,并配置适当的时钟频率。
  3. 利用CCM中的寄存器来使能BUS_CLK并配置适当的时钟频率。
  4. 使eLCDIF退出软复位,并禁用时钟。
  5. 通过适当设置LCDIF_CTRL1_RESET位来复位LCD控制器。
  6. 确保HW_LCDIF_CTRL寄存器中的READ_WRITEB位为0。
  7. 选择操作的传输方式。HW_LCDIF_CTRL寄存器中的LCDIF_MASTER位决定了所选择的传输模式。总线主模式(LCDIF_MASTER=1)或PIO(LCDIF_MASTER=0)模式。
  8. 根据液晶控制器的特性设置INPUT_DATA_SWIZZLE。另外,如果需要在数据输出之前向左或向右移动数据,请设置DATA_SHIFT_DIR和SHIFT_NUM_BITS。
  9. 适当设置WORD_LENGTH字段:0:16位输入,1:8位输入,2:18位输入,3:24/32位输入。另外,在HW_LCDIF_CTRL寄存器中选择正确的16/18/24位数据格式。
  10. 根据输入帧在HW_LCDIF_CTRL1中设置BYTE_PACKING_FORMAT字段。
  11. 适当设置LCD_DATABUS_WIDTH:0=16位输出,1=8位输出,2=18位输出,3=24/32位输出。
  12. 启用必要的中断请求。

LCDIF_RLn寄存器介绍

这个寄存器就是用来对eLCDIF进行整体控制用,通过配置这个寄存器来实现驱动各种液晶屏控制器。
在这里插入图片描述
SFTRST(bit31):eLCDIF 软复位控制位,当此位为 1 的话就会强制复位 LCD。

CLKGATE(bit30):正常运行模式下,此位必须为 0!如果此位为 1 的话时钟就不会进入到LCDIF。

BYPASS_COUNT(bit19):如果要工作在 DOTCLK 模式的话就此位必须为 1。

VSYNC_MODE(bit18):1:LCDIF 工作在 VSYNC 接口模式。

DOTCLK_MODE(bit17):1:LCDIF 工作在 DOTCLK 接口模式。

INPUT_DATA_SWIZZLE(bit15:14):输入数据字节交换设置,0:不交换字节也就是小端模式;1:交换所有字节,也就是大端模式;2:半字交换;3:在每个半字内进行字节交换。

CSC_DATA_SWIZZLE(bit13:12) :CSC数据字节交换设置 , 交换方式 和INPUT_DATA_SWIZZLE 一样

LCD_DATABUS_WIDTH(bit11:10):LCD数据总线宽度,0:16 位;1: 8 位;2:18 位;3:为 24 位。

WORD_LENGTH(bit9:8):输入的数据格式,即像素数据宽度, 0:16位;1:8 位;2:18 位;3:24 位。

MASTER(bit5):为 1 的话设置 eLCDIF 工作在主模式。

DATA_FORMAT_16_BIT(bit3):当此位为 1 并且 WORD_LENGTH 为 0 的时候像素格式为 ARGB555,当此位为 0 并且 WORD_LENGTH 为 0 的时候像素格式为 RGB565。

LCDIF_TRANSFER_COUNT寄存器介绍

这个寄存器用来配置显示区域的。
在这里插入图片描述高16位是V_COUNT, 是 LCD 的垂直分辨率。
低 16 位是 H_COUNT,是 LCD 的水平分辨率。

LCDIF_VDCTRL0寄存器介绍

该寄存器用于控制LCDIF的VSYNC和DOTCLK模式,以便与不同类型的液晶显示器链接。只用了高16位。
在这里插入图片描述
VSYNC_OEB(bit29):VSYNC 信号方向控制位,为 0 的话 VSYNC 是输出,为 1 的话VSYNC 是输入。

ENABLE_PRESENT(bit28):EBABLE 数据线使能位,也就是 DE 数据线。为 1 的话使能ENABLE 数据线,为 0 的话关闭 ENABLE 数据线。

VSYNC_POL(bit27):VSYNC 数据线极性设置位,为 0 的话 VSYNC 低电平有效,为 1 的 话 VSYNC 高电平有效,要根据所使用的 LCD 数据手册来设置。

HSYNC_POL(bit26):HSYNC 数据线极性设置位,为 0 的话 HSYNC 低电平有效,为 1 的 话 HSYNC 高电平有效,要根据所使用的 LCD 数据手册来设置

DOTCLK_POL(bit25):DOTCLK 数据线(像素时钟线 CLK) 极性设置位,为 0 的话下降沿锁存数据,上升沿捕获数据,为 1 的话相反,要根据所使用的 LCD 数据手册来设置。

ENABLE_POL(bit24):EANBLE 数据线极性设置位,为 0 的话低电平有效,为 1 的话高电平有效。

VSYNC_PERIOD_UNIT(bit21):VSYNC 信号周期单位,为 0 的话 VSYNC 周期单位为像素时钟。为 1 的话 VSYNC 周期单位是水平行,如果使用 DOTCLK 模式话就要设置为 1。

VSYNC_PULSE_WIDTH_UNIT(bit20) :VSYNC 信号脉冲宽度单位 ,和VSYNC_PERIOD_UNUT 一样,如果使用 DOTCLK 模式的话要设置为 1。

VSYNC_PULSE_WIDTH(bit17:0):VSPW 参数设置位。

LCDIF_VDCTRL1寄存器介绍

用于配置VSYNC信号在块中产生时的周期。周期 = 屏幕高度+VSPW+VBP+VFP

LCDIF_VDCTRL2寄存器介绍

高 16位是 HSYNC_PULSE_WIDTH,用来设置 HSYNC 信号宽度,也就是 HSPW。

低 16 位是HSYNC_PERIOD,用来设置 HSYNC 总周期,周期 = 屏幕宽度+HSPW+HBP+HFP

LCDIF_VDCTRL3寄存器介绍

HORIZONTAL_WAIT_CNT:设置HSYNC信号产生到有效数据产生之间的时间间隔,等于HSPW+HBP

VERTICAL_WAIT_CNT:设置VSYNC信号产生到有效数据产生之间的时间间隔,等于VSPW+VBP
在这里插入图片描述

LCDIF_VDCTRL4寄存器介绍

SYNC_SIGNALS_ON(bit18):同步信号使能位,设置为 1 的话使能 VSYNC、HSYNC、DOTCLK 这些信号。

DOTCLK_H_VALID_DATA_CNT(bit15:0):设置 LCD 的宽度,也就是水平像素数量。
在这里插入图片描述

LCDIF_CUR_BUF 和 LCDIF_NEXT_BUF寄存器

这两个寄存器分别为当前帧和下一帧缓冲区,也就是 LCD 显存。一般这两个寄存器保存同一个地址。

(这里在一开始不太明白芯片为什么直接传数据给SDRAM就能点亮RGB液晶屏,后来才知道,只要在SDRAM开辟一块缓冲区,然后让这两个寄存器指向开辟的缓冲区,并且缓冲区的大小等于屏幕宽*高,这样一来,向缓冲区内特定的位置填入数据就能够显示了,填入的颜色数据输出转换到数据线IO口这个过程则由硬件的输出块部分完成。)

在DOTCLK模式下点亮RGB液晶屏

  1. 初始化IO口
  2. 配置时钟及像素时钟
  3. 配置eLCDIF的接口
  4. 编写各种函数

代码

C文件

#include "bsp_lcd.h"
#include "bsp_gpio.h"
#include "bsp_delay.h"
#include "stdio.h"

/* 液晶屏参数结构体 */
struct tftlcd_typedef tftlcd_dev;

/*
 * @description	: 始化LCD
 * @param 		: 无
 * @return 		: 无
 */
void lcd_init(void)
{
	lcdgpio_init();			/* 初始化IO */
	lcd_reset();			/* 复位LCD  */
	delayms(10);			/* 延时10ms */
	lcd_noreset();			/* 结束复位 */

	/* TFTLCD参数结构体初始化 */
    tftlcd_dev.height = 480;	
    tftlcd_dev.width = 800;
    tftlcd_dev.vspw = 1;
    tftlcd_dev.vbpd = 23;
    tftlcd_dev.vfpd = 22;
    tftlcd_dev.hspw = 1;
    tftlcd_dev.hbpd = 46;
    tftlcd_dev.hfpd = 210;	
    lcdclk_init(30, 3, 7);	/* 初始化LCD时钟 34.2MHz */
	
	tftlcd_dev.pixsize = 4;	/* ARGB8888模式,每个像素4字节 */
	tftlcd_dev.framebuffer = LCD_FRAMEBUF_ADDR;	/*设置显存首地址*/
	tftlcd_dev.backcolor = LCD_WHITE;			/* 背景色为白色 */
	tftlcd_dev.forecolor = LCD_BLACK;			/* 前景色为黑色 */
     
	/* 初始化ELCDIF的CTRL寄存器
     * bit [31] 0 : 停止复位
     * bit [19] 1 : 旁路计数器模式
     * bit [17] 1 : LCD工作在dotclk模式
     * bit [15:14] 00 : 输入数据不交换
     * bit [13:12] 00 : CSC不交换
     * bit [11:10] 11 : 24位总线宽度
     * bit [9:8]   11 : 24位数据宽度,也就是RGB888
     * bit [5]     1  : elcdif工作在主模式
     * bit [1]     0  : 所有的24位均有效
	 */
	 LCDIF->CTRL |= (1 << 19) | (1 << 17) | (0 << 14) | (0 << 12) |
	 				(3 << 10) | (3 << 8) | (1 << 5) | (0 << 1);
	/*
     * 初始化ELCDIF的寄存器CTRL1
     * bit [19:16]  : 0X7 ARGB模式下,传输24位数据,A通道不用传输
	 */	
	 LCDIF->CTRL1 = 0X7 << 16; 

	 /*
      * 初始化ELCDIF的寄存器TRANSFER_COUNT寄存器
      * bit [31:16]  : 高度
      * bit [15:0]   : 宽度
	  */
	LCDIF->TRANSFER_COUNT  = (tftlcd_dev.height << 16) | (tftlcd_dev.width << 0);

	/*
     * 初始化ELCDIF的VDCTRL0寄存器
     * bit [29] 0 : VSYNC输出
     * bit [28] 1 : 使能ENABLE输出
     * bit [27] 0 : VSYNC低电平有效
     * bit [26] 0 : HSYNC低电平有效
     * bit [25] 0 : DOTCLK上升沿有效
     * bit [24] 1 : ENABLE信号高电平有效
     * bit [21] 1 : DOTCLK模式下设置为1
     * bit [20] 1 : DOTCLK模式下设置为1
     * bit [17:0] : vsw参数
	 */
	LCDIF->VDCTRL0 = 0;	//先清零
	if(lcdid == ATKVGA) 
	{   //VGA需要特殊处理
		LCDIF->VDCTRL0 = (0 << 29) | (1 << 28) | (0 << 27) |
					 (0 << 26) | (1 << 25) | (0 << 24) |
					 (1 << 21) | (1 << 20) | (tftlcd_dev.vspw << 0);
	} 
	else 
	{
		LCDIF->VDCTRL0 = (0 << 29) | (1 << 28) | (0 << 27) |
					 (0 << 26) | (0 << 25) | (1 << 24) |
					 (1 << 21) | (1 << 20) | (tftlcd_dev.vspw << 0);
	}

	/*
	 * 初始化ELCDIF的VDCTRL1寄存器,设置VSYNC总周期
	 */  
	LCDIF->VDCTRL1 = tftlcd_dev.height + tftlcd_dev.vspw + tftlcd_dev.vfpd + tftlcd_dev.vbpd;  //VSYNC周期
	 
	 /*
	  * 初始化ELCDIF的VDCTRL2寄存器,设置HSYNC周期
	  * bit[31:18] :hsw
	  * bit[17:0]  : HSYNC总周期
	  */ 
	LCDIF->VDCTRL2 = (tftlcd_dev.hspw << 18) | (tftlcd_dev.width + tftlcd_dev.hspw + tftlcd_dev.hfpd + tftlcd_dev.hbpd);

	/*
	 * 初始化ELCDIF的VDCTRL3寄存器,设置HSYNC周期
	 * bit[27:16] :水平等待时钟数
	 * bit[15:0]  : 垂直等待时钟数
	 */ 
	LCDIF->VDCTRL3 = ((tftlcd_dev.hbpd + tftlcd_dev.hspw) << 16) | (tftlcd_dev.vbpd + tftlcd_dev.vspw);

	/*
	 * 初始化ELCDIF的VDCTRL4寄存器,设置HSYNC周期
	 * bit[18] 1 : 当使用VSHYNC、HSYNC、DOTCLK的话此为置1
	 * bit[17:0]  : 宽度
	 */ 
	
	LCDIF->VDCTRL4 = (1<<18) | (tftlcd_dev.width);

	/*
     * 初始化ELCDIF的CUR_BUF和NEXT_BUF寄存器,设置当前显存地址和下一帧的显存地址
	 */
	LCDIF->CUR_BUF = (unsigned int)tftlcd_dev.framebuffer;
	LCDIF->NEXT_BUF = (unsigned int)tftlcd_dev.framebuffer;

	lcd_enable();			/* 使能LCD */
	delayms(10);
	lcd_clear(LCD_WHITE);	/* 清屏 */
	
}

 
/*
 * @description	: LCD GPIO初始化
 */
void lcdgpio_init(void)
{
	gpio_pin_config_t gpio_config;
	
	/* 1、IO初始化复用功能 */
	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_SetPinMux(IOMUXC_GPIO1_IO08_GPIO1_IO08,0);			/* 背光BL引脚      */
	IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18,0xF080);
					

	/* 2、配置LCD IO属性	
	 *bit 16:0 HYS关闭
	 *bit [15:14]: 0 默认22K上拉
	 *bit [13]: 0 pull功能
	 *bit [12]: 0 pull/keeper使能 
	 *bit [11]: 0 关闭开路输出
	 *bit [7:6]: 10 速度100Mhz
	 *bit [5:3]: 111 驱动能力为R0/7
	 *bit [0]: 1 高转换率
	 */
	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_ENABLE_LCDIF_ENABLE,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_HSYNC_LCDIF_HSYNC,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_VSYNC_LCDIF_VSYNC,0xB9);

	IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO08_GPIO1_IO08,0xB9);	/* 背光BL引脚 */

	/* GPIO初始化 */
	gpio_config.direction = kGPIO_DigitalOutput;			/* 输出 */
	gpio_config.outputLogic = 1; 							/* 默认关闭背光 */
	gpio_init(GPIO1, 8, &gpio_config);						/* 背光默认打开 */
	gpio_pinwrite(GPIO1, 8, 1);								/* 打开背光     */
}

/*
 * @description		: LCD时钟初始化, LCD时钟计算公式如下:
 *                	  LCD CLK = 24 * loopDiv / prediv / div
 * @param -	loopDiv	: loopDivider值
 * @param -	prediv  : lcdifprediv值
 * @param -	div		: lcdifdiv值
 * @return 			: 无
 */
void lcdclk_init(unsigned char loopDiv, unsigned char prediv, unsigned char div)
{
	/* 先初始化video pll 
     * VIDEO PLL = OSC24M * (loopDivider + (denominator / numerator)) / postDivider
 	 *不使用小数分频器,因此denominator和numerator设置为0
 	 */
	CCM_ANALOG->PLL_VIDEO_NUM = 0;		/* 不使用小数分频器 */
	CCM_ANALOG->PLL_VIDEO_DENOM = 0;	

	/*
     * PLL_VIDEO寄存器设置
     * bit[13]:    1   使能VIDEO PLL时钟
     * bit[20:19]  2  设置postDivider为1分频
     * bit[6:0] : 32  设置loopDivider寄存器
	 */
	CCM_ANALOG->PLL_VIDEO =  (2 << 19) | (1 << 13) | (loopDiv << 0); 

	/*
     * MISC2寄存器设置
     * bit[31:30]: 0  VIDEO的post-div设置,时钟源来源于postDivider,1分频
	 */
	CCM_ANALOG->MISC2 &= ~(3 << 30);
	CCM_ANALOG->MISC2 = 0 << 30;

	/* LCD时钟源来源与PLL5,也就是VIDEO           PLL  */
	CCM->CSCDR2 &= ~(7 << 15);  	
	CCM->CSCDR2 |= (2 << 15);			/* 设置LCDIF_PRE_CLK使用PLL5 */

	/* 设置LCDIF_PRE分频 */
	CCM->CSCDR2 &= ~(7 << 12);		
	CCM->CSCDR2 |= (prediv - 1) << 12;	/* 设置分频  */

	/* 设置LCDIF分频 */
	CCM->CBCMR &= ~(7 << 23);					
	CCM->CBCMR |= (div - 1) << 23;				

	/* 设置LCD时钟源为LCDIF_PRE时钟 */
	CCM->CSCDR2 &= ~(7 << 9);					/* 清除原来的设置		 	*/
	CCM->CSCDR2 |= (0 << 9);					/* LCDIF_PRE时钟源选择LCDIF_PRE时钟 */
}

/*
 * @description	: 复位ELCDIF接口
 * @param 		: 无
 * @return 		: 无
 */
void lcd_reset(void)
{
	LCDIF->CTRL  = 1<<31; /* 强制复位 */
}

/*
 * @description	: 结束复位ELCDIF接口
 */
void lcd_noreset(void)
{
	LCDIF->CTRL  = 0<<31; /* 取消强制复位 */
}

/*
 * @description	: 使能ELCDIF接口
 */
void lcd_enable(void)
{
	LCDIF->CTRL |= 1<<0; /* 使能ELCDIF */
}

/*
 * @description		: 画点函数 
 * @param - x		: x轴坐标
 * @param - y		: y轴坐标
 * @param - color	: 颜色值
 * @return 			: 无
 */
void lcd_drawpoint(unsigned short x,unsigned short y,unsigned int color)
{ 
  	*(unsigned int*)((unsigned int)tftlcd_dev.framebuffer + tftlcd_dev.pixsize * (tftlcd_dev.width * y+x))=color;
}


/*
 * @description		: 读取指定点的颜色值
 * @param - x		: x轴坐标
 * @param - y		: y轴坐标
 * @return 			: 读取到的指定点的颜色值
 */
unsigned int lcd_readpoint(unsigned short x,unsigned short y)
{ 
	return *(unsigned int*)((unsigned int)tftlcd_dev.framebuffer + tftlcd_dev.pixsize * (tftlcd_dev.width * y + x));
}

/*
 * @description		: 清屏
 * @param - color	: 颜色值
 * @return 			: 读取到的指定点的颜色值
 */
void lcd_clear(unsigned int color)
{
	unsigned int num;
	unsigned int i = 0; 

	unsigned int *startaddr=(unsigned int*)tftlcd_dev.framebuffer;	//指向帧缓存首地址
	num=(unsigned int)tftlcd_dev.width * tftlcd_dev.height;			//缓冲区总长度
	for(i = 0; i < num; i++)
	{
		startaddr[i] = color;
	}		
}

H文件

#ifndef _BSP_LCD_H
#define _BSP_LCD_H

#include "imx6ul.h"

/* 颜色 */
#define LCD_BLUE		  0x000000FF
#define LCD_GREEN		  0x0000FF00
#define LCD_RED 		  0x00FF0000
#define LCD_CYAN		  0x0000FFFF
#define LCD_MAGENTA 	  0x00FF00FF
#define LCD_YELLOW		  0x00FFFF00
#define LCD_LIGHTBLUE	  0x008080FF
#define LCD_LIGHTGREEN	  0x0080FF80
#define LCD_LIGHTRED	  0x00FF8080
#define LCD_LIGHTCYAN	  0x0080FFFF
#define LCD_LIGHTMAGENTA  0x00FF80FF
#define LCD_LIGHTYELLOW   0x00FFFF80
#define LCD_DARKBLUE	  0x00000080
#define LCD_DARKGREEN	  0x00008000
#define LCD_DARKRED 	  0x00800000
#define LCD_DARKCYAN	  0x00008080
#define LCD_DARKMAGENTA   0x00800080
#define LCD_DARKYELLOW	  0x00808000
#define LCD_WHITE		  0x00FFFFFF
#define LCD_LIGHTGRAY	  0x00D3D3D3
#define LCD_GRAY		  0x00808080
#define LCD_DARKGRAY	  0x00404040
#define LCD_BLACK		  0x00000000
#define LCD_BROWN		  0x00A52A2A
#define LCD_ORANGE		  0x00FFA500
#define LCD_TRANSPARENT   0x00000000

/* 屏幕ID */
#define ATK7084		0X7084	/* 7寸800*480 */

/* LCD显存地址 */
#define LCD_FRAMEBUF_ADDR	(0x89000000)

/* LCD控制参数结构体 */
struct tftlcd_typedef{
	unsigned short height;		/* LCD屏幕高度 */
	unsigned short width;		/* LCD屏幕宽度 */
	unsigned char pixsize;		/* LCD每个像素所占字节大小 */
	unsigned short vspw;
	unsigned short vbpd;
	unsigned short vfpd;
	unsigned short hspw;
	unsigned short hbpd;
	unsigned short hfpd;
	unsigned int framebuffer; 	/* LCD显存首地址   	  */
	unsigned int forecolor;		/* 前景色 */
	unsigned int backcolor;		/* 背景色 */
	unsigned int id;  			/*	屏幕ID */
};

extern struct tftlcd_typedef tftlcd_dev;

/* 函数声明 */
void lcd_init(void);
unsigned short lcd_read_panelid(void);
void lcdgpio_init(void);
void lcdclk_init(unsigned char loopDiv, unsigned char prediv, unsigned char div);
void lcd_reset(void);
void lcd_noreset(void);
void lcd_enable(void);
void video_pllinit(unsigned char loopdivi, unsigned char postdivi);

void lcd_drawpoint(unsigned short x,unsigned short y,unsigned int color);
unsigned int lcd_readpoint(unsigned short x,unsigned short y);
void lcd_clear(unsigned int color);
void lcd_fill(unsigned    short x0, unsigned short y0, unsigned short x1, unsigned short y1, unsigned int color);

#endif
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值