i.MX6ULL(10) LCD driver

  1 LCD Introduction

LCD (Liquid Crystal Display), liquid crystal display. The structure of the LCD is to place a liquid crystal cell in two parallel glass substrates, set a TFT (thin film transistor) on the lower substrate glass, and set a color filter on the upper substrate glass, and control the liquid crystal molecules by changing the signal and voltage on the TFT. Rotate the direction, so as to achieve the purpose of controlling whether the polarized light of each pixel is emitted or not to achieve the display purpose.

1.1 LCD structure

serial number name describe
1 backlight layer Including reflector, light guide plate, LED lamp, diffusion film, prism film
2 liquid crystal layer Composed of liquid crystal, alignment film, backlight, filter, light guide plate
3 TFT layer Including TFT transistors, capacitors, alignment films, etc.
4 Glass base board Provides a carrier for chips and circuits, providing mechanical support and protection
5 PCB substrate Connect transistors and other circuit elements to transmit signals and power

LCD screens or monitors have many interfaces, such as VGA, HDMI, MIPI DP, etc., which are common on monitors ,
but the I.MX6U-ALPHA development board does not support these interfaces.

IMX6ULL-ALPHA supports LCD with RGB interface. RGBLCD has two driving modes: DE and HV. The signal lines of RGBLCD interface are as follows

Signal line description
R[7:0] 8 red data lines
G[7:0] 8 green data lines
B[7:0] 8 blue data lines
DE data enable line
VSYNC     vertical synchronization signal line also called frame Synchronization signal , when this signal is generated, it means that a new frame of image is displayed,
HSYNC     horizontal synchronization signal line
PCLK     pixel clock signal line

1.2 RGB LCD hardware diagram

The punctual atomic screen supports multiple screen IDs. Control the up/down of R7/G7/B7 through SGM3157 to customize the ID of the LCD module and help the MCU judge the resolution and related parameters of the current LCD panel to improve program compatibility
.

                                              Figure 1.2

24-bit color data cable

ALIENTEK has three types of RGB LCD screens, the models are: ATK-4342 (4.3 inches, 480*272), ATK-
7084 (7 inches, 800*480) and ATK-7016 (7 inches, 1024*600), this The tutorial takes the screen of ATK-7016 as an example.
The schematic diagram of the screen interface of ATK-7016 is shown in Figure 24.1.1.4
 

Two Imaging Principles

The imaging process of each frame of LCD involves a series of steps and signals. The following are the basic imaging principles:

  1. Synchronization signal: First, the LCD will receive a synchronization signal, which indicates the beginning of a frame of image. The sync signal is usually a pulse signal that tells the LCD monitor to start receiving new image data.
  2. Data transmission: After receiving the synchronous signal, the LCD will start to receive image data, which includes the gray value and color information of each pixel. Image data is usually transferred to the LCD display either serially or in parallel.
  3. Row scan: After the image data is transmitted, the LCD will perform a row scan to determine the status of each pixel. Row scanning is usually done by a row driver chip, which scans each row of pixels in a certain order and determines the brightness of each pixel according to the image data.
  4. Frame Refresh: After the line scan is completed, the LCD will perform frame refresh to update the entire image. During the frame refresh process, the brightness of each pixel is adjusted according to the image data, and finally synthesized into a complete image.
  5. Vertical blanking: During the frame refresh process, in order to ensure the stability of the image, the LCD will perform vertical blanking at the end of each frame of image. During the vertical blanking period, all pixels will be cleared for the display of the next frame image.

In general, the imaging process of each frame of LCD involves steps such as synchronous signal, data transmission, row scanning, frame refresh and vertical blanking. Through these steps, the LCD monitor can display dynamic images in real time. It should be noted that the actual imaging process may be more complex and diverse, depending on the design and application requirements of the LCD display.

2.1 One-frame image scan of LCD
 


When a line is displayed, the HSYNC signal will be sent, and the electron gun (CRT display) will be turned off at this time, and then quickly move to the left of the screen. When the HSYNC signal ends, a new line of data can be displayed, and the electron gun will be turned on again.

A delay will be inserted between the end of the HSYNC signal and the reopening of the electron gun . This delay is HBP in Figure 24.1.1.5 . After one line is displayed, the electron gun will be turned off to wait for the HSYNC signal to be generated. A delay will be inserted between the electron gun is turned off and the HSYNC signal is generated. This delay is the HFP signal in Figure 24.1.1.5. In the same way, when a frame of image is displayed, the electron gun will also be turned off, and then wait until the VSYNC signal is generated, and a delay will be added during this period. This delay is the VFP
in Figure 24.1.1.5 . When the VSYNC signal is generated, the electron gun moves to the upper left corner. When the VSYNC signal ends and the electron gun is turned on again, a delay will be added in the middle . This delay is VBP in Figure 24.1.1.5

– HSYNC is a horizontal synchronization signal (horizontal synchronization signal), when this signal is generated, it means that a new line is displayed
– VSYNC is a vertical synchronization signal (frame synchronization signal), when this signal is generated, it means that a new frame of image is displayed
– HBP, HFP , VBP, and VFP are the reasons for the black border in the above picture. Sending a line or a frame of data to the IC inside the screen requires a response time for the IC. Through this response time, the IC can recognize that a line or a frame of image has been scanned.

HBP, HFP, VBP and VFP are the reasons for the black borders in Figure 24.1.1.5, but this is
the reason why there are black borders on CRT monitors, and now LCD monitors do not need electron guns, so why are there still black borders? This is because
there is an IC inside the RGB LCD screen, sending a line or a frame of data to the IC requires a response time for the IC. Through this reaction
time, the IC can recognize that a line of data has been scanned and a
new line is about to be scanned, or that a frame of image has been scanned and the next frame of image is about to be
displayed. Therefore, the main purpose of continuing to exist the four parameters HBP, HFP, VPB and VFP in the LCD screen is
to lock valid pixel data. These four times are important time parameters of the LCD
, which will be used later when writing the LCD driver
. As for the specific values ​​of these four time parameters, it is necessary to check the LCD data sheet used.

2.2 RGB LCD Screen Timing

2.2.1 Line display timing diagram

Line display timing
– HSYNC: horizontal synchronization signal (horizontal synchronization signal), when this signal is generated, it means that a new line is displayed
– HSPW: HSYNC signal width, that is, the duration of HSYNC signal, the unit is CLK
– HBP: line synchronization signal back shoulder, The unit is CLK
– HOZVAL: the time required to display a line of data, if the resolution is 1024*600, the value is 1024, the unit is CLK
– HFP: the front shoulder of the line synchronization signal, the unit is CLK

After displaying a row of data, it needs to wait for HFP CLK time before sending out the next HSYNC signal, so
the time required to display a row is: HSPW + HBP + HOZVAL + HFP.


2.2.2 Frame Display Timing Diagram

2.2.3 Pixel Clock


The pixel clock is the clock signal of the RGB LCD. Taking the ATK7016 screen as an example, the number of clocks required to display a frame of image is
: = (VSPW+VBP+LINE+VFP) * (HSPW + HBP + HOZVAL + HFP)
= ( 3 + 20 + 600 + 12) * (20 + 140 + 1024 + 160)
= 635 * 1344
= 853440.
It takes 853440 clocks to display a frame of image, then displaying 60 frames is: 853440 * 60 = 51206400≈51.2M,
so the pixel clock is 51.2MHz

  • 1. The selector is used to select which PLL is used as the LCDIF clock source.   Bit LCDIF1_PRE_CLK_SEL (bit17:15) of CCM_CSCDR2 determines   the dedicated PLL5 for VIDEO, so LCDIF1_PRE_CLK_SEL is set to 2
  • 2. The prescaler of the LCDIF clock    is determined by the bit LCDIF1_PRED of the register CCM_CSCDR2. The value that can be set is 0~7, corresponding to 1~8 frequency division respectively.
  • 3. Further frequency division The frequency division value is determined by bit LCDIF1_PODF in register CBCMR. The value that can be set is 0~7, corresponding to 1~8 frequency division respectively.
  • 4. Selector, used to select the final root clock of LCDIF. Determined by bit LCDIF1_CLK_SEL of register CSCDR2
     

CCM_CSCDR2


 

2.2.4 Video memory

As I said when talking about the pixel format, if the ARGB8888 format is used, a pixel needs 4 bytes
of memory to store pixel data, then 1024*600 resolution requires 1024*600*4=2457600B≈2.4MB of memory . But
RGB LCD has no internal memory, so it is necessary to allocate a section of memory in the DDR3 on the development board as
the video memory of the RGB LCD screen. If we want to display any image on the screen, we can directly operate this part of the video memory.
 

三  IMX6ULL Enhanced LCD Interface (eLCDIF)  

3,.1 eLCDIF interface

eLCDIF is the LCD screen interface that comes with IMX6U. It is used to connect the screen with RGB LCD interface. The characteristics of eLCDIF interface are as follows:

  • Support DE mode for RGB LCD
  • Support VSYNC mode for high-speed data transmission
  • Support 4:2:2 YCbCr digital video in ITU-R BT.656 format and convert it to analog TV signal
  • Support 8/16/18/24/32 bit LCD

1. MPU interface
MPU interface is used to directly transmit data and commands between I.MX6U and LCD screen. This interface is used for LCD screen with 6080/8080 interface
, such as the MCU screen we often use when learning STM32. If
the bits DOTCLK_MODE, DVI_MODE and VSYNC_MODE of the register LCDIF_CTRL are all 0, it means that LCDIF works in MPU
interface mode.
For detailed information about the MPU interface and timing, refer to "34.4.6 MPU Interface" on page 2150 of the "I.MX6ULL Reference Manual" . This tutorial does not use the MPU interface.
2. VSYNC interface
The timing sequence of VSYNC interface is basically the same as that of MPU interface, except that the VSYNC signal is added for frame synchronization. When
the bit VSYNC_MODE of LCDIF_CTRL is 1, this interface is enabled. For more information about the VSYNC interface, please
refer to "34.4.7 VSYNC Interface" on page 2152 of the "I.MX6ULL Reference Manual". This tutorial does not use the VSYNC
interface.
3. DOTCLK interface
DOTCLK interface is used to connect RGB LCD interface screen, it includes VSYNC, HSYNC, DOTCLK
and ENABLE (optional) these four signals, such interface is usually called RGB interface
. The timing sequence of DOTCLK interface
is shown in Figure 24.1.2.1:

Because the DOTCLK interface is connected to the RGB screen,
the DOTCLK interface is used in this routine. The following introduces several important registers of the eLCDIF interface.

3.2 Important registers

3.2.1 LCDIF_CTRL Register

  • SFTRST: eLCDIF soft reset control bit When this bit is 1, it will force reset the LCD
  • CLKGATE : This bit must be 0, otherwise the clock will not enter the LCDIF
  • BYPASS_COUNT: In DOTCLK mode, must be set to 1
  • VSYNC_MODE : Set to 1 to indicate working in VSYNC interface mode
  • DOTCLK_MODE : Set to 1 to indicate working in DOTCLK interface mode
  •  INPUT_DATA_SWIZZLE: Input data byte swap setting
  • CSC_DATA_SWIZZLE: CSC data byte swap setting
  • LCD_DATABUS_WIDTH: If the LCD data bus width is 3, the bus width is 24 bits
  • WORD_LENGTH: input data format, that is, pixel data width
  • MASTER: Set to 1 to indicate that eLCDIF works in master mode
  • DATA_FORMAT_1 6_BIT: 16-bit pixel RGB565 /ARGB 555
  • DATA_FORMAT_18_BIT: 18-bit pixel RGB666
  • DATA_FORMAT_24_BIT : 24-bit pixels
  • RUN: eLCDIF interface operation control bit

3.2.2 LCDIF_CTRL1  

Only the BYTE_PACKING_FORMAT bit is used to determine which bytes of data are valid in the 32-bit data . The default value is 0xF (that is, all bytes are valid), and 0 means that all bytes are invalid.

3.2.3 LCDIF_TRANSFER_COUNT Register

Used to set the resolution of the connected RGB LCD screen

The upper 16 bits are V_COUNT, which is the vertical resolution of the LCD.

The lower 16 bits are H_COUNT, which is the horizontal resolution of the LCD

If the LCD resolution is 1024*600, then V_COUNT is 600, and H_COUNT is 1024.

3.2.4 LCDIF_VDCTRL0 Register

This register is the VSYNC and DOTCLK mode control register
0
 

LCDIF_VDCTRL0  

  •  – VSYNC: VSYNC signal direction control bit, 0 means output, 1 means input
  • – ENABLE_PRESENT: Data line enable bit, ie DE data line
  • – VSYNC_POL: VSYNC data line polarity setting bit, 0 means active low
  • – HSYNC_POL: HSYNC data line polarity setting bit, 0 means active low
  • – DOTCLK_POL: DOTCLK data line polarity setting bit, 0 means falling edge latch, rising edge capture data
  • – ENABLE_POL: ENABLE data line polarity setting bit, 0 means active low
  • – VSYNC_PERIOD_UNIT: VSYNC signal period unit, 0 means pixel clock as unit, 1 means horizontal line unit
  • – VSYNC_PULSE_WIDTH_UNIT: VSYNC signal pulse width unit, 0 means pixel clock as unit, 1 means horizontal line unit
  • – VSYNC_PULSE_WIDTH: VSPW parameter setting bit
     

3.2.5 LCDIF_VDCTRL1-4 Registers

  1. The LCDIF_VDCTRL1 register is the length between two VSYNC signals, that is VSPW+VBPD+HEIGHT+VFP. 
  2. LCDIF_VDCTRL2: VSYNC and DOTCLK mode control register 2, the upper 16 bits are used to set the HSYNC signal width, and the lower 16 bits are used to set the HSYNC total period
  3. LCDIF_VDCTRL3: VSYNC and DOTCLK Mode Control Register 3
  4. HORIZONTAL_WAIT_CNT : For DOTCLK mode, set the time between HSYNC signal generation and valid data generation, that is, HSPW+HBP

    VERTICAL_WAIT_CNT : For VSYNC mode, set the time between VSYNC signal generation and valid data generation, ie VSPW+VBP

  5. LCDIF_VDCTRL4: VSYNC and DOTCLK Mode Control Register 4 

  • SYNC_SIGNALS_ON (bit18): Synchronization signal enable bit, if set to 1, enable VSYNC, HSYNC,
  • DOTCLK these signals.
  • DOTCLK_H_VALID_DATA_CNT(bit15:0): Set the width of LCD, that is, the number of horizontal pixels 3. .

3.2.6 BUF memory register

  • LCDIF_CUR_BUF register: the current frame buffer, generally the first address of the video memory
  • LCDIF_NEXT_BUF register: the next frame buffer, generally the first address of the video memory 

For a detailed description of these registers, please refer to Section 34.6 on page 2165 of the "I.MX6ULL Reference Manual".

Four experiments 

In this chapter, we use the eLCDIF interface of I.MX6U to drive ALIENTEK
's ATK7016 screen. The configuration steps are as follows:
1. The IO used to initialize the LCD
must first be the IO used by the initialization LCD, and multiplex it as the eLCDIF interface IO.
2. Set the pixel clock of the LCD.
Consult the data sheet of the LCD screen used, or calculate the clock pixel by yourself, and then set the corresponding register of CCM
.
3. Configure eLCDIF interface
Set LCDIF registers CTRL, CTRL1, TRANSFER_COUNT, VDCTRL0~4, CUR_BUF and
NEXT_BUF. Set the corresponding parameters according to the LCD data sheet.
4. Write API functions
The purpose of driving the LCD screen is to display content, so it is necessary to write some basic API functions, such as drawing points, lines
, circles, string display functions, etc.

4.1 Code structure

The main files of the routine : five files: bsp_lcd.c, bsp_lcd.h, bsp_lcdapi.c, bsp_lcdapi.h and font.h.
bsp_lcd.c and bsp_lcd.h are LCD driver files, bsp_lcdapi.c and bsp_lcdapi.h are LCD API operation function files, font.h is a character set dot matrix data array file

4.2 Code Analysis

4.2.1 LCD initialization

1 void lcd_init(void); 

The punctual atomic development board first reads the screen ID    Figure 1.2

/*
 * 读取屏幕ID,
 * 描述:LCD_DATA23=R7(M0);LCD_DATA15=G7(M1);LCD_DATA07=B7(M2);
 * 		M2:M1:M0
 *		0 :0 :0	//4.3寸480*272 RGB屏,ID=0X4342
 *		0 :0 :1	//7寸800*480 RGB屏,ID=0X7084
 *	 	0 :1 :0	//7寸1024*600 RGB屏,ID=0X7016
 *  	1 :0 :1	//10.1寸1280*800,RGB屏,ID=0X1018
 *		1 :0 :0	//4.3寸800*480 RGB屏,ID=0X4384
 * @param 		: 无
 * @return 		: 屏幕ID
 */
unsigned short lcd_read_panelid(void)
{
	unsigned char idx = 0;

	/* 配置屏幕ID信号线 */
	IOMUXC_SetPinMux(IOMUXC_LCD_VSYNC_GPIO3_IO03, 0);
	IOMUXC_SetPinConfig(IOMUXC_LCD_VSYNC_GPIO3_IO03, 0X10B0);

	/* 打开模拟开关 */
	gpio_pin_config_t idio_config;
	idio_config.direction = kGPIO_DigitalOutput;
	idio_config.outputLogic = 1;
	gpio_init(GPIO3, 3, &idio_config);

	/* 读取ID值,设置G7 B7 R7为输入 */
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA07_GPIO3_IO12, 0);		/* B7(M2) */
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA15_GPIO3_IO20, 0);		/* G7(M1) */
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA23_GPIO3_IO28, 0);		/* R7(M0) */

    //电器属性 输入
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA07_GPIO3_IO12, 0xF080);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA15_GPIO3_IO20, 0xF080);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA23_GPIO3_IO28, 0xF080);  

	idio_config.direction = kGPIO_DigitalInput;
	gpio_init(GPIO3, 12, &idio_config);
	gpio_init(GPIO3, 20, &idio_config);
	gpio_init(GPIO3, 28, &idio_config);

	idx = (unsigned char)gpio_pinread(GPIO3, 28); 	/* 读取M0 */
	idx |= (unsigned char)gpio_pinread(GPIO3, 20) << 1;	/* 读取M1 */
	idx |= (unsigned char)gpio_pinread(GPIO3, 12) << 2;	/* 读取M2 */

	if(idx==0)return ATK4342;		//4.3寸屏,480*272分辨率
	else if(idx==1)return ATK7084;	//7寸屏,800*480分辨率
	else if(idx==2)return ATK7016;	//7寸屏,1024*600分辨率
	else if(idx==4)return ATK4384;	//4寸屏,800*480分辨率
	else if(idx==5)return ATK1018;	//10.1寸屏,1280*800分辨率		
	else if(idx==7)return ATKVGA;   //VGA模块,1366*768分辨率
	else return 0;

}

2 Define the LCD structure


/* 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 */
};

3 LCD gpio initializes multiplexing electrical characteristics

/* 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);

Property Settings
 

/* 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引脚 		*/

4 Turn on the backlight or the screen is black

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

5 Soft reset LCD end reset 

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

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

6 Set the screen framebuffer, timing, pixel format, parameters, backlight and pixel clock clock frequency refer to the corresponding screen  2.2.3 pixel clock

//Resolution vsync signal width, frame sync signal back porch, front porch, Hsync signal width, horizontal back porch, front porch

if(lcdid == ATK4342) {
        //分辨率 vsync 信号宽度 、帧同步信号后肩 、前肩、Hsync 信号宽度、水平后肩、前肩
		tftlcd_dev.height = 272;	
		tftlcd_dev.width = 480;
		tftlcd_dev.vspw = 1;
		tftlcd_dev.vbpd = 8;
		tftlcd_dev.vfpd = 8;
		tftlcd_dev.hspw = 1;
		tftlcd_dev.hbpd = 40;
		tftlcd_dev.hfpd = 5; 	
		lcdclk_init(27, 8, 8);	/* 初始化LCD时钟 10.1MHz */
	} else if(lcdid == ATK4384) {
		tftlcd_dev.height = 480;	
		tftlcd_dev.width = 800;
		tftlcd_dev.vspw = 3;
		tftlcd_dev.vbpd = 32;
		tftlcd_dev.vfpd = 13;
		tftlcd_dev.hspw = 48;
		tftlcd_dev.hbpd = 88;
		tftlcd_dev.hfpd = 40;
		lcdclk_init(42, 4, 8);	/* 初始化LCD时钟 31.5MHz */
	} else if(lcdid == ATK7084) {
		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 */
	} else if(lcdid == ATK7016) {
		tftlcd_dev.height = 600;	
		tftlcd_dev.width = 1024;
		tftlcd_dev.vspw = 3;
		tftlcd_dev.vbpd = 20;
		tftlcd_dev.vfpd = 12;
		tftlcd_dev.hspw = 20;
		tftlcd_dev.hbpd = 140;
		tftlcd_dev.hfpd = 160;
		lcdclk_init(32, 3, 5);	/* 初始化LCD时钟 51.2MHz */
	} else if(lcdid == ATK1018) {
		tftlcd_dev.height = 800;	
		tftlcd_dev.width = 1280;
		tftlcd_dev.vspw = 3;
		tftlcd_dev.vbpd = 10;
		tftlcd_dev.vfpd = 10;
		tftlcd_dev.hspw = 10;
		tftlcd_dev.hbpd = 80;
		tftlcd_dev.hfpd = 70;
		lcdclk_init(35, 3, 5);	/* 初始化LCD时钟 56MHz */
	} else if(lcdid == ATKVGA) {  
		tftlcd_dev.height = 768;	
		tftlcd_dev.width = 1366;
		tftlcd_dev.vspw = 3;
		tftlcd_dev.vbpd = 24;
		tftlcd_dev.vfpd = 3;
		tftlcd_dev.hspw = 143;
		tftlcd_dev.hbpd = 213;
		tftlcd_dev.hfpd = 70;
		lcdclk_init(32, 3, 3);	/* 初始化LCD时钟 85MHz */
	}
	tftlcd_dev.pixsize = 4;				/* ARGB8888模式,每个像素4字节 */
	tftlcd_dev.framebuffer = LCD_FRAMEBUF_ADDR;	
	tftlcd_dev.backcolor = LCD_WHITE;	/* 背景色为白色 */
	tftlcd_dev.forecolor = LCD_BLACK;	/* 前景色为黑色 */

clk clock source lcdclk_init 2.2.3 Pixel clock multi-level frequency division

/*
 * @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时钟 */
}

7 Related register settings

/* 初始化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;

8 Enable LCD and clear screen


	lcd_enable();			/* 使能LCD 	*/
	delayms(10);
	lcd_clear(LCD_WHITE);	/* 清屏 		*/
/*
 * @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;
	}		
}

4.2.2 LCD Api

To read and write pixels is to write the corresponding address of framebuffer offset

/*
 * @description		: 画点函数 
 * @param - x		: x轴坐标
 * @param - y		: y轴坐标
 * @param - color	: 颜色值
 * @return 			: 无
 */
inline 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 			: 读取到的指定点的颜色值
 */
inline 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));
}

populate api

/*
 * @description		: 以指定的颜色填充一块矩形
 * @param - x0		: 矩形起始点坐标X轴
 * @param - y0		: 矩形起始点坐标Y轴
 * @param - x1		: 矩形终止点坐标X轴
 * @param - y1		: 矩形终止点坐标Y轴
 * @param - color	: 要填充的颜色
 * @return 			: 读取到的指定点的颜色值
 */
void lcd_fill(unsigned    short x0, unsigned short y0, 
                 unsigned short x1, unsigned short y1, unsigned int color)
{ 
    unsigned short x, y;

	if(x0 < 0) x0 = 0;
	if(y0 < 0) y0 = 0;
	if(x1 >= tftlcd_dev.width) x1 = tftlcd_dev.width - 1;
	if(y1 >= tftlcd_dev.height) y1 = tftlcd_dev.height - 1;
	
    for(y = y0; y <= y1; y++)
    {
        for(x = x0; x <= x1; x++)
			lcd_drawpoint(x, y, color);
    }
}

LCD display font 

/***************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名	: 	 bsp_lcdapi.c
作者	   : 左忠凯
版本	   : V1.0
描述	   : LCD API函数文件。
其他	   : 无
论坛 	   : www.wtmembed.com
日志	   : 初版V1.0 2019/3/18 左忠凯创建
***************************************************************/
#include "bsp_lcdapi.h"
#include "font.h" 

/*
 * @description		: 画线函数
 * @param - x1		: 线起始点坐标X轴
 * @param - y1		: 线起始点坐标Y轴
 * @param - x2		: 线终止点坐标X轴
 * @param - y2		: 线终止点坐标Y轴
 * @return 			: 无
 */ 
void lcd_drawline(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2)
{
	u16 t; 
	int xerr = 0, yerr = 0, delta_x, delta_y, distance; 
	int incx, incy, uRow, uCol; 
	delta_x = x2 - x1; 					/* 计算坐标增量 */
	delta_y = y2 - y1; 
	uRow = x1; 
	uCol = y1; 
	if(delta_x > 0) 					/* 设置单步方向 */ 
		incx = 1;
	else if(delta_x==0)					/* 垂直线 */
		incx = 0;		
	else 
	{
		incx = -1;
		delta_x = -delta_x;
	} 
	if(delta_y>0)
		incy=1; 
	else if(delta_y == 0)				/* 水平线 */
		incy=0;
	else
	{
		incy = -1;
		delta_y = -delta_y;
	} 
	if( delta_x > delta_y)				/*选取基本增量坐标轴  */
		distance = delta_x; 
	else 
		distance = delta_y; 
	for(t = 0; t <= distance+1; t++ )	/* 画线输出 */
	{  

		lcd_drawpoint(uRow, uCol, tftlcd_dev.forecolor);/* 画点 */
		xerr += delta_x ; 
		yerr += delta_y ; 
		if(xerr > distance) 
		{ 
			xerr -= distance; 
			uRow += incx; 
		} 
		if(yerr > distance) 
		{ 
			yerr -= distance; 
			uCol += incy; 
		} 
	}  
}   

/*
 * @description	: 画矩形函数
 * @param - x1	: 矩形坐上角坐标X轴
 * @param - y1	: 矩形坐上角坐标Y轴
 * @param - x2	: 矩形右下角坐标X轴
 * @param - y2	: 矩形右下角坐标Y轴
 * @return 		: 无
 */
void lcd_draw_rectangle(unsigned short x1, unsigned short y1, unsigned short x2, unsigned short y2)
{
	lcd_drawline(x1, y1, x2, y1);
	lcd_drawline(x1, y1, x1, y2);
	lcd_drawline(x1, y2, x2, y2);
	lcd_drawline(x2, y1, x2, y2);
}

/*
 * @description	: 在指定位置画一个指定大小的圆
 * @param - x0	: 圆心坐标X轴
 * @param - y0	: 圆心坐标Y轴
 * @param - y2	: 圆形半径
 * @return 		: 无
 */
void lcd_draw_Circle(unsigned short x0,unsigned short y0,unsigned char r)
{
    int mx = x0, my = y0;
    int x = 0, y = r;

    int d = 1 - r;   
    while(y > x)    	/* y>x即第一象限的第1区八分圆 */
    {
        lcd_drawpoint(x  + mx, y  + my, tftlcd_dev.forecolor);
        lcd_drawpoint(y  + mx, x  + my, tftlcd_dev.forecolor);
        lcd_drawpoint(-x + mx, y  + my, tftlcd_dev.forecolor);
        lcd_drawpoint(-y + mx, x  + my, tftlcd_dev.forecolor);

        lcd_drawpoint(-x + mx, -y + my, tftlcd_dev.forecolor);
        lcd_drawpoint(-y + mx, -x + my, tftlcd_dev.forecolor);
        lcd_drawpoint(x  + mx, -y + my, tftlcd_dev.forecolor);
        lcd_drawpoint(y  + mx, -x + my, tftlcd_dev.forecolor);
        if( d < 0)
        {
            d = d + 2 * x + 3;
        }
        else
        {
            d= d + 2 * (x - y) + 5;
            y--;
        }
        x++;
    }
}

/*
 * @description	: 在指定位置显示一个字符
 * @param - x	: 起始坐标X轴
 * @param - y	: 起始坐标Y轴
 * @param - num	: 显示字符
 * @param - size: 字体大小, 可选12/16/24/32
 * @param - mode: 叠加方式(1)还是非叠加方式(0)
 * @return 		: 无
 */
void lcd_showchar(unsigned     short x, unsigned short y,
				      unsigned char num, unsigned char size, 
				      unsigned char mode)
{  							  
    unsigned char  temp, t1, t;
	unsigned short y0 = y;
	unsigned char csize = (size / 8+ ((size % 8) ? 1 : 0)) * (size / 2);	/* 得到字体一个字符对应点阵集所占的字节数	 */	
 	num = num - ' ';  	/*得到偏移后的值(ASCII字库是从空格开始取模,所以-' '就是对应字符的字库)  */
	for(t = 0; t < csize; t++)
	{   
		if(size == 12) temp = asc2_1206[num][t]; 		/* 调用1206字体 */
		else if(size == 16)temp = asc2_1608[num][t];	/* 调用1608字体 */
		else if(size == 24)temp = asc2_2412[num][t];	/* 调用2412字体 */
		else if(size == 32)temp = asc2_3216[num][t];	/* 调用3216字体 */
		else return;									/* 没有的字库 		*/
		for(t1 = 0; t1 < 8; t1++)
		{			    
			if(temp & 0x80)lcd_drawpoint(x, y, tftlcd_dev.forecolor);
			else if(mode==0)lcd_drawpoint(x, y, tftlcd_dev.backcolor);
			temp <<= 1;
			y++;
			if(y >= tftlcd_dev.height) return;			/* 超区域了 */	
			if((y - y0) == size)
			{
				y = y0;
				x++;
				if(x >= tftlcd_dev.width) return;		/* 超区域了 */
				break;
			}
		}  	 
	}  		    	   	 	  
} 

/*
 * @description	: 计算m的n次方
 * @param - m	: 要计算的值
 * @param - n	: n次方
 * @return 		: m^n次方.
 */
unsigned int lcd_pow(unsigned char m,unsigned char n)
{
	unsigned int result = 1;	 
	while(n--) result *= m;    
	return result;
}

/*
 * @description	: 显示指定的数字,高位为0的话不显示
 * @param - x	: 起始坐标点X轴。
 * @param - y	: 起始坐标点Y轴。
 * @param - num	: 数值(0~999999999)。
 * @param - len : 数字位数。
 * @param - size: 字体大小
 * @return 		: 无
 */
void lcd_shownum(unsigned     short x, 
					 unsigned short y, 
					 unsigned int num, 
					 unsigned char len,
					 unsigned char size)
{         	
	unsigned char  t, temp;
	unsigned char  enshow = 0;						   
	for(t = 0; t < len; t++)
	{
		temp = (num / lcd_pow(10, len - t - 1)) % 10;
		if(enshow == 0 && t < (len - 1))
		{
			if(temp == 0)
			{
				lcd_showchar(x + (size / 2) * t, y, ' ', size, 0);
				continue;
			}else enshow = 1; 	 
		}
	 	lcd_showchar(x + (size / 2) * t, y, temp + '0', size, 0); 
	}
} 

/*
 * @description		: 显示指定的数字,高位为0,还是显示
 * @param - x	 	: 起始坐标点X轴。
 * @param - y	 	: 起始坐标点Y轴。
 * @param - num		: 数值(0~999999999)。
 * @param - len 	: 数字位数。
 * @param - size	: 字体大小
 * @param - mode	: [7]:0,不填充;1,填充0.
 * 					  [6:1]:保留
 *					  [0]:0,非叠加显示;1,叠加显示.
 * @return 	 		: 无
 */
void lcd_showxnum(unsigned     short x, unsigned short y, 
					  unsigned int num, unsigned char len, 
					  unsigned char size, unsigned char mode)
{  
	unsigned char t, temp;
	unsigned char enshow = 0;						   
	for(t = 0; t < len; t++)
	{
		temp = (num / lcd_pow(10, len - t- 1)) % 10;
		if(enshow == 0 && t < (len - 1))
		{
			if(temp == 0)
			{
				if(mode & 0X80) lcd_showchar(x + (size / 2) * t, y, '0', size, mode & 0X01);  
				else  lcd_showchar(x + (size / 2) * t, y , ' ', size, mode & 0X01);  
 				continue;
			}else enshow=1; 
		 	 
		}
	 	lcd_showchar( x + (size / 2) * t, y, temp + '0' , size , mode & 0X01); 
	}
} 

/*
 * @description		: 显示一串字符串
 * @param - x		: 起始坐标点X轴。
 * @param - y		: 起始坐标点Y轴。
 * @param - width 	: 字符串显示区域长度
 * @param - height	: 字符串显示区域高度
 * @param - size	: 字体大小
 * @param - p		: 要显示的字符串首地址
 * @return 			: 无
 */
void lcd_show_string(unsigned short x,unsigned short y,
						  unsigned short width,unsigned short height,
						  unsigned char size,char *p)
{         
	unsigned char x0 = x;
	width += x;
	height += y;
    while((*p <= '~') &&(*p >= ' '))		/* 判断是不是非法字符! */ 
    {       
        if(x >= width) {x = x0; y += size;}
        if(y >= height) break;				/* 退出 */
        lcd_showchar(x, y, *p , size, 0);
        x += size / 2;
        p++;
    }  
}


4.2.3 Test verification display

/**************************************************************
Copyright © zuozhongkai Co., Ltd. 1998-2019. All rights reserved.
文件名	: 	 mian.c
作者	   : 左忠凯
版本	   : V1.0
描述	   : I.MX6U开发板裸机实验16 LCD液晶屏实验
其他	   : 本实验学习如何在I.MX6U上驱动RGB LCD液晶屏幕,I.MX6U有个
 		 ELCDIF接口,通过此接口可以连接一个RGB LCD液晶屏。
论坛 	   : www.wtmembed.com
日志	   : 初版V1.0 2019/1/15 左忠凯创建
**************************************************************/
#include "bsp_clk.h"
#include "bsp_delay.h"
#include "bsp_led.h"
#include "bsp_beep.h"
#include "bsp_key.h"
#include "bsp_int.h"
#include "bsp_uart.h"
#include "stdio.h"
#include "bsp_lcd.h"
#include "bsp_lcdapi.h"


/* 背景颜色索引 */
unsigned int backcolor[10] = {
	LCD_BLUE, 		LCD_GREEN, 		LCD_RED, 	LCD_CYAN, 	LCD_YELLOW, 
	LCD_LIGHTBLUE, 	LCD_DARKBLUE, 	LCD_WHITE, 	LCD_BLACK, 	LCD_ORANGE

}; 
	

/*
 * @description	: main函数
 * @param 		: 无
 * @return 		: 无
 */
int main(void)
{
	unsigned char index = 0;
	unsigned char state = OFF;

	int_init(); 				/* 初始化中断(一定要最先调用!) */
	imx6u_clkinit();			/* 初始化系统时钟 			*/
	delay_init();				/* 初始化延时 			*/
	clk_enable();				/* 使能所有的时钟 			*/
	led_init();					/* 初始化led 			*/
	beep_init();				/* 初始化beep	 		*/
	uart_init();				/* 初始化串口,波特率115200 */
	lcd_init();					/* 初始化LCD 			*/

	tftlcd_dev.forecolor = LCD_RED;	  
	while(1)				
	{	
		lcd_clear(backcolor[index]);
		delayms(1); 	  
		lcd_show_string(10, 40, 260, 32, 32,(char*)"ALPHA IMX6U"); 	
		lcd_show_string(10, 80, 240, 24, 24,(char*)"RGBLCD TEST");
		lcd_show_string(10, 110, 240, 16, 16,(char*)"ATOM@ALIENTEK");      					 
		lcd_show_string(10, 130, 240, 12, 12,(char*)"2019/8/14");	      					 
	    index++;
		if(index == 10)
			index = 0;      
		state = !state;
		led_switch(LED0,state);
		delayms(1000);

#if 0
		index++;
		if(index == 10)
			index = 0;
		lcd_fill(0, 300, 1023, 599, backcolor[index]);
		lcd_show_string(800,10,240,32,32,(char*)"INDEX=");  /*显示字符串				  */
		lcd_shownum(896,10, index, 2, 32); 					/* 显示数字,叠加显示	*/
		
		state = !state;
		led_switch(LED0,state);
		delayms(1000);	/* 延时一秒	*/
#endif
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/TyearLin/article/details/131524815