本文介绍了 CPKCOR-RA8D1B 开发套件运行官方 Demo 例程实现 MIPI 屏幕驱动的项目设计,包括项目介绍、准备工作、工程编译和上传、Demo 效果演示、自定义图片显示等。
.../src/mipi_dsi_ep.c 文件,通过 show_pattern 函数显示不同图案typedef enum
{
simple = 0,
partition = 1,
gradient = 2
} color_pattern_t;
show_pattern(partition);
包括硬件和软件等方面的前期准备。
LLVM Embedded Toolchain for ARM 工具链的安装和部署;这里介绍了官方 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
/* 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 标签页,查看该工程调用的堆栈;

在左侧 项目资源管理器 窗口的项目文件夹上右键,选择 构建项目 ;
当工程编译完成,下方控制台输出无错误,表明工程构建完成;
使用 Type-C 数据线连接核心板的 Debug USB 接口和电脑;
右键工程,选择 调试方式 - 调试配置 ,选择编译完成的 _Flat 文件,调试器选择 J-Link ARM;
点击 调试 按钮,进入调试界面,点击菜单栏 运行 按钮执行程序;

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


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

| 设置项 | 推荐值 | 说明 |
|---|---|---|
| 输出数据类型 | 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 /* 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 显示屏在完成色彩显示初始化和自检后,循环显示自定义图片填充;

见底部视频。
本文介绍了 CPKCOR-RA8D1B 开发套件运行官方 Demo 例程实现 MIPI 屏幕驱动显示的项目设计,包括项目介绍、准备工作、工程编译和上传、Demo效果演示、自定义图片显示等,也为相关产品的开发设计和快速应用提供了参考。
注意到图片显示有部分重叠,修改 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);
}
}
重新构建并调试工程,效果如下


举报
更多回帖