174|2

70

帖子

0

资源

一粒金砂(中级)

【GD32450I-EVAL】TLI-RGB屏幕驱动初探

(一)概述
GD32F4系列是我知道的国内最早的M4F内核单片机了,另外的几个系列诸如F3、E1都是不带硬件FPU的M4内核,在一些运算的场景上劣势相当明显,当然,F4最终还是在今年被新推出的M33内核E5系列给摩擦了,后者超高精度定时器和TMU数学加速功能简直让人垂涎,连NXP的POWERQUAD都被不支持的arctan运算都给加速了!
但E5强大的数学能力并不足以让他处处压制F4系列,F4系列有一项重头戏功能——TLI借口,能够直驱RGB接口!而F450更是F4系列其中其中的最强者,主频高达200M,比E5系列还要高20M。

 

(二)TLI
TLI外设除了提供一般的RGB888接口还,还支持双显示层功能,能够通过DMA发送。
另外,直驱过RGB和MCU的一定能够感受到,RGB有一个重大的劣势,就是无法单独刷新某一块区域,这导致在设置DMA缓冲区时必须要一个完整的480*272*2(如果是使用RGB565 16位色)缓冲区,而双缓冲更是需要480*272*2*2,算下来足足有510K,目前F4作为兆易创新SRAM最大的片子也就512K,本芯片则是只有256K,只要程序有一点大小SRAM开销就放不下哪怕一个缓冲,如果不使用外部SDRAM的前提下根本不可能驱动一个最基本的480*272屏幕。
TLI的特性给了一个选择,可以设置填充空缺的位置,而使用一个较小的分辨率和较小的内存开销,这在开发测试阶段很意义。

 

(三)TLI设置
1-时钟源设置
TLI的时钟完全是由一个独立的PLL(PLLSAI)锁相环输出的,与系统时钟来源不同。值得一提的是I2S也是另一个独立的PLL时钟源(PLLI2S),总共三个PLL锁相环,让音频应用时钟也可以更准确。
PLL.png
TLI的时钟从(PLLSAI)锁相环输出:
通过rcu_pllsai_config设置锁相环参数,rcu_osci_on使能锁相环,rcu_tli_clock_div_config使能锁相环后的分频参数

    /* configure PLLSAI to generate TLI clock */
    if(ERROR == rcu_pllsai_config(192, 2, 3)){
        while(1);
    }
    rcu_tli_clock_div_config(RCU_PLLSAIR_DIV8);
    
    rcu_osci_on(RCU_PLLSAI_CK);
    
    if(ERROR == rcu_osci_stab_wait(RCU_PLLSAI_CK)){
        while(1);
    }

 

2-使能本身设备时钟

rcu_periph_clock_enable(RCU_TLI);

 

3-使能GPIO

void tli_gpio_config(void)
{
    /* enable GPIO clock */
    rcu_periph_clock_enable(RCU_GPIOB);
    rcu_periph_clock_enable(RCU_GPIOE);
    rcu_periph_clock_enable(RCU_GPIOH);
    rcu_periph_clock_enable(RCU_GPIOI);
    rcu_periph_clock_enable(RCU_GPIOG);

    /* configure HSYNC(PI10), VSYNC(PI9), PCLK(PG7) */
    /* configure LCD_R7(PG6), LCD_R6(PH12), LCD_R5(PH11), LCD_R4(PH10), LCD_R3(PH9),LCD_R2(PH8), 
                 LCD_R1(PH3), LCD_R0(PH2), LCD_G7(PI2), LCD_G6(PI1), LCD_G5(PI0), LCD_G4(PH15), 
                 LCD_G3(PH14), LCD_G2(PH13),LCD_G1(PE6), LCD_G0(PE5),LCD_B7(PI7), LCD_B6(PI6), 
                 LCD_B5(PI5), LCD_B4(PI4), LCD_B3(PG11),LCD_B2(PG10), LCD_B1(PG12), LCD_B0(PE4) */
    /* configure TLI pins AF function */
    gpio_af_set(GPIOE,GPIO_AF_14,GPIO_PIN_5);
    gpio_af_set(GPIOE,GPIO_AF_14,GPIO_PIN_6);
    gpio_af_set(GPIOE,GPIO_AF_14,GPIO_PIN_4);
    
    gpio_af_set(GPIOH,GPIO_AF_14,GPIO_PIN_2);
    gpio_af_set(GPIOH,GPIO_AF_14,GPIO_PIN_3);
    gpio_af_set(GPIOH,GPIO_AF_14,GPIO_PIN_8);
    gpio_af_set(GPIOH,GPIO_AF_14,GPIO_PIN_9);
    gpio_af_set(GPIOH,GPIO_AF_14,GPIO_PIN_10);
    gpio_af_set(GPIOH,GPIO_AF_14,GPIO_PIN_11);
    gpio_af_set(GPIOH,GPIO_AF_14,GPIO_PIN_12);
    gpio_af_set(GPIOH,GPIO_AF_14,GPIO_PIN_13);
    gpio_af_set(GPIOH,GPIO_AF_14,GPIO_PIN_14);
    gpio_af_set(GPIOH,GPIO_AF_14,GPIO_PIN_15);
    
    gpio_af_set(GPIOI,GPIO_AF_14,GPIO_PIN_0);
    gpio_af_set(GPIOI,GPIO_AF_14,GPIO_PIN_1);
    gpio_af_set(GPIOI,GPIO_AF_14,GPIO_PIN_2);
    gpio_af_set(GPIOI,GPIO_AF_14,GPIO_PIN_4);
    gpio_af_set(GPIOI,GPIO_AF_14,GPIO_PIN_5);
    gpio_af_set(GPIOI,GPIO_AF_14,GPIO_PIN_6);
    gpio_af_set(GPIOI,GPIO_AF_14,GPIO_PIN_7);
    gpio_af_set(GPIOI,GPIO_AF_14,GPIO_PIN_9);
    gpio_af_set(GPIOI,GPIO_AF_14,GPIO_PIN_10);
    
    gpio_af_set(GPIOG,GPIO_AF_14,GPIO_PIN_6);
    gpio_af_set(GPIOG,GPIO_AF_14,GPIO_PIN_7);
    gpio_af_set(GPIOG,GPIO_AF_14,GPIO_PIN_10);
    gpio_af_set(GPIOG,GPIO_AF_14,GPIO_PIN_11);
    gpio_af_set(GPIOG,GPIO_AF_14,GPIO_PIN_12);

    /* configure TLI GPIO */
    gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6);
    gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ,GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6);

    gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10
                |GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15);
    gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ,GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_8|GPIO_PIN_9
                |GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15);

    gpio_mode_set(GPIOI, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4
                |GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_9|GPIO_PIN_10);
    gpio_output_options_set(GPIOI, GPIO_OTYPE_PP, GPIO_OSPEED_200MHZ,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_4
                |GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_9|GPIO_PIN_10);
    
    gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12);
    gpio_output_options_set(GPIOG, GPIO_OTYPE_PP,GPIO_OSPEED_200MHZ, GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12);

    /* LCD PWM BackLight(PB15) */
    gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_15);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_15);
    gpio_bit_set(GPIOB,GPIO_PIN_15);
}

 

4-TLI初始化
设置HS、VS、DE几个引脚空闲状态高低电平状态

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


配置前后空闲时序,可以通过bpsz实现局部范围内的图像显示

    /* LCD display timing configuration */
    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;


设置背景颜色

    /* configure LCD background R,G,B values */
    tli_init_struct.backcolor_red = 0xFF;
    tli_init_struct.backcolor_green = 0xFF;
    tli_init_struct.backcolor_blue = 0xFF;
    tli_init(&tli_init_struct);

 

5-TLI单一层显示
通过层的POS实现单个层在局部范围内显示,比如下面这个例子就是指显示X:20->160; Y:30->90
配置这些参数对应的是设置TLI_LxHPOS和TLI_LxVPOS寄存器实现,外部像素由TLI_LxDC决定,对应的就是下面的layer_default_xx字段
TLI_LxBLEND.png

    /* TLI window size configuration */
    tli_layer_init_struct.layer_window_leftpos = 20 + HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH;
    tli_layer_init_struct.layer_window_rightpos = (20 + 140 + HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH - 1);
    tli_layer_init_struct.layer_window_toppos = 30 + VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH;
    tli_layer_init_struct.layer_window_bottompos = (30 + 60 + VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH - 1);


设置像素格式RGB565

    /* TLI window pixel format configuration */
    tli_layer_init_struct.layer_ppf = LAYER_PPF_RGB565;


设置层的透明程度

    /* TLI window specified alpha configuration */
    tli_layer_init_struct.layer_sa = 255; 


设置层混合模式【图】

    /* TLI window blend configuration */
    tli_layer_init_struct.layer_acf1 = LAYER_ACF1_PASA;
    tli_layer_init_struct.layer_acf2 = LAYER_ACF2_PASA;


设置该层显示范围外的颜色

    /* TLI layer default alpha R,G,B value configuration */
    tli_layer_init_struct.layer_default_alpha = 0;
    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 frame buffer base address configuration */
    tli_layer_init_struct.layer_frame_bufaddr = (uint32_t)&gImage_0;
    tli_layer_init_struct.layer_frame_line_length = ((140 * 2) + 3);
    tli_layer_init_struct.layer_frame_buf_stride_offset = (140 * 2);
    tli_layer_init_struct.layer_frame_total_line_number = 60;
    tli_layer_init(LAYER1, &tli_layer_init_struct);

 

6-开防抖动

    tli_dither_config(TLI_DITHER_ENABLE);

 


可以看到,虽然数据手册里说了内部有DMA发送数据,但实际配置的时候是不需要额外配置DMA的,    
tli_layer_init_struct.layer_frame_bufaddr = (uint32_t)&gImage_0;
这句实际上是把缓冲区基地址传进了一个寄存器就完事了

 

(四)TLI测试
例程中实现了两个层叠加显示,我就不再重复了,关键是要实现两个层轮流单独显示
1-使能层显示

    tli_layer_enable(LAYER0);
    tli_reload_config(TLI_REQUEST_RELOAD_EN);
    tli_enable();


2-在500ms周期轮流显示两个图案

    static __IO uint32_t timingdelaylocal = 0U;

    if(timingdelaylocal){

        if(timingdelaylocal < 500U){
            gd_eval_led_on(LED1);
            tli_layer_disable(LAYER1);
            tli_layer_enable(LAYER0);
            tli_reload_config(TLI_REQUEST_RELOAD_EN);
        }else{
            gd_eval_led_off(LED1);
            tli_layer_disable(LAYER0);
            tli_layer_enable(LAYER1);
            tli_reload_config(TLI_REQUEST_RELOAD_EN);
        }

        timingdelaylocal--;
    }else{
        timingdelaylocal = 1000U;
    }

 

 

(五)效果

display.gif


回复

1万

帖子

133

资源

管理员

个人签名

玩板看这里:

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

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


回复

327

帖子

0

资源

一粒金砂(中级)

看起来跟STM32的LTDC差不多。要是有个MIPI接口那就更加好了


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

关闭
站长推荐上一条 1/5 下一条

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

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

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

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