外观
4.3 寸 480x800 Mipi 屏幕示例
2025-10-29
本示例演示如何从 BMP 图片文件 读取数据,转换为 BGR888 格式,并通过 MIPI 接口 在 LCD 屏幕上显示。
显示睿擎的 Logo 图像
本示例以 睿擎(ruiching)的 Logo 为例,展示完整的图像显示流程:
读取 BMP 文件
转换为 BGR888 格式
初始化 LCD 控制器
开启背光
刷新帧缓冲(将图像显示到屏幕)
硬件连接
注意
必须在断电状态下进行连接操作。
开发板的 mipi 接口和显示屏的接口连接好,注意接口防呆设计,确保方向正确,轻轻锁紧连接器扣具。


创建工程点击展开
依次点击 “文件” -> “新建” -> "RT-Thread RuiChing App 项目"。

在弹出新建向导中选择 开发版 、BSP: 、示例 、 调试器/下载器。选择好之后点击 “完成”。

点击 “完成” 后,等待工程创建完成。

创建完成。

构建工程点击展开
单击工程使工程进入 Active-Debug 模式。

点击工具栏上的构建按钮进行工程编译。

构建成功后,会显示构建成功的信息。

固件下载点击展开
固化设备树

固化 APP

核心示例代码
- 准备 BMP 图片并将其转为 BGR888 格式
在将 BMP 图片显示到 MIPI 屏幕之前,必须确保图片数据正确,并转换为设备兼容的 BGR888 格式。
检查 BMP 文件是否损坏 确认 BMP 文件以 0x4D42(即 "BM")开头,否则文件可能损坏或格式错误。
检查位深度(Bits Per Pixel, BPP) 本示例仅处理 24-bit(RGB888)BMP 文件。
bmp2bgr888.c
rt_err_t bmp_extract_bgr888(const rt_uint8_t *bmp_data, rt_uint8_t *img_buffer)
{
...
if (header.bf_type != 0x4d42) // 检查文件签名
{
ret = (-RT_EINVAL);
rt_kprintf("[BMP] Invalid signature (got 0x%04X, expected 0x4D42)",
header.bf_type);
return ret;
}
if (info.bi_bitcount != 24) // 检查位深度
{
ret = (-RT_ENOSYS);
rt_kprintf("[BMP] Error: Only 24-bit format supported (got %d-bit)\n",
info.bi_bitcount);
return ret;
}
...
}- 检查是否为倒向存储(Bottom-Up BMP)
高度值符号
正高度:表示图片数据从 最后一行开始存储(需反向读取)。
负高度:表示数据从 第一行开始存储(直接顺序读取)。
若为倒向存储,需翻转行序以适配帧缓冲。
- 转换为 BGR888 格式 BMP 通常存储为 BRG,但 MIPI 屏幕可能要求 BGR,需逐像素转换。
bmp2bgr888.c
rt_err_t bmp_extract_bgr888(const rt_uint8_t *bmp_data, rt_uint8_t *img_buffer)
{
...
// 像素转化
if (info.bi_height < 0)
{
info.bi_height = -info.bi_height;
is_top_down = 1;
}
else
{
is_top_down = 0;
}
row_size = ((info.bi_width * info.bi_bitcount + 31) / 32) * 4;
pixel_data = bmp_data + header.bf_offbits;
for (y = 0; y < info.bi_height; y++)
{
src_y = is_top_down ? y : (info.bi_height - 1 - y);
const rt_uint8_t *src_row = pixel_data + src_y * row_size;
dst_row = img_buffer + y * info.bi_width * 3;
for (x = 0; x < info.bi_width; x++)
{
if (info.bi_bitcount == 24)
{
// 像素转化
dst_row[x * 3 + 0] = src_row[x * 3 + 0]; // B
dst_row[x * 3 + 1] = src_row[x * 3 + 1]; // G
dst_row[x * 3 + 2] = src_row[x * 3 + 2]; // R
}
}
}
...
}- 初始化 LCD 设备并显示图像
通过 RT-Thread 设备框架 以 可读写模式(RT_DEVICE_FLAG_RDWR) 打开 LCD 设备。
使用 RTGRAPHIC_CTRL_GET_INFO 命令获取 LCD 的 分辨率、像素格式、帧缓冲地址 等关键参数,并打印调试信息
参数值 说明 pixel_format 像素格式(如 BGR888) bits_per_pixel 位深度(如 24bpp) pitch 每行字节数(含填充) width,height 屏幕分辨率 framebuffer 帧缓冲地址 smem_len 帧缓冲总大小 通过 RTGRAPHIC_CTRL_SET_BRIGHTNESS 控制屏幕背光
背光值范围:0(完全关闭)到 100(最大亮度)。
硬件依赖:由于硬件背光由 GPIO 直接控制(非 PWM 调光),其行为已被驱动层抽象化。
| 参数值 | 硬件行为 | 说明 |
|---|---|---|
| brightness = 0 | GPIO 输出低电平 | 背光完全关闭 |
| brightness > 0 | GPIO 输出高电平 | 背光开启 |
将转换后的 BGR888 数据 写入 LCD 的帧缓冲(info.framebuffer)。
通过 RTGRAPHIC_CTRL_RECT_UPDATE 通知 LCD 控制器刷新指定区域(全屏刷新)。
main.c
int main(void)
{
...
device = rt_device_find("lcd");
if (!device)
{
rt_kprintf("Can't find device lcd\n");
return (-RT_ENOENT);
}
rt_kprintf("ok!\n");
rt_device_init(device);
rt_device_open(device, RT_DEVICE_FLAG_RDWR);
rt_device_control(device, RTGRAPHIC_CTRL_GET_INFO, &info);
rt_kprintf(" Graphic Device Information:\n");
rt_kprintf(" pixel_format: %d\n", info.pixel_format);
rt_kprintf(" bits_per_pixel: %u\n", info.bits_per_pixel);
rt_kprintf(" pitch: %d bytes\n", info.pitch);
rt_kprintf(" size: %dx%d\n", info.width, info.height);
rt_kprintf(" framebuffer: %p\n", info.framebuffer);
rt_kprintf(" smem_len: %lu\n", (rt_uint32_t)info.smem_len);
rt_kprintf("Step 4 - Set backlight open. ok!\n");
rt_device_control(device, RTGRAPHIC_CTRL_SET_BRIGHTNESS, &bright);
rt_kprintf("Step 5 - Frame update. ok!\n");
rt_memcpy(info.framebuffer, img_data, info.smem_len);
rt_device_control(device, RTGRAPHIC_CTRL_RECT_UPDATE, RT_NULL);
rt_free(img_data);
return 0;
}运行程序
开发板运行程序后,结果如下:

系统执行流程总结:
初始化:检查 BMP → 转换 BGR888 → 初始化 LCD;
显示:写入帧缓冲 → 开启背光 → 刷新屏幕;
