【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 给出代码程序对应的流程图

工程代码
打开主函数所在文件 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
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);
R_FSP_VersionGet(&version);
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);
bsp_sdram_init();
ST7796U_init_HW();
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();
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++)
{
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)) );
err = R_GLCDC_Open(&g_display_ctrl, &g_display_cfg);
handle_error(err, "** GLCDC driver initialization FAILED ** \r\n");
err = R_GPT_Open(&g_timer0_ctrl, &g_timer0_cfg);
handle_error(err, "** R_GPT_Open API failed ** \r\n");
touch_screen_reset();
err = R_IIC_MASTER_Open(&g_i2c_master_ctrl, &g_i2c_master_cfg);
handle_error(err, "** IIC MASTER Open API failed ** \r\n");
mipi_dsi_push_table(g_lcd_init_focuslcd);
err = R_ICU_ExternalIrqOpen(&g_external_irq_ctrl, &g_external_irq_cfg);
handle_error(err, "** ICU ExternalIrqOpen API failed ** \r\n");
mipi_dsi_start_display();
}
- 进一步定位至
mipi_dsi_start_display() 函数
void mipi_dsi_start_display(void)
{
fsp_err_t err = FSP_SUCCESS;
uint8_t color_count;
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();
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++)
{
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)) );
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;
gp_double_buffer = gp_single_buffer + g_buffer_size;
err = R_GPT_InfoGet (&g_timer0_ctrl, &timer_info);
handle_error(err, "** GPT InfoGet API failed ** \r\n");
R_BSP_SoftwareDelay(500,1000);
R_BSP_SoftwareDelay(500,1000);
R_BSP_SoftwareDelay(500,1000);
err = R_GLCDC_Start(&g_display_ctrl);
handle_error(err, "** GLCDC Start API failed ** \r\n");
err = R_ICU_ExternalIrqEnable(&g_external_irq_ctrl);
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++)
{
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++)
{
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];
}
}
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];
}
}
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];
}
}
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];
}
}
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;
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);
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);
}
}
保存代码,构建工程。
工程加载
工程调试
-
在左侧 项目资源管理器 窗口的项目文件夹上右键,选择 构建项目 ;
-
当工程编译完成,下方控制台输出无错误,表明工程构建完成;
-
使用 Type-C 数据线连接核心板的 Debug USB 接口和电脑;
-
右键工程,选择 调试方式 - 调试配置 ,选择编译完成的 _Flat 文件,调试器选择 J-Link ARM;
-
点击 调试 按钮,进入调试界面,点击菜单栏 运行 按钮执行程序;

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


动态效果
见顶部视频。
自定义图片显示
在了解上述官方例程的运作方式和基本框架后,进一步实现自定义图片的显示和切换,包括自定义图片转换、关键代码、效果演示等。
图片转换
- 运行 Image2LCD 软件,加载目标图片,进行参数配置;

| 设置项 |
推荐值 |
说明 |
|---|
| 输出数据类型 |
C 语言数组 |
生成 .c 文件,便于复制到工程中 |
| 扫描模式 |
水平扫描 |
与大多数 LCD 控制器兼容 |
| 输出灰度 |
16 位真彩色 |
对应 RGB565 格式 |
| 图像宽度/高度 |
设置为 222×480 |
与图片一致 |
工程代码
将 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
- 打开
...\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 显示屏在完成色彩显示初始化和自检后,循环显示自定义图片填充;

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