561|1

121

帖子

0

资源

一粒金砂(中级)

【GD32450I-EVAL】+ 04液晶屏层叠显示与透明度调整测试 [复制链接]

本帖最后由 DDZZ669 于 2020-9-20 15:44 编辑

上篇 " 【GD32450I-EVAL】+ 03库函数基础使用方法-以按键中断为例" 介绍了GD32库开发的基础使用方法,本篇来研究一下液晶显示屏。

result.jpg

 

 

1 RGB液晶屏

 

GD32450I开发板上带了一块4.3英寸的480x272的RGB接口显示屏,类型为TFT-LCD(Thin Film Transistor-Liquid Crystal Display),即薄膜晶体管液晶显示器。

之前只用过MCU接口的屏幕,这里简单说一下区别:

  • MCU-LCD:最初是为单片机(MCU)设计的,因单片机内存较小,把显存内置在LCD模块内部,通过专门的显示命令来更新显存,MCU屏不能做得很大。MCU屏显示图像,显示需要发送画点的命令来修改MCU内部RAM。
  • RGB-LCD:其显存是由系统内存充当,只要系统内存够大,RGB-LCD就可以做出较大尺寸。RGB屏显示图像,只需显存组织好数据,启动显示后,LCD-DMA会自动把显存通过RGB接口送到显示屏,因此RGB屏的刷新速度较快。

两种屏的工作方式示意图如下:

mcu-rgb.png

 

关于屏幕的两种驱动模式:

de-vh.png

RGB屏一般有2种驱动模式:DE模式和SYNC模式(或称HV模式)。DE模式使用DE信号来确定有效数据,而SYNC模式,则需要行同步(Hsync)和场同步(Vsync),来表示扫描的行和列。

 

关于屏幕的一些参数:

480272.png

可以看到,虽然屏幕分辨率是480*272,但水平和垂直的总周期会大于这个数,边缘多出来的像素具体是什么作用可以先不用管,程序中屏幕初始化的时候会用到这些数,先知道如何对应起来即可。

 

 

2 GD32的TLI

 

TLI(TFT-LCD Interface)即液晶屏接口,它是GD32单片机自身提供的一种驱动RGB-LCD的一种控制接口。TLI支持两个独立的显示层,并支持层窗口和层混叠功能。其层叠显示过程如下图所示:

layer.png

此图中,层0层1即两个独立的显示层,另外还有一个BG层,即背景层,可以指定显示某种颜色,该层处于最底层。层0叠加在BG层之上,通过调节层0的透明度,可以与BG层融合显示。层1叠加在最上面,也可以调节透明度。这三个层叠加在一起,就是屏幕展现出来的效果。

 

 

3 图片转RGB565

 

这款LCD支持多种像素格式,具体如下表,此次测试先使用RGB565格式,即红、绿、蓝分别占用5、6、5位来表示颜色值,所以描述一个彩色像素需要16位,即2个字节,也就是一个字。

format.png

 

图片转换成RGB565的16进制数据,可以使用一些小工具来转换,转换后保存成数组。

转换方法如下,先找一张自己需要的图片,然后使用Picture2Hex这个小软件,指定转换后图片的宽度和高度,选择图片转换即可,然后产生一个logo.c文件,将该文件中的数组放到自己的代码工程中使用。

rgb565.png

 

4 层叠与透明度显示测试

 

上面介绍了一些基本原理,下面写一个测试程序来看一下层叠显示的效果。

 

首先是主函数部分,就是各种初始化,最后在按键中断中会来改变3个层的颜色或透明度:

int main(void)
{
    system_clock_config();
	systick_config();
    mytimer_init();
	
	key_config();//通过按键来改变3个层的颜色或透明度
	
	lcd_init();//LCD的GPIO等的初始化
	lcd_layer_init();//LCD的显示层的初始化
	
	tli_layer_enable(LAYER0);
	tli_layer_enable(LAYER1);
	tli_enable();//使能两个显示层
	
	//设置两个显示层的透明度
	lcd_layer_set(LCD_LAYER_FOREGROUND);
	lcd_transparency_set(125);//0~255
	lcd_layer_set(LCD_LAYER_BACKGROUND);
	lcd_transparency_set(155);//0~255

    while (1) 
	{
		//主循环,什么也不做,在按键中断中会只改变透明度
    }
}

 

初始化部分主要开看LCD的初始化和层的初始化。

先看LCD的初始化

void lcd_init(void)
{
//--------此处省去GPIO、时钟等的初始化
    
    /* TLI initialization */
    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 display timing configuration */
    tli_init_struct.synpsz_hpsz = 40;
    tli_init_struct.synpsz_vpsz = 9;
    tli_init_struct.backpsz_hbpsz = 42; 
    tli_init_struct.backpsz_vbpsz = 11;  
    tli_init_struct.activesz_hasz = 522;
    tli_init_struct.activesz_vasz = 283;
    tli_init_struct.totalsz_htsz = 524; 
    tli_init_struct.totalsz_vtsz = 285;
	
    /* LCD background color configure*/  //最底层
    tli_init_struct.backcolor_red = 0xFF;
    tli_init_struct.backcolor_green = 0xFF;
    tli_init_struct.backcolor_blue = 0xFF; 
    tli_init(&tli_init_struct);
}

第1部分中,DE参数为Low,所以采用的是SYNC模式。

第2部分中,好多参数,可以先对照上面的屏幕参数表格。

第2部分中,就是叠加层中的“BG层”,即最底层,这里先都给0xFF,即白色。

 

再来看层的初始化:

void lcd_layer_init(void)
{
    tli_layer_parameter_struct  tli_layer_init_struct;
	
    /* TLI layer1 configuration */ //layer1 前景层(最上层)
    tli_layer_init_struct.layer_window_leftpos = (0 + 43);//最左侧从0开始
    tli_layer_init_struct.layer_window_rightpos = (0 + 400 + 43 - 1); //最右侧到400结束
    tli_layer_init_struct.layer_window_toppos = (0 + 12);//最上侧从0开始
    tli_layer_init_struct.layer_window_bottompos = (0 + 200 + 12 - 1);//最下侧到200结束
    tli_layer_init_struct.layer_ppf = LAYER_PPF_RGB565;//RGB565格式
    tli_layer_init_struct.layer_sa = 0x0;//其余部分透明显示
    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 = 0x0;//图片部分的透明度,之后可以通过按键修改
    tli_layer_init_struct.layer_acf1 = LAYER_ACF1_PASA;//LAYER_ACF1_SA;    
    tli_layer_init_struct.layer_acf2 = LAYER_ACF2_PASA;//LAYER_ACF2_SA;
    tli_layer_init_struct.layer_frame_bufaddr = (uint32_t)image_eeworld;//eeworld图片的RGB565数组
    tli_layer_init_struct.layer_frame_line_length = ((LCD_PIXEL_WIDTH * 2) + 3); 
    tli_layer_init_struct.layer_frame_buf_stride_offset = (LCD_PIXEL_WIDTH * 2);
    tli_layer_init_struct.layer_frame_total_line_number = LCD_PIXEL_HEIGHT; 
    tli_layer_init(LAYER1, &tli_layer_init_struct);

    /* TLI layer0 configuration */ //layer0 背景层(中间层)
    tli_layer_init_struct.layer_window_leftpos = (80 + 43);//最左侧从80开始
    tli_layer_init_struct.layer_window_rightpos = (80 + 400 + 43 - 1);  //最右侧到80+400结束
    tli_layer_init_struct.layer_window_toppos = (72 + 12);//最上侧从72开始
    tli_layer_init_struct.layer_window_bottompos = (72+ 200 + 12 - 1);//最下侧到72+200结束
    tli_layer_init_struct.layer_ppf = LAYER_PPF_RGB565;
    tli_layer_init_struct.layer_sa = 0x0;//其余部分透明显示
    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 = 0x0;
    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 = (uint32_t)image_gd32;//gd32图片的RGB565数组
    tli_layer_init_struct.layer_frame_line_length = ((LCD_PIXEL_WIDTH * 2) + 3); 
    tli_layer_init_struct.layer_frame_buf_stride_offset = (LCD_PIXEL_WIDTH * 2);
    tli_layer_init_struct.layer_frame_total_line_number = LCD_PIXEL_HEIGHT; 
    tli_layer_init(LAYER0, &tli_layer_init_struct);

    tli_reload_config(TLI_REQUEST_RELOAD_EN);
    lcd_font_set(&LCD_DEFAULT_FONT);
    tli_dither_config(TLI_DITHER_ENABLE);
}

这里的layer0与layer1即叠加层中的“层0”和“层1”,两个显示层都配置为宽400高200,其余的部分透明显示。

 

使用按键来修改BG层的颜色:

void change_backcolor(int n)
{
	int i = n%4;
	switch(i)
	{
		case 0:
			tli_init_struct.backcolor_red   = 0xFF;
			tli_init_struct.backcolor_green = 0xFF;
			tli_init_struct.backcolor_blue  = 0xFF; 
		    break;
		case 1:
			tli_init_struct.backcolor_red   = 0xFF;
			tli_init_struct.backcolor_green = 0x00;
			tli_init_struct.backcolor_blue  = 0x00; 
		    break;
		case 2:
			tli_init_struct.backcolor_red   = 0x00;
			tli_init_struct.backcolor_green = 0xFF;
			tli_init_struct.backcolor_blue  = 0x00; 
		    break;
		case 3:
			tli_init_struct.backcolor_red   = 0x00;
			tli_init_struct.backcolor_green = 0x00;
			tli_init_struct.backcolor_blue  = 0xFF; 
		    break;
	}
	tli_init(&tli_init_struct);
}

 

使用按键来修改层0和层1的透明度:

void lcd_layer_set(uint32_t layer)
{
    if (layer == LCD_LAYER_BACKGROUND)
	{
        current_framebuffer = (uint32_t)image_gd32;//LCD_FRAME_BUFFER;
        current_layer = LCD_LAYER_BACKGROUND;
    }else
	{
        current_framebuffer = (uint32_t)image_eeworld;//LCD_FRAME_BUFFER + BUFFER_OFFSET;
        current_layer = LCD_LAYER_FOREGROUND;
    }
}
void lcd_transparency_set(uint8_t trans)
{
    if (current_layer == LCD_LAYER_BACKGROUND)
	{
        TLI_LxSA(LAYER0) = trans;
    }
	else
	{
        TLI_LxSA(LAYER1) = trans;
    }
    tli_reload_config(TLI_REQUEST_RELOAD_EN);
}
//改变层0的透明度-------------
void change_layer0_transparency(int n)
{
	int i = n%6;//0 1 2 3 4 5
	
	lcd_layer_set(LCD_LAYER_BACKGROUND);
	lcd_transparency_set(i*50);
}
//改变层1的透明度-------------
void change_layer1_transparency(int n)
{
	int i = n%6;//0 1 2 3 4 5
	
	lcd_layer_set(LCD_LAYER_FOREGROUND);
	lcd_transparency_set(i*50);
}

 

 

5 下载验证

 

编译一下程序:

compiling picture.c...
linking...
Program Size: Code=4360 RO-data=334236 RW-data=80 ZI-data=1088  
FromELF: creating hex file...
".\GD32F4xx-OBJ\USBH-HID.axf" - 0 Error(s), 5 Warning(s).
Build Time Elapsed:  00:00:03

可以看到Code为4360字节,即4K多点,而RO-data有334236字节,即326K多,主要是RGB565的数组占用了较大的空间。

这里用到了了2个400x200的RGB565的数组,总大小为400x200x2x2=320000字节,即320K,占据了RO-data的大部分。

关于这几个大小的含义,可参考上篇 "【GD32450I-EVAL】+ 03库函数基础使用方法-以按键中断为例"中 "程序编译下载" 处的介绍。

 

由于图片占用较大空间,下载程序时间较长(约半分钟),之后可以考虑如何先把图片烧写到flash的某个位置,然后程序来读取,这样不用每次都花时间来烧写图片数据。

 

演示视频如下,通过调节各层的透明度,可以清楚的看到各个层的叠加关系:


 


回复

1万

帖子

133

资源

管理员

个人签名

玩板看这里:

http://bbs.eeworld.com.cn/elecplay.html

EEWorld测评频道众多好板等你来玩,还可以来频道许愿树许愿说说你想要玩的板子,我们都在努力为大家实现!


回复
您需要登录后才可以回帖 登录 | 注册

最新文章 更多>>
    关闭
    站长推荐上一条 1/6 下一条

    About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

    站点相关: 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

    北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

    电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2020 EEWORLD.com.cn, Inc. All rights reserved
    快速回复 返回顶部 返回列表