瑞萨单片机论坛
直播中

jf_07365693

1年用户 380经验值
擅长:嵌入式技术 控制/MCU
私信 关注
[讨论]

【CPKCOR-RA8D1】MIPI 图片显示

mipi_demo_pic_show

【CPKCOR-RA8D1】MIPI 图片显示

本文介绍了 CPKCOR-RA8D1B 开发套件运行官方 Demo 例程实现 MIPI 屏幕驱动的项目设计,包括项目介绍、准备工作、工程编译和上传、Demo 效果演示、自定义图片显示等。

项目介绍

  • 该示例工程演示了 CPKCOR 核心板和扩展板的 MIPI 屏驱动显示功能测试。
  • 屏幕驱动IC为 ST7796U, 像素大小为 222 x 480 ;
  • 打开 .../src/mipi_dsi_ep.c 文件,通过 show_pattern 函数显示不同图案
typedef enum
{
    simple = 0,
    partition = 1,
    gradient = 2
} color_pattern_t;

show_pattern(partition);

准备工作

包括硬件和软件等方面的前期准备。

硬件

  • Renesas RA8D1 核心板:CPKCOR-RA8D1B;
  • 1 根 USB Type-A 转 Type-C 或 Type-C 转 Type-C 数据线;
  • 1个 MIPI 显示屏,型号 H0233S001-V1,驱动芯片 ST7796U ;
  • 1个 CPKEXP-EKRA8X1 扩展板;

软件

  • 开发环境搭建:包括 FSP软件包LLVM Embedded Toolchain for ARM 工具链的安装和部署;
  • 官方 Demo 示例工程下载:使用 git 工具或下载 cpk_examples
  • 下载 和安装 Image2LCD 软件:将目标图片转换为数组代码;

Demo 工程

这里介绍了官方 Demo 例程 mipi_cpkexp_ra8d1_ep 的工程测试方案,包括项目流程图、关键代码、工程加载和调试、效果演示等。

流程图

根据 ...\src\mipi_dsi_ep.c 给出代码程序对应的流程图

flowchrt_mipi_demo.jpeg

工程代码

打开主函数所在文件 src\hal_entry.c ,代码如下

#include "mipi_dsi_ep.h"
#include "hal_data.h"
#include "r_mipi_dsi.h"
#include "common_utils.h"

FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER

void hal_entry(void)
{
    mipi_dsi_entry();

#if BSP_TZ_SECURE_BUILD
    /* Enter non-secure code */
    R_BSP_NonSecureEnter();
#endif
}
  • 主函数中调用 mipi_dsi_entry() 函数,右键打开声明,定位至该函数
void mipi_dsi_entry(void)
{
    fsp_err_t          err        = FSP_SUCCESS;
    fsp_pack_version_t version    = {RESET_VALUE};
    g_hz_size = (g_display_cfg.input[0].hsize);
    g_vr_size = (g_display_cfg.input[0].vsize);
    g_hstride = (g_display_cfg.input[0].hstride);

    /* version get API for FLEX pack information */
    R_FSP_VersionGet(&version);

    /* Project information printed on the Console */
    APP_PRINT(BANNER_INFO, EP_VERSION, version.version_id_b.major, version.version_id_b.minor, version.version_id_b.patch);
    APP_PRINT(EP_INFO);
    APP_PRINT(MIPI_DSI_MENU);

    /* Initialize SDRAM. */
    bsp_sdram_init();
    ST7796U_init_HW();
    /* Get LCDC configuration */
        g_hz_size = (g_display_cfg.input[0].hsize);
        g_vr_size = (g_display_cfg.input[0].vsize);
        g_hstride = (g_display_cfg.input[0].hstride);

        DWT_init();
        DWT_clean_count();

//        uint32_t * p = (uint32_t *)&fb_background[0][0];
//        DWT_pre_count = DWT_get_count();
//            for(uint32_t x=0;x<g_vr_size;x++) //g_vr_size
//            {
//                for(uint32_t y=0;y<g_hz_size;y++)
//                {
//                    p[y+x*g_hz_size] = color_32bit[0];
//                }
//            }
//        SCB_EnableDCache();
    uint16_t * p = (uint16_t *)&fb_background[0][0];
        DWT_pre_count = DWT_get_count();
            for(uint32_t x=0;x<g_vr_size;x++) //g_vr_size
            {
                for(uint32_t y=0;y<g_hz_size;y++)
                {
                    p[y+x*g_hz_size] = color[0];
                }
            }
        DWT_post_count = DWT_get_count();

        DWT_delta = DWT_post_count - DWT_pre_count;

        APP_PRINT("\r\n");
        APP_PRINT("11Before open GLCDC, DWT count:%d\r\n", DWT_delta);
        APP_PRINT("11Before open GLCDC, time:%d\r\n", DWT_count_to_us(DWT_delta) );

        APP_PRINT("11Before open GLCDC, speed:%dMB/s\r\n", (g_hz_size*g_vr_size*2)/(DWT_count_to_us(DWT_delta)) );
//        APP_PRINT("Before start GLCDC, speed:%dMB/s\r\n", (g_hz_size*g_vr_size*4)/(DWT_count_to_us(DWT_delta)) ); // 32bit

    /* Initialize GLCDC module */
    err = R_GLCDC_Open(&g_display_ctrl, &g_display_cfg);

    /* Handle error */
    handle_error(err, "** GLCDC driver initialization FAILED ** \r\n");

    /* Initialize GPT module */
    err = R_GPT_Open(&g_timer0_ctrl, &g_timer0_cfg);
    /* Handle error */
    handle_error(err, "** R_GPT_Open API failed ** \r\n");

    /* LCD reset */
    touch_screen_reset();

    /* Initialize IIC MASTER module */
    err = R_IIC_MASTER_Open(&g_i2c_master_ctrl, &g_i2c_master_cfg);
    /* Handle error */
    handle_error(err, "** IIC MASTER Open API failed ** \r\n");

    /* Initialize LCD. */
    mipi_dsi_push_table(g_lcd_init_focuslcd);

    /* Initialize ICU module */
    err = R_ICU_ExternalIrqOpen(&g_external_irq_ctrl, &g_external_irq_cfg);
    /* Handle error */
    handle_error(err, "** ICU ExternalIrqOpen API failed ** \r\n");

    /* Start display 8-color bars */
    mipi_dsi_start_display();
}
  • 进一步定位至 mipi_dsi_start_display() 函数
void mipi_dsi_start_display(void)
{
    fsp_err_t err = FSP_SUCCESS;
    uint8_t color_count;

    /* Get LCDC configuration */
    g_hz_size = (g_display_cfg.input[0].hsize);
    g_vr_size = (g_display_cfg.input[0].vsize);
    g_hstride = (g_display_cfg.input[0].hstride);
//    SCB_EnableDCache();
    DWT_init();
    DWT_clean_count();

    uint16_t * p = (uint16_t *)&fb_background[0][0];
    DWT_pre_count = DWT_get_count();
    for(uint32_t x=0;x<g_vr_size;x++) //g_vr_size
    {
        for(uint32_t y=0;y<g_hz_size;y++)
        {
            p[y+x*g_hz_size] = y;
        }
    }

    DWT_post_count = DWT_get_count();

    DWT_delta = DWT_post_count - DWT_pre_count;

    APP_PRINT("\r\n");
    APP_PRINT("Before start GLCDC, DWT count:%d\r\n", DWT_delta);
    APP_PRINT("Before start GLCDC, time:%d\r\n", DWT_count_to_us(DWT_delta) );

    APP_PRINT("Before start GLCDC, speed:%dMB/s\r\n", (g_hz_size*g_vr_size*2)/(DWT_count_to_us(DWT_delta)) );


    /* Initialize buffer pointers */
    g_buffer_size = (uint32_t) (g_hz_size * g_vr_size * BYTES_PER_PIXEL);
    gp_single_buffer = (uint32_t*) g_display_cfg.input[0].p_base;

    /* Double buffer for drawing color bands with good quality */
    gp_double_buffer = gp_single_buffer + g_buffer_size;

    /* Get timer information */
    err = R_GPT_InfoGet (&g_timer0_ctrl, &timer_info);
    /* Handle error */
    handle_error(err, "** GPT InfoGet API failed ** \r\n");
    R_BSP_SoftwareDelay(500,1000);
    R_BSP_SoftwareDelay(500,1000);
    R_BSP_SoftwareDelay(500,1000);

    /* Start video mode */
    err = R_GLCDC_Start(&g_display_ctrl);

    /* Handle error */
    handle_error(err, "** GLCDC Start API failed ** \r\n");

    /* Enable external interrupt */
    err = R_ICU_ExternalIrqEnable(&g_external_irq_ctrl);
    /* Handle error */
    handle_error(err, "** ICU ExternalIrqEnable API failed ** \r\n");

    DWT_clean_count();
    DWT_pre_count = DWT_get_count();
        for(uint32_t x=0;x<g_vr_size;x++) //g_vr_size
        {
            for(uint32_t y=0;y<g_hz_size;y++)
            {
                p[y+x*g_hz_size] = color[0];
            }
        }



     DWT_post_count = DWT_get_count();
     DWT_delta = DWT_post_count - DWT_pre_count;

     APP_PRINT("After start GLCDC, DWT count:%d\r\n", DWT_delta);
     APP_PRINT("After start GLCDC, time:%d\r\n", DWT_count_to_us(DWT_delta) );

     APP_PRINT("After start GLCDC, speed:%dMB/s\r\n", (g_hz_size*g_vr_size*2)/(DWT_count_to_us(DWT_delta)) );

     R_BSP_SoftwareDelay(500,1000);

     while(1){
            show_pattern(partition);
            show_pic();
     }
}
  • 可知该函数在完成一系列初始化操作后,进入主循环,实现指定功能的显示操作,如 show_pattern() 函数;
void show_pattern(color_pattern_t pattern)
{
    uint16_t * p = (uint16_t *)&fb_background[0][0];
    R_BSP_SoftwareDelay(400, BSP_DELAY_UNITS_MILLISECONDS);
    count++;
    if(count>=sizeof(color))
    {
        count=0;
    }

    switch(pattern){
        case simple:
            for(uint32_t x=0;x<g_vr_size;x++) //g_vr_size
            {
                for(uint32_t y=0;y<g_hz_size;y++)
                {
                    p[y+x*g_hz_size] = color[count];
                }
            }
            break;
        case partition:
            for(uint32_t x=0;x<g_vr_size/2;x++)
            {
                for(uint32_t y=0;y<(g_hz_size-34)/2;y++)
                {
                    p[y+x*g_hz_size] = color[0];
                }
//                R_BSP_SoftwareDelay(50, BSP_DELAY_UNITS_MILLISECONDS);
            }

            for(uint32_t x=0;x<g_vr_size/2;x++)
            {
                for(uint32_t y=(g_hz_size-34)/2;y<g_hz_size;y++)
                {
                    p[y+x*g_hz_size] = color[1];
                }
//                R_BSP_SoftwareDelay(50, BSP_DELAY_UNITS_MILLISECONDS);
            }
            for(uint32_t x=g_vr_size/2;x<g_vr_size;x++)
            {
                for(uint32_t y=0;y<act_hz/2;y++)
                {
                    p[y+x*g_hz_size] = color[2];
                }
//                R_BSP_SoftwareDelay(50, BSP_DELAY_UNITS_MILLISECONDS);
            }
            for(uint32_t x=g_vr_size/2;x<g_vr_size;x++)
            {
                for(uint32_t y=act_hz/2;y<g_hz_size;y++)
                {
                    p[y+x*g_hz_size] = color[3];
                }
//                R_BSP_SoftwareDelay(50, BSP_DELAY_UNITS_MILLISECONDS);
            }
            break;
        case gradient:
            for(uint32_t x=0;x<g_vr_size;x++)
            {
                for(uint32_t y=0;y<g_hz_size;y++)
                {
                    p[y+x*g_hz_size] = x;
                }
            }
            break;
        default :
            break;

    }
#if defined(RENESAS_CORTEX_M85)
#if (BSP_CFG_DCACHE_ENABLED)
    int32_t size;
    /* Invalidate cache - so the HW can access any data written by the CPU */

        size = sizeof(fb_background[0])/2;

    SCB_CleanInvalidateDCache_by_Addr(p, size);
#endif
#endif
        R_GLCDC_BufferChange (&g_display_ctrl, (uint8_t*) p, DISPLAY_FRAME_LAYER_1);

        /* Wait for a Vsync event */
        g_vsync_flag = RESET_FLAG;
        while (g_vsync_flag);
}
  • 对于图片的显示,由 show_pic() 函数实现;
void show_pic()
{
    uint8_t * p = (uint8_t *)&fb_background[0][0];
    R_BSP_SoftwareDelay(400, BSP_DELAY_UNITS_MILLISECONDS);

    for(uint32_t x=0;x<g_vr_size*2;x++)
    {
        for(uint32_t y=0;y<g_hz_size;y++)
        {

           p[y+x*(g_hz_size)] = gImage_qier[y+x*(g_hz_size-34)];

        }
        R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
    }
}

保存代码,构建工程。

工程加载

  • 加载目标 Demo 示例工程,路径为 ...\cpk_examples\cpkexp_ekra8x1\mipi_cpkexp_ra8d1_ep\e2studio_llvm

  • 设备名称:R7FA8D1BHECBD ;

  • 进入 Stacks 标签页,查看该工程调用的堆栈;

    mipi_demo_stacks.jpg

工程调试

  • 在左侧 项目资源管理器 窗口的项目文件夹上右键,选择 构建项目

  • 当工程编译完成,下方控制台输出无错误,表明工程构建完成;

  • 使用 Type-C 数据线连接核心板的 Debug USB 接口和电脑;

  • 右键工程,选择 调试方式 - 调试配置 ,选择编译完成的 _Flat 文件,调试器选择 J-Link ARM

  • 点击 调试 按钮,进入调试界面,点击菜单栏 运行 按钮执行程序;

    mipi_demo_debug.jpg

效果演示

当工程调试或运行时,板载 TFT 显示屏在完成色彩显示初始化和自检后,循环显示色彩填充和图片填充;

mipi_demo_run.jpg

mipi_demo_pic_show.jpg

动态效果

见顶部视频。

自定义图片显示

在了解上述官方例程的运作方式和基本框架后,进一步实现自定义图片的显示和切换,包括自定义图片转换、关键代码、效果演示等。

图片转换

  • 运行 Image2LCD 软件,加载目标图片,进行参数配置;

image2lcd_setting.jpg

  • 相关参数如下
设置项 推荐值 说明
输出数据类型 C 语言数组 生成 .c 文件,便于复制到工程中
扫描模式 水平扫描 与大多数 LCD 控制器兼容
输出灰度 16 位真彩色 对应 RGB565 格式
图像宽度/高度 设置为 222×480 与图片一致
  • 设置完成后,点击上方的 保存 按钮,复制生成的数组代码;

    logo_numbers.jpg

工程代码

将 Image2LCD 软件生成的 image.h 文件保存至 ...\cpk_examples\cpkexp_ekra8x1\mipi_cpkexp_ra8d1_ep\e2studio_llvm\src 路径下,并添加头文件代码;

#ifndef IMAGE_H_
#define IMAGE_H_

const unsigned char gImage_logo[213128] = { 0X00,0X10,0XDE,0X00,0XE0,0X01,0X01,0X1B,
0X53,0X29,0X53,0X29,0X53,0X29,0X53,0X29,0X53,0X29,0X53,0X29,0X53,0X29,0X53,0X29,
0X53,0X29,0X53,0X29,0X53,0X29,0X53,0X29,0X53,0X29,0X53,0X29,0X53,0X29,0X53,0X29,
......
......
0X53,0X29,0X53,0X29,0X53,0X29,0X53,0X29,0X53,0X29,0X53,0X29,0X53,0X29,0X53,0X29,
0X53,0X29,0X53,0X29,0X53,0X29,0X53,0X29,0X53,0X29,0X53,0X29,0X53,0X29,0X53,0X29,
};

#endif /* IMAGE_H_ */
  • 打开 ...\src\mipi_dsi_ep.c 文件,添加 #include "image.h" 引入图片数组;
  • 定位至 show_pic() 函数,修改调用的图片数组名为 gImage_logo[]
void show_pic()
{
    uint8_t * p = (uint8_t *)&fb_background[0][0];
    R_BSP_SoftwareDelay(400, BSP_DELAY_UNITS_MILLISECONDS);

    for(uint32_t x=0;x<g_vr_size*2;x++)
    {
        for(uint32_t y=0;y<g_hz_size;y++)
        {

           p[y+x*(g_hz_size)] = gImage_logo[y+x*(g_hz_size-34)];

        }
        R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
    }
}
  • 保存代码,重新构建工程;
  • 若无错误提示,则调试工程。

显示效果

当工程调试或运行时,板载 TFT 显示屏在完成色彩显示初始化和自检后,循环显示自定义图片填充;

mipi_show_logo.jpg

动态演示

见底部视频。

总结

本文介绍了 CPKCOR-RA8D1B 开发套件运行官方 Demo 例程实现 MIPI 屏幕驱动显示的项目设计,包括项目介绍、准备工作、工程编译和上传、Demo效果演示、自定义图片显示等,也为相关产品的开发设计和快速应用提供了参考。

mipi_image_show

回帖(1)

无垠的广袤

2025-10-8 12:12:21

注意到图片显示有部分重叠,修改 show_pic() 函数


void show_pic(void)
{
    const uint16_t *src = (const uint16_t *)gImage_logo;               // RGB565 像素数组
    uint16_t       *dst = (uint16_t *)&fb_background[0][0];            // 目标帧缓冲
    const uint32_t  src_width = g_hz_size - 34;                        // logo 宽度(像素)
    const uint32_t  dst_width = g_hz_size;
    const uint32_t  height    = g_vr_size;

    const uint32_t x_offset = 0;

    for (uint32_t y = 0; y < height; y++)
    {
        for (uint32_t x = 0; x < src_width; x++)
        {
            dst[y * dst_width + x + x_offset] = src[y * src_width + x];
        }
        R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
    }
}

重新构建并调试工程,效果如下


mipi_show_pic_normal.jpg


mipi_show_image_normal.jpg


举报

更多回帖

发帖
×
20
完善资料,
赚取积分