[MCU] 【兆易GD32H759I-EVAL】LCD测试

TL-LED   2024-5-12 00:51 楼主

这篇测试下开发板上的LCD显示屏,显示缓存使用上篇测试的SDRAM存储器。

 

一、电路硬件部分 

 

LCD显示屏硬件电路图部分

看到显示部分电路有很多跳线帽,是显示屏引脚复用功能选择。板卡默认调试是显示屏功能。

 

001.jpg

 

二、TFT-LCD (TLI)接口介绍

 

2.1、简介

TLI(TFT-LCD接口)连接同步的LCD接口,并且为无源LCD显示屏提供像素数据,时钟以及时序信号。它支持不同的完全可编程的时序参数显示。一个内嵌的DMA不断的从系统存储器搬移数据到TLI然后输出到外部的LCD显示。 TLI支持两个独立的显示层,并支持层窗口和层混叠功能。

 

2.2、特点

 每像素最多24位并行数据输出;
 支持高达2048*2048的分辨率;
 完全可编程的时序参数;
 内嵌DMA处理像素数据拷贝;
 带有窗口和混合功能的两个独立的层;
 支持多种像素格式: ARGB8888, RGB888, RGB565等;
 支持CLUT(颜色查找表)和色键格式;
 像素低位的抖动操作。

 

2.3、结构框图

002.jpg

 

2.4、显示时序图

003.jpg

2.5、混合过程框图

TLI每层都支持窗口功能以及两层的混合功能,可将两层混合成一帧。

004.jpg

 

三、程序部分

 

3.1、lcd.c

#include "gd32h7xx.h"
#include "lcd/tli_lcd.h"
#include "exmc/exmc_sdram.h"
#include "lcd/font.h"

#define BACK_FRAME_START_ADDR SDRAM_DEVICE0_ADDR
#define FORE_FRAME_START_ADDR ((u32)(BACK_FRAME_START_ADDR + (LCD_PIXEL_WIDTH + 1) * LCD_PIXEL_HEIGHT * 2))

static u16 s_arrBackgroundFrame[(LCD_PIXEL_WIDTH + 1) * LCD_PIXEL_HEIGHT] __attribute__((at(BACK_FRAME_START_ADDR)));
static u16 s_arrForegroundFrame[(LCD_PIXEL_WIDTH + 1) * LCD_PIXEL_HEIGHT] __attribute__((at(FORE_FRAME_START_ADDR)));

StructTLILCDDev g_structTLILCDDev;

//设置层窗口
void LCDLayerWindowSet(EnumTLILCDLayer layer, u32 x, u32 y, u32 width, u32 height)
{
  tli_layer_parameter_struct  tli_layer_init_struct; 
  u32 swap, x0, y0;
  
  tli_layer_struct_para_init(&tli_layer_init_struct);

  if(LCD_SCREEN_VERTICAL == g_structTLILCDDev.dir)
  {
    x0 = x;
    y0 = y + height - 1;
    y = x0;
    x = LCD_PIXEL_WIDTH - 1 - y0;
    if(x >= LCD_PIXEL_WIDTH){return;}
    if(y >= LCD_PIXEL_HEIGHT){return;}

    swap = width;
    width = height;
    height = swap;
  }

  if((x + width) > LCD_PIXEL_WIDTH)
  {
    width = LCD_PIXEL_WIDTH - x;
  }

  if((y + height) > LCD_PIXEL_HEIGHT)
  {
    height = LCD_PIXEL_HEIGHT - y;
  }

  if(LCD_LAYER_BACKGROUND == layer)
  {
    tli_layer_init_struct.layer_window_leftpos    = (x + HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH);             
    tli_layer_init_struct.layer_window_rightpos   = (x + width + HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH - 1); 
    tli_layer_init_struct.layer_window_toppos     = (y + VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH);                 
    tli_layer_init_struct.layer_window_bottompos  = (y + height + VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH - 1);    
    tli_layer_init_struct.layer_ppf               = LAYER_PPF_RGB565;          
    tli_layer_init_struct.layer_sa                = 0xFF;                      
    tli_layer_init_struct.layer_default_blue      = 0xFF;                      
    tli_layer_init_struct.layer_default_green     = 0xFF;                      
    tli_layer_init_struct.layer_default_red       = 0xFF;                      
    tli_layer_init_struct.layer_default_alpha     = 0xFF;                      
    tli_layer_init_struct.layer_acf1              = LAYER_ACF1_PASA;           
    tli_layer_init_struct.layer_acf2              = LAYER_ACF2_PASA;           
    tli_layer_init_struct.layer_frame_bufaddr     = (u32)s_arrBackgroundFrame; 
    tli_layer_init_struct.layer_frame_line_length = ((width * 2) + 3);         
    tli_layer_init_struct.layer_frame_buf_stride_offset = (width * 2);         
    tli_layer_init_struct.layer_frame_total_line_number = height;              
    tli_layer_init(LAYER0, &tli_layer_init_struct); 
    tli_color_key_disable(LAYER0);                  
    tli_lut_disable(LAYER0);                        

    if(LCD_SCREEN_HORIZONTAL == g_structTLILCDDev.dir)
    {
      g_structTLILCDDev.width[LCD_LAYER_BACKGROUND] = width;
      g_structTLILCDDev.height[LCD_LAYER_BACKGROUND] = height;
    }
    else if(LCD_SCREEN_VERTICAL == g_structTLILCDDev.dir)
    {
      g_structTLILCDDev.width[LCD_LAYER_BACKGROUND] = height;
      g_structTLILCDDev.height[LCD_LAYER_BACKGROUND] = width;
    }
  }
  
  else if(LCD_LAYER_FOREGROUND == layer)
  {
    tli_layer_init_struct.layer_window_leftpos    = (x + HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH);            
    tli_layer_init_struct.layer_window_rightpos   = (x + width + HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH - 1); 
    tli_layer_init_struct.layer_window_toppos     = (y + VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH);                
    tli_layer_init_struct.layer_window_bottompos  = (y + height + VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH - 1);    
    tli_layer_init_struct.layer_ppf               = LAYER_PPF_RGB565;          
    tli_layer_init_struct.layer_sa                = 0xFF;                      
    tli_layer_init_struct.layer_default_blue      = 0xFF;                      
    tli_layer_init_struct.layer_default_green     = 0xFF;                      
    tli_layer_init_struct.layer_default_red       = 0xFF;                      
    tli_layer_init_struct.layer_default_alpha     = 0x00;                      
    tli_layer_init_struct.layer_acf1              = LAYER_ACF1_PASA;           
    tli_layer_init_struct.layer_acf2              = LAYER_ACF2_PASA;           
    tli_layer_init_struct.layer_frame_bufaddr     = (u32)s_arrForegroundFrame; 
    tli_layer_init_struct.layer_frame_line_length = ((width * 2) + 3);         
    tli_layer_init_struct.layer_frame_buf_stride_offset = (width * 2);         
    tli_layer_init_struct.layer_frame_total_line_number = height;              
    tli_layer_init(LAYER1, &tli_layer_init_struct); 
    tli_color_key_disable(LAYER1);                  
    tli_lut_disable(LAYER1);                        

    if(LCD_SCREEN_HORIZONTAL == g_structTLILCDDev.dir)
    {
      g_structTLILCDDev.width[LCD_LAYER_FOREGROUND] = width;
      g_structTLILCDDev.height[LCD_LAYER_FOREGROUND] = height;
    }
    else if(LCD_SCREEN_VERTICAL == g_structTLILCDDev.dir)
    {
      g_structTLILCDDev.width[LCD_LAYER_FOREGROUND] = height;
      g_structTLILCDDev.height[LCD_LAYER_FOREGROUND] = width;
    }
  }

  tli_reload_config(TLI_REQUEST_RELOAD_EN);
}

//使能背景或前景层
void LCDLayerEnable(EnumTLILCDLayer layer)
{

  if(LCD_LAYER_BACKGROUND == layer)
  {
    tli_layer_enable(LAYER0);
  }
  else if(LCD_LAYER_FOREGROUND == layer)
  {
    tli_layer_enable(LAYER1);
  }
  tli_reload_config(TLI_REQUEST_RELOAD_EN);
}

//禁用背景或前景层
void LCDLayerDisable(EnumTLILCDLayer layer)
{
  if(LCD_LAYER_BACKGROUND == layer)
  {
    tli_layer_disable(LAYER0);
  }
  else if(LCD_LAYER_FOREGROUND == layer)
  {
    tli_layer_disable(LAYER1);
  }
  tli_reload_config(TLI_REQUEST_RELOAD_EN);
}

//切换层
void LCDLayerSwitch(EnumTLILCDLayer layer)
{
  if(LCD_LAYER_BACKGROUND == layer)
  {
    g_structTLILCDDev.frameBuf = s_arrBackgroundFrame;
    g_structTLILCDDev.currentLayer = LCD_LAYER_BACKGROUND;
  }
  else
  {
    g_structTLILCDDev.frameBuf = s_arrForegroundFrame;
    g_structTLILCDDev.currentLayer = LCD_LAYER_FOREGROUND;
  }
}
//设置当前层的透明度
void LCDTransparencySet(EnumTLILCDLayer layer, u8 trans)
{
  if (LCD_LAYER_BACKGROUND == layer)
  {
    TLI_LXSA(LAYER0) &= ~(TLI_LXSA_SA);
    TLI_LXSA(LAYER0) = trans;
  }
  else
  {
    TLI_LXSA(LAYER1) &= ~(TLI_LXSA_SA);
    TLI_LXSA(LAYER1) = trans;
  }
  tli_reload_config(TLI_REQUEST_RELOAD_EN);
}

//开启LCD显示
void LCDDisplayOn(void)
{
  tli_enable();
}

//关闭LCD显示
void LCDDisplayOff(void)
{
  tli_disable();
}

//等待LCD行传输空闲
void LCDWaitHIdle(void)
{
  while(RESET == tli_flag_get(TLI_FLAG_HDE));
  while(SET == tli_flag_get(TLI_FLAG_HDE));
}

//等待LCD场传输空闲
void LCDWaitVIdle(void)
{
  while(RESET == tli_flag_get(TLI_FLAG_VDE));
  while(SET == tli_flag_get(TLI_FLAG_VDE));
}

//设置LCD显示方向
void LCDDisplayDir(EnumTLILCDDir dir)
{
  u32 swap;

  if(g_structTLILCDDev.dir != dir)
  {
    g_structTLILCDDev.dir = dir;

    swap = g_structTLILCDDev.width[LCD_LAYER_BACKGROUND];
    g_structTLILCDDev.width[LCD_LAYER_BACKGROUND] = g_structTLILCDDev.height[LCD_LAYER_BACKGROUND];
    g_structTLILCDDev.height[LCD_LAYER_BACKGROUND] = swap;

    swap = g_structTLILCDDev.width[LCD_LAYER_FOREGROUND];
    g_structTLILCDDev.width[LCD_LAYER_FOREGROUND] = g_structTLILCDDev.height[LCD_LAYER_FOREGROUND];
    g_structTLILCDDev.height[LCD_LAYER_FOREGROUND] = swap;
  }
}

//清屏
void LCDClear(u32 color)
{
  ipa_destination_parameter_struct  ipa_destination_init_struct;

  u8 red, green, blue;

  RGB565ToRGB888A(color, &red, &green, &blue);

  rcu_periph_clock_enable(RCU_IPA);

  ipa_deinit();

  ipa_pixel_format_convert_mode_set(IPA_FILL_UP_DE); 

  //设置目标图像参数
  ipa_destination_struct_para_init(&ipa_destination_init_struct);
  ipa_destination_init_struct.destination_pf       = IPA_DPF_RGB565;                   
  ipa_destination_init_struct.destination_memaddr  = (u32)g_structTLILCDDev.frameBuf;  
  ipa_destination_init_struct.destination_lineoff  = 0;                 
  ipa_destination_init_struct.destination_prealpha = 0xFF;              
  ipa_destination_init_struct.destination_prered   = red;               
  ipa_destination_init_struct.destination_pregreen = green;             
  ipa_destination_init_struct.destination_preblue  = blue;              
  ipa_destination_init_struct.image_width          = LCD_PIXEL_WIDTH;  
  ipa_destination_init_struct.image_height         = LCD_PIXEL_HEIGHT; 
  ipa_destination_init(&ipa_destination_init_struct); 

  // //使能IPA内部定时器
  // ipa_interval_clock_num_config(0);
  // ipa_inter_timer_config(IPA_INTER_TIMER_ENABLE);

  ipa_transfer_enable();

  while(RESET == ipa_interrupt_flag_get(IPA_INT_FLAG_FTF));

  ipa_interrupt_flag_clear(IPA_INT_FLAG_FTF);

  ipa_deinit();
}

//画点
void LCDDrawPoint(u32 x, u32 y, u32 color)
{
  u32 width, height;

  width = g_structTLILCDDev.width[g_structTLILCDDev.currentLayer];
  height = g_structTLILCDDev.height[g_structTLILCDDev.currentLayer];

  if(x >= width || y >= height)
  {
    return;
  }

  if(LCD_SCREEN_HORIZONTAL == g_structTLILCDDev.dir) 
  {
    g_structTLILCDDev.frameBuf[width * y + x] = color;
  }
  else
  {
    g_structTLILCDDev.frameBuf[height * x + (height - 1 - y)] = color;
  }
}

//读点
u32 LCDReadPoint(u32 x, u32 y)
{
  u32 width, height;

  width = g_structTLILCDDev.width[g_structTLILCDDev.currentLayer];
  height = g_structTLILCDDev.height[g_structTLILCDDev.currentLayer];

  if(x >= width || y >= height)
  {
    return 0;
  }

  if(LCD_SCREEN_HORIZONTAL == g_structTLILCDDev.dir) 
  {
    return g_structTLILCDDev.frameBuf[width * y + x];
  }
  else
  {
    return g_structTLILCDDev.frameBuf[height * x + (height - 1 - y)];
  }
}

//LCD填充
void LCDFill(u32 x, u32 y, u32 width, u32 height, u32 color)
{
  ipa_destination_parameter_struct  ipa_destination_init_struct;  
  u32 destStartAddr;        
  u32 phyWidth, phyHeight;  
  u32 phyX, phyY;           
  u32 lineOff;              
  u32 swap;                 
  u8  red, green, blue;    
  u32 x1, y1, x2, y2, color1, color2;

  if(LCD_SCREEN_HORIZONTAL == g_structTLILCDDev.dir)
  {
    phyWidth = g_structTLILCDDev.width[g_structTLILCDDev.currentLayer];
    phyHeight = g_structTLILCDDev.height[g_structTLILCDDev.currentLayer];
    phyX = x;
    phyY = y;
  }
  else if(LCD_SCREEN_VERTICAL == g_structTLILCDDev.dir)
  {
    phyWidth = g_structTLILCDDev.width[g_structTLILCDDev.currentLayer];
    phyHeight = g_structTLILCDDev.height[g_structTLILCDDev.currentLayer];

    swap = phyWidth;
    phyWidth = phyHeight;
    phyHeight = swap;

    swap = width;
    width = height;
    height = swap;

    phyX = phyWidth - y - width;
    phyY = x;
  }

  if((phyX + width) > LCD_PIXEL_WIDTH)
  {
    width = LCD_PIXEL_WIDTH - phyX;
  }
  if((phyY + height) > LCD_PIXEL_HEIGHT)
  {
    height = LCD_PIXEL_HEIGHT - phyY;
  }

  if(LCD_SCREEN_HORIZONTAL == g_structTLILCDDev.dir)
  {
    x1 = phyX;
    x2 = x1 + 1;
    y1 = phyY + height;
    y2 = y1;
  }
  else if(LCD_SCREEN_VERTICAL == g_structTLILCDDev.dir)
  {
    x1 = x + height;
    x2 = x1;
    y1 = y + width - 1;
    y2 = y1 - 1;
  }
  color1 = LCDReadPoint(x1, y1);
  color2 = LCDReadPoint(x2, y2);

  destStartAddr = (u32)g_structTLILCDDev.frameBuf + g_structTLILCDDev.pixelSize * (phyWidth * phyY + phyX);

  lineOff = phyWidth - width;

  RGB565ToRGB888A(color, &red, &green, &blue);

  rcu_periph_clock_enable(RCU_IPA);

  ipa_deinit();

  ipa_pixel_format_convert_mode_set(IPA_FILL_UP_DE); 

  //设置目标图像参数
  ipa_destination_struct_para_init(&ipa_destination_init_struct);
  ipa_destination_init_struct.destination_pf       = IPA_DPF_RGB565;  
  ipa_destination_init_struct.destination_memaddr  = destStartAddr;   
  ipa_destination_init_struct.destination_lineoff  = lineOff;         
  ipa_destination_init_struct.destination_prealpha = 0xFF;            
  ipa_destination_init_struct.destination_prered   = red;             
  ipa_destination_init_struct.destination_pregreen = green;           
  ipa_destination_init_struct.destination_preblue  = blue;            
  ipa_destination_init_struct.image_width          = width;           
  ipa_destination_init_struct.image_height         = height;          
  ipa_destination_init(&ipa_destination_init_struct);                 

  // //使能IPA内部定时器
  // ipa_interval_clock_num_config(0);
  // ipa_inter_timer_config(IPA_INTER_TIMER_ENABLE);

  ipa_transfer_enable();

  while(RESET == ipa_interrupt_flag_get(IPA_INT_FLAG_FTF));

  ipa_interrupt_flag_clear(IPA_INT_FLAG_FTF);

  ipa_deinit();

  LCDDrawPoint(x1, y1, color1);
  LCDDrawPoint(x2, y2, color2);
}

//LCD填充
void LCDFillPixel(u32 x0, u32 y0, u32 x1, u32 y1, u32 color)
{
  u32 swap, width, height;

  if(x0 > x1)
  {
    swap = x0;
    x0 = x1;
    x1 = swap;
  }
	
  if(y0 > y1)
  {
    swap = y0;
    y0 = y1;
    y1 = swap;
  }

  width = x1 - x0 + 1;

  height = y1 - y0 + 1;
	
  LCDFill(x0, y0, width, height, color);
}

void LCDColorFill(u32 x, u32 y, u32 width, u32 height, u16* color)
{
  u32 x0, y0, i;

  x0 = x;
  y0 = y;

  i = 0;
  for(y = y0; y < y0 + height; y++)
  {
    for(x = x0; x < x0 + width; x++)
    {
      LCDDrawPoint(x, y, color[i]);
      i++;
    }
  }
}

void LCDColorFillPixel(u32 x0, u32 y0, u32 x1, u32 y1, u16* color)
{
  u32 x, y, swap, i;

  if(x0 > x1)
  {
    swap = x0;
    x0 = x1;
    x1 = swap;
  }

  if(y0 > y1)
  {
    swap = y0;
    y0 = y1;
    y1 = swap;
  }
	
  i = 0;
  for(y = y0; y <= y1; y++)
  {
    for(x = x0; x <= x1; x++)
    {
      LCDDrawPoint(x, y, color[i]);
      i++;
    }
  }
}

void LCDDrawLine(u32 x0, u32 y0, u32 x1, u32 y1, u32 color)
{
  int x, y, dx, dy, dx2, dy2, xStep, yStep, swap, sum;

  dx = x1 - x0;
  dy = y1 - y0;
  if(dx < 0){dx = -dx;}
  if(dy < 0){dy = -dy;}
  dx2 = dx << 1;
  dy2 = dy << 1;

  if(dx >= dy)
  {
    if(x0 > x1)
    {
      swap = x0; x0 = x1; x1 = swap;
      swap = y0; y0 = y1; y1 = swap;
    }

    if(y1 > y0){yStep = 1;}else{yStep = -1;}

    x = x0;
    y = y0;
    sum = -dx;
    while(x <= x1)
    {
      LCDDrawPoint(x, y, color);

      x = x + 1;

      sum = sum + dy2;

      if(sum >= 0)
      {
        sum = sum - dx2;
        y = y + yStep;
      }
    }
  }
  else
  {

    if(y0 > y1)
    {
      swap = x0; x0 = x1; x1 = swap;
      swap = y0; y0 = y1; y1 = swap;
    }

    if(x1 > x0){xStep = 1;}else{xStep = -1;}

    x = x0;
    y = y0;
    sum = -dy;
    while(y <= y1)
    {
      LCDDrawPoint(x, y, color);
      y = y + 1;
      sum = sum + dx2;
      if(sum >= 0)
      {
        sum = sum - dy2;
        x = x + xStep;
      }
    }
  }
}

void LCDDrawRectangle(u32 x1, u32 y1, u32 x2, u32 y2, u32 color)
{
  LCDDrawLine(x1, y1, x2, y1, color);
  LCDDrawLine(x1, y1, x1, y2, color);
  LCDDrawLine(x1, y2, x2, y2, color);
  LCDDrawLine(x2, y1, x2, y2, color);
}

void LCDDrawCircle(u32 x0, u32 y0, u32 r, u32 color)
{
  int x, y, d;

  x = 0;
  y = r;
  d = 5 - (r << 2);
  while(x <= y)
  {
    LCDDrawPoint(x0 + x, y0 + y, color);
    LCDDrawPoint(x0 + x, y0 - y, color);
    LCDDrawPoint(x0 - x, y0 + y, color);
    LCDDrawPoint(x0 - x, y0 - y, color);
    LCDDrawPoint(x0 + y, y0 + x, color);
    LCDDrawPoint(x0 - y, y0 + x, color);
    LCDDrawPoint(x0 + y, y0 - x, color);
    LCDDrawPoint(x0 - y, y0 - x, color);
    x++;

    if(d < 0)
    {
      d = d + (x << 3) + 12;
    }
    else
    {
      d = d + ((x - y) << 3) + 20;
      y--;
    }
  }
}

void LCDShowChar(u32 x, u32 y, EnumTLILCDFont font, EnumTLILCDTextMode mode, u32 textColor, u32 backColor, u32 code)
{
  u8  byte;       
  u32 i, j;       
  u32 y0;         
  u32 height;     
  u32 bufSize;    
  u8* enBuf;      
  u8* codeBuf;    

  switch (font)
  {
  case LCD_FONT_12: height = 12; break;
  case LCD_FONT_16: height = 16; break;
  case LCD_FONT_24: height = 24; break;
  default: return;
  }

	 switch (font)
	 {
	 case LCD_FONT_12: bufSize = 12; break;
	 case LCD_FONT_16: bufSize = 16; break;
	 case LCD_FONT_24: bufSize = 36; break;
	 default: return;
	 }
	 
   switch (font)
   {
   case LCD_FONT_12: enBuf = (u8*)asc2_1206[code - ' ']; break;
   case LCD_FONT_16: enBuf = (u8*)asc2_1608[code - ' ']; break;
   case LCD_FONT_24: enBuf = (u8*)asc2_2412[code - ' ']; break;
   default: return;
   }
   codeBuf = enBuf;

  y0 = y;

  for(i = 0; i < bufSize; i++)
  {
    byte = codeBuf[i];

    for(j = 0; j < 8; j++)
    {
      if(byte & 0x80)
      {
        LCDDrawPoint(x, y, textColor);
      }
      else if(LCD_TEXT_NORMAL == mode)
      {
        LCDDrawPoint(x, y, backColor);
      }

      byte <<= 1;
      y++;
      if(y >= g_structTLILCDDev.height[g_structTLILCDDev.currentLayer])
      {
        return;
      }

      if((y - y0) >= height)
      {
        y = y0;
        x++;

        if(x >= g_structTLILCDDev.width[g_structTLILCDDev.currentLayer])
        {
          return;
        }
        break;
      }
    }
  }
}

void LCDShowString(u32 x, u32 y, u32 width, u32 height, EnumTLILCDFont font, EnumTLILCDTextMode mode, u32 textColor, u32 backColor, char* string)
{
  u32 x0, x1, y1, cWidth, i, code;
  
  x0 = x;
  x1 = x0 + width - 1;
  y1 = x1 + height - 1;

  switch (font)
  {
  case LCD_FONT_12: cWidth = 6; break;
  case LCD_FONT_16: cWidth = 8; break;
  case LCD_FONT_24: cWidth = 12; break;
  default: return;
  }

  i = 0;
  while(0 != string[i])
  {
    if((u8)string[i] < 0x80) //ASCII码
    {
      LCDShowChar(x, y, font, mode, textColor, backColor, string[i]);
      if((x + cWidth) > x1)
      {
        x = x0;
        y = y + height;
        if(y > y1)
        {
          return;
        }
      }
      else
      {
        x = x + cWidth;
      }

      i = i + 1;
    }
    else
    {
      code = (string[i] << 8) | string[i + 1];
      LCDShowChar(x, y, font, mode, textColor, backColor, code);

      if((x + cWidth * 2) > x1)
      {
        x = x0;
        y = y + height;
        if(y > y1)
        {
          return;
        }
      }
      else
      {
        x = x + cWidth * 2;
      }
      i = i + 2;
    }
  }
}

void LCDWindowSave(u32 x, u32 y, u32 width, u32 height, void* saveBuf)
{
  ipa_foreground_parameter_struct  ipa_fg_init_struct;          
  ipa_destination_parameter_struct ipa_destination_init_struct; 
  u32 foreStartAddr;       
  u32 phyWidth, phyHeight;  
  u32 phyX, phyY;           
  u32 lineOff;              
  u32 swap;                 

  if(LCD_SCREEN_HORIZONTAL == g_structTLILCDDev.dir)
  {
    phyWidth = g_structTLILCDDev.width[g_structTLILCDDev.currentLayer];
    phyHeight = g_structTLILCDDev.height[g_structTLILCDDev.currentLayer];
    phyX = x;
    phyY = y;
  }

  else if(LCD_SCREEN_VERTICAL == g_structTLILCDDev.dir)
  {
    phyWidth = g_structTLILCDDev.width[g_structTLILCDDev.currentLayer];
    phyHeight = g_structTLILCDDev.height[g_structTLILCDDev.currentLayer];

    swap = phyWidth;
    phyWidth = phyHeight;
    phyHeight = swap;

    swap = width;
    width = height;
    height = swap;

    phyX = phyWidth - y - width;
    phyY = x;
  }

  if((phyX + width) > LCD_PIXEL_WIDTH)
  {
    width = LCD_PIXEL_WIDTH - phyX;
  }
  if((phyY + height) > LCD_PIXEL_HEIGHT)
  {
    height = LCD_PIXEL_HEIGHT - phyY;
  }

  foreStartAddr = (u32)g_structTLILCDDev.frameBuf + g_structTLILCDDev.pixelSize * (phyWidth * phyY + phyX);
  lineOff = phyWidth - width;
  rcu_periph_clock_enable(RCU_IPA);
  ipa_deinit();
  ipa_pixel_format_convert_mode_set(IPA_FGTODE); 

  //设置前景图像参数
  ipa_foreground_struct_para_init(&ipa_fg_init_struct);
  ipa_fg_init_struct.foreground_pf              = FOREGROUND_PPF_RGB565;  
  ipa_fg_init_struct.foreground_memaddr         = foreStartAddr;          
  ipa_fg_init_struct.foreground_lineoff         = lineOff;                
  ipa_fg_init_struct.foreground_alpha_algorithm = IPA_FG_ALPHA_MODE_0;    
  ipa_fg_init_struct.foreground_prealpha        = 0xFF; 
  ipa_fg_init_struct.foreground_prered          = 0x00;  
  ipa_fg_init_struct.foreground_pregreen        = 0x00;  
  ipa_fg_init_struct.foreground_preblue         = 0x00;  
  ipa_foreground_init(&ipa_fg_init_struct);              

  //设置目标图像参数
  ipa_destination_struct_para_init(&ipa_destination_init_struct);
  ipa_destination_init_struct.destination_pf       = IPA_DPF_RGB565;  
  ipa_destination_init_struct.destination_memaddr  = (u32)saveBuf;    
  ipa_destination_init_struct.destination_lineoff  = 0;               
  ipa_destination_init_struct.destination_prealpha = 0xFF;           
  ipa_destination_init_struct.destination_prered   = 0x00;           
  ipa_destination_init_struct.destination_pregreen = 0x00;          
  ipa_destination_init_struct.destination_preblue  = 0x00;           
  ipa_destination_init_struct.image_width          = width;          
  ipa_destination_init_struct.image_height         = height;         
  ipa_destination_init(&ipa_destination_init_struct);               

  // //使能IPA内部定时器
  // ipa_interval_clock_num_config(0);
  // ipa_inter_timer_config(IPA_INTER_TIMER_ENABLE);

  ipa_transfer_enable();
  while(RESET == ipa_interrupt_flag_get(IPA_INT_FLAG_FTF));
  ipa_interrupt_flag_clear(IPA_INT_FLAG_FTF);
  ipa_deinit();
}

void LCDWindowFill(u32 x, u32 y, u32 width, u32 height, void* imageBuf)
{
  ipa_foreground_parameter_struct  ipa_fg_init_struct;          
  ipa_destination_parameter_struct ipa_destination_init_struct; 
  u32 destStartAddr;       
  u32 phyWidth, phyHeight; 
  u32 phyX, phyY;          
  u32 lineOff;             
  u32 swap;                

  if(LCD_SCREEN_HORIZONTAL == g_structTLILCDDev.dir)
  {
    phyWidth = g_structTLILCDDev.width[g_structTLILCDDev.currentLayer];
    phyHeight = g_structTLILCDDev.height[g_structTLILCDDev.currentLayer];
    phyX = x;
    phyY = y;
  }

  else if(LCD_SCREEN_VERTICAL == g_structTLILCDDev.dir)
  {

    phyWidth = g_structTLILCDDev.width[g_structTLILCDDev.currentLayer];
    phyHeight = g_structTLILCDDev.height[g_structTLILCDDev.currentLayer];

    swap = phyWidth;
    phyWidth = phyHeight;
    phyHeight = swap;
		
    swap = width;
    width = height;
    height = swap;

    phyX = phyWidth - y - width;
    phyY = x;
  }

  if((phyX + width) > LCD_PIXEL_WIDTH)
  {
    width = LCD_PIXEL_WIDTH - phyX;
  }
  if((phyY + height) > LCD_PIXEL_HEIGHT)
  {
    height = LCD_PIXEL_HEIGHT - phyY;
  }

  destStartAddr = (u32)g_structTLILCDDev.frameBuf + g_structTLILCDDev.pixelSize * (phyWidth * phyY + phyX);
  lineOff = phyWidth - width;
  rcu_periph_clock_enable(RCU_IPA);
  ipa_deinit();
  ipa_pixel_format_convert_mode_set(IPA_FGTODE); 

  //设置前景图像参数
  ipa_foreground_struct_para_init(&ipa_fg_init_struct);
  ipa_fg_init_struct.foreground_pf              = FOREGROUND_PPF_RGB565; 
  ipa_fg_init_struct.foreground_memaddr         = (u32)imageBuf;         
  ipa_fg_init_struct.foreground_lineoff         = 0;                    
  ipa_fg_init_struct.foreground_alpha_algorithm = IPA_FG_ALPHA_MODE_0;   
  ipa_fg_init_struct.foreground_prealpha        = 0xFF; 
  ipa_fg_init_struct.foreground_prered          = 0x00;
  ipa_fg_init_struct.foreground_pregreen        = 0x00; 
  ipa_fg_init_struct.foreground_preblue         = 0x00; 
  ipa_foreground_init(&ipa_fg_init_struct);             

  //设置目标图像参数
  ipa_destination_struct_para_init(&ipa_destination_init_struct);
  ipa_destination_init_struct.destination_pf       = IPA_DPF_RGB565;     
  ipa_destination_init_struct.destination_memaddr  = (u32)destStartAddr; 
  ipa_destination_init_struct.destination_lineoff  = lineOff; 
  ipa_destination_init_struct.destination_prealpha = 0xFF;    
  ipa_destination_init_struct.destination_prered   = 0x00;    
  ipa_destination_init_struct.destination_pregreen = 0x00;    
  ipa_destination_init_struct.destination_preblue  = 0x00;    
  ipa_destination_init_struct.image_width          = width;   
  ipa_destination_init_struct.image_height         = height;  
  ipa_destination_init(&ipa_destination_init_struct);         

  // //使能IPA内部定时器
  // ipa_interval_clock_num_config(0);
  // ipa_inter_timer_config(IPA_INTER_TIMER_ENABLE);

  ipa_transfer_enable();
  while(RESET == ipa_interrupt_flag_get(IPA_INT_FLAG_FTF));
  ipa_interrupt_flag_clear(IPA_INT_FLAG_FTF);
  ipa_deinit();
}

void RGB565ToRGB888A(u16 rgb565, u8* r, u8* g, u8* b)
{
  *r = ((0xF800 & rgb565) >> 11) & 0xFF;
  *g = ((0x07E0 & rgb565) >> 5 ) & 0xFF;
  *b = ((0x001F & rgb565) >> 0 ) & 0xFF;
}

u32 RGB565ToRGB888B(u16 rgb565)
{
  u8 r, g, b;
  r = ((0xF800 & rgb565) >> 11) & 0xFF;
  g = ((0x07E0 & rgb565) >> 5 ) & 0xFF;
  b = ((0x001F & rgb565) >> 0 ) & 0xFF;
  return ((r << 16) | (g << 8) | (b << 0));
}

u32 RGB888ToRGB565A(u8 r, u8 g, u8 b)
{
  r = r >> 3;
  g = g >> 2;
  b = b >> 3;

  return ((r << 11) | (g << 5) | (b << 0));
}

u32 RGB888ToRGB565B(u32 rgb888)
{
  u8 r, g, b;

  r = (rgb888 >> 16) & 0xFF;
  g = (rgb888 >> 8 ) & 0xFF;
  b = (rgb888 >> 0 ) & 0xFF;

  return RGB888ToRGB565A(r, g, b);
}


void init_lcd(void)
{
	u32 i;
	
	tli_parameter_struct tli_init_struct;
	
	g_structTLILCDDev.pWidth = LCD_PIXEL_WIDTH;
  g_structTLILCDDev.pHeight = LCD_PIXEL_HEIGHT;
  g_structTLILCDDev.dir = LCD_SCREEN_HORIZONTAL;
  g_structTLILCDDev.currentLayer = LCD_LAYER_BACKGROUND;
  g_structTLILCDDev.frameBuf = s_arrBackgroundFrame;
  g_structTLILCDDev.backFrameAddr = BACK_FRAME_START_ADDR;
  g_structTLILCDDev.foreFrameAddr = FORE_FRAME_START_ADDR;
  g_structTLILCDDev.pixelSize = 2;
  for(i = 0; i < LCD_LAYER_MAX; i++)
  {
    g_structTLILCDDev.width[i] = g_structTLILCDDev.pWidth;
    g_structTLILCDDev.height[i] = g_structTLILCDDev.pHeight;
  }
	
	rcu_periph_clock_enable(RCU_TLI);
	
	rcu_periph_clock_enable(RCU_GPIOA);
	rcu_periph_clock_enable(RCU_GPIOB);
	rcu_periph_clock_enable(RCU_GPIOC);
	rcu_periph_clock_enable(RCU_GPIOD);
	rcu_periph_clock_enable(RCU_GPIOE);
	rcu_periph_clock_enable(RCU_GPIOF);
	rcu_periph_clock_enable(RCU_GPIOH);
	rcu_periph_clock_enable(RCU_GPIOG);

	/* configure HSYNC(PE15), VSYNC(PA7), PCLK(PG7) */
	gpio_af_set(GPIOE, GPIO_AF_14, GPIO_PIN_15);
	gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_7);
	gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_7);
	gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_15);
	gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_15);
	gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
	gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_7);
	gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
	gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_7);

	/* configure LCD_R7(PG6), LCD_R6(PH12), LCD_R5(PH11), LCD_R4(PA5), LCD_R3(PH9),LCD_R2(PH8),
							 LCD_R1(PH3), LCD_R0(PH2) */
	gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_6);
	gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_12);
	gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_11);
	gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_5);
	gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_9);
	gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_8);
	gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_3);
	gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_2);

	gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
	gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_6);
	gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12);
	gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_12);
	gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
	gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_11);
	gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5);
	gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_5);
	gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9);
	gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_9);
	gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8);
	gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_8);
	gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);
	gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_3);
	gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2);
	gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_2);

	/* configure  LCD_G7(PD3), LCD_G6(PC7), LCD_G5(PC1), LCD_G4(PH15), LCD_G3(PH14), LCD_G2(PH13),LCD_G1(PB0), LCD_G0(PB1) */
	gpio_af_set(GPIOD, GPIO_AF_14, GPIO_PIN_3);
	gpio_af_set(GPIOC, GPIO_AF_14, GPIO_PIN_7);
	gpio_af_set(GPIOC, GPIO_AF_14, GPIO_PIN_1);
	gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_15);
	gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_14);
	gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_13);
	gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_0);
	gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_1);

	gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);
	gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_3);
	gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
	gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_7);
	gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1);
	gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_1);
	gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_15);
	gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_15);
	gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_14);
	gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_14);
	gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_13);
	gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_13);
	gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_0);
	gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_0);
	gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1);
	gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_1);

	/* configure LCD_B7(PB9), LCD_B6(PB8), LCD_B5(PB5), LCD_B4(PC11), LCD_B3(PG11),LCD_B2(PG10), LCD_B1(PG12), LCD_B0(PG14) */
	gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_9);
	gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_8);
	gpio_af_set(GPIOB, GPIO_AF_3, GPIO_PIN_5);
	gpio_af_set(GPIOC, GPIO_AF_14, GPIO_PIN_11);
	gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_11);
	gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_10);
	gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_12);
	gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_14);

	gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9);
	gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_9);
	gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8);
	gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_8);
	gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5);
	gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_5);
	gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
	gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_11);
	gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
	gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_11);
	gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
	gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_10);
	gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12);
	gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_12);
	gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_14);
	gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_14);

	/* configure LCD_DE(PF10) */
	gpio_af_set(GPIOF, GPIO_AF_14, GPIO_PIN_10);
	gpio_mode_set(GPIOF, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
	gpio_output_options_set(GPIOF, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_10);
	/* LCD PWM BackLight(PG13) */
	gpio_mode_set(GPIOG, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_13);
	gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_13);
	gpio_bit_set(GPIOG, GPIO_PIN_13);
	
	//复位TLI
  tli_deinit();
  tli_struct_para_init(&tli_init_struct);
	
	//配置TLI时钟
	rcu_pll_input_output_clock_range_config(IDX_PLL2, RCU_PLL2RNG_1M_2M, RCU_PLL2VCO_150M_420M);
	/* configure the PLL2 clock: CK_PLL2P/CK_PLL2Q/CK_PLL2R = HXTAL_VALUE / 25 * 150 / 3 */
	if(ERROR == rcu_pll2_config(25, 150, 3, 3, 3)) {
			while(1) {
			}
	}
	rcu_pll_clock_output_enable(RCU_PLL2R);
	rcu_tli_clock_div_config(RCU_PLL2R_DIV8);

	rcu_osci_on(RCU_PLL2_CK);

	if(ERROR == rcu_osci_stab_wait(RCU_PLL2_CK)) {
			while(1) {
			}
	}

	/* configure TLI parameter struct */
	tli_init_struct.signalpolarity_hs = TLI_HSYN_ACTLIVE_LOW;
	tli_init_struct.signalpolarity_vs = TLI_VSYN_ACTLIVE_LOW;
	tli_init_struct.signalpolarity_de = TLI_DE_ACTLIVE_LOW;
	tli_init_struct.signalpolarity_pixelck = TLI_PIXEL_CLOCK_TLI;

	//LCD显示时序配置
	tli_init_struct.synpsz_hpsz = 	HORIZONTAL_SYNCHRONOUS_PULSE - 1;
	tli_init_struct.synpsz_vpsz = 	VERTICAL_SYNCHRONOUS_PULSE - 1;
	tli_init_struct.backpsz_hbpsz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH - 1;
	tli_init_struct.backpsz_vbpsz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH - 1;
	tli_init_struct.activesz_hasz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH + ACTIVE_WIDTH	- 1;
	tli_init_struct.activesz_vasz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH + ACTIVE_HEIGHT - 1;
	tli_init_struct.totalsz_htsz = 	HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH + ACTIVE_WIDTH + HORIZONTAL_FRONT_PORCH - 1;
	tli_init_struct.totalsz_vtsz = 	VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH + ACTIVE_HEIGHT + VERTICAL_FRONT_PORCH - 1;
	
	//配置背景色RGB值 
	tli_init_struct.backcolor_red = 	0x00;
	tli_init_struct.backcolor_green = 0x00;
	tli_init_struct.backcolor_blue = 	0x00;
	tli_init(&tli_init_struct);
	
  LCDLayerWindowSet(LCD_LAYER_BACKGROUND, 0, 0, LCD_PIXEL_WIDTH, LCD_PIXEL_HEIGHT);
  LCDLayerWindowSet(LCD_LAYER_FOREGROUND, 0, 0, LCD_PIXEL_WIDTH, LCD_PIXEL_HEIGHT);
	
  LCDLayerEnable(LCD_LAYER_BACKGROUND);
  LCDLayerDisable(LCD_LAYER_FOREGROUND);
  LCDTransparencySet(LCD_LAYER_BACKGROUND, 0xFF);
  LCDTransparencySet(LCD_LAYER_FOREGROUND, 0xFF);
  tli_dither_config(TLI_DITHER_ENABLE);
  // tli_dither_config(TLI_DITHER_DISABLE);
  tli_reload_config(TLI_REQUEST_RELOAD_EN);
  tli_enable();
  LCDLayerSwitch(LCD_LAYER_BACKGROUND);
  LCDDisplayDir(LCD_SCREEN_HORIZONTAL);
  LCDClear(LCD_COLOR_BLACK);
}

 

3.2、main.c

#include "main.h"

void cache_enable(void);


int main(void)
{
	uint8_t x=0;
	uint32_t sd=0;
	cache_enable();
	systick_config();
	init_usart(115200);
	init_led();
	exmc_synchronous_dynamic_ram_init(EXMC_SDRAM_DEVICE0);
	init_lcd();
  LCDDisplayDir(LCD_SCREEN_HORIZONTAL);
  LCDClear(LCD_COLOR_WHITE);

	while(1) 
	{
		switch(x)
		{
			case 0: LCDClear(LCD_COLOR_WHITE);  break;
			case 1: LCDClear(LCD_COLOR_RED );  break;
			case 2: LCDClear(LCD_COLOR_GREEN);  break;
			case 3: LCDClear(LCD_COLOR_BLUE);  break;
			case 4: LCDClear(LCD_COLOR_YELLOW);  break;
			case 5: LCDClear(LCD_COLOR_MAGENTA);  break;
			case 6: LCDClear(LCD_COLOR_BLACK);  break;
		}
		x++;
		if(x>6)
		{
			x=0;
		}
		LCDShowString(10, 20, 300, 24, LCD_FONT_24, LCD_TEXT_TRANS, LCD_COLOR_RED, NULL, "GD32H759 TLI LCD TEST!");
		
		delay_1ms(500);
	}
}

void cache_enable(void)
{
    /* enable i-cache */
    SCB_EnableICache();

    /* enable d-cache */
    SCB_EnableDCache();
}

 

四、运行

 

下载程序后,运行视频如下:

TLI LCD

 

 

 


 

回复评论 (1)

牛呀,这试用一下子就上了这么多优秀的帖子!
点赞  2024-5-12 15:05
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复