2. 像素与颜色格式:RGB565颜色编码、像素排列、显存映射、16位色深详解
在驱动ST7789这类TFT-LCD时,理解像素的颜色编码方式与显存映射关系是进行高效刷新的基础。本章将深入剖析RGB565颜色格式、像素在显存中的排列规律以及16位色深的实际含义,为后续双缓冲与DMA优化打下坚实的理论基础。
2.1 16位色深与RGB565编码
ST7789支持16位色深(即每像素占用2字节),采用RGB565格式。这种格式在色彩表现力与存储/传输带宽之间取得了良好平衡,是嵌入式小尺寸LCD最主流的颜色编码方案。
| 颜色分量 | 位宽 | 取值范围 | 权重 |
|---|---|---|---|
| 红色 (R) | 5 bit | 0 ~ 31 | 高位 |
| 绿色 (G) | 6 bit | 0 ~ 63 | 中间位 |
| 蓝色 (B) | 5 bit | 0 ~ 31 | 低位 |
RGB565 数据排列(大端模式,MCU常用):
字节0 (高字节) 字节1 (低字节)
┌───┬───┬───┬───┬───┬───┬───┬───┐ ┌───┬───┬───┬───┬───┬───┬───┬───┐
│ R4│ R3│ R2│ R1│ R0│ G5│ G4│ G3│ │ G2│ G1│ G0│ B4│ B3│ B2│ B1│ B0│
└───┴───┴───┴───┴───┴───┴───┴───┘ └───┴───┴───┴───┴───┴───┴───┴───┘
颜色转换示例:将24位RGB(128, 64, 32)转换为RGB565
R = 128 >> 3 = 16 (0b10000)
G = 64 >> 2 = 16 (0b100000)
B = 32 >> 3 = 4 (0b00100)
RGB565 = (R << 11) | (G << 5) | B
= (16 << 11) | (16 << 5) | 4
= 0x8414
实战提示:在C语言中,常用宏定义进行RGB888到RGB565的快速转换:
#define RGB565(r, g, b) ((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3))
2.2 像素排列与显存映射
ST7789的显存(GRAM)以行优先方式组织。每个像素对应一个16位RGB565值,显存地址按从左到右、从上到下的顺序递增。
显存映射公式:
对于坐标 (x, y),显存地址偏移 = (y × 宽度 + x) × 2 字节
对于坐标 (x, y),显存地址偏移 = (y × 宽度 + x) × 2 字节
关键参数(以240×240分辨率为例):
- 总像素数:240 × 240 = 57,600 像素
- 显存总大小:57,600 × 2 = 115,200 字节 ≈ 112.5 KB
- 每行字节数:240 × 2 = 480 字节
2.3 像素数据在SPI总线上的传输顺序
ST7789通过SPI接口接收像素数据时,遵循先高字节后低字节的传输顺序。当使用9位SPI模式(8位数据+1位DCX)时,每个像素需要2次传输。
| 传输序号 | DCX电平 | 数据内容 | 说明 |
|---|---|---|---|
| 第1次 | 高 (数据) | RGB565 高字节 | R[4:0] + G[5:3] |
| 第2次 | 高 (数据) | RGB565 低字节 | G[2:0] + B[4:0] |
常见错误:字节序混淆是导致颜色显示异常的首要原因。如果屏幕出现颜色通道错位(如红色变蓝色),请检查MCU端发送数据时是否使用了小端模式,以及SPI的MSB/LSB优先设置是否与ST7789匹配。
2.4 颜色深度对比:16位 vs 18位 vs 24位
虽然ST7789硬件支持18位色深(通过3字节/像素的RGB666格式),但在实际嵌入式应用中,16位RGB565是性能和画质的最佳平衡点。
| 色深 | 每像素字节数 | 总颜色数 | 240×240显存占用 | 适用场景 |
|---|---|---|---|---|
| 16位 (RGB565) | 2 | 65,536 | 112.5 KB | 通用GUI、图标、文字 |
| 18位 (RGB666) | 3 | 262,144 | 168.75 KB | 照片、渐变、图像显示 |
| 24位 (RGB888) | 3(需转换) | 16,777,216 | 168.75 KB(模拟) | 上位机预处理后下传 |
性能调优要点:在双缓冲方案中,使用RGB565格式可使帧缓冲区大小减半,从而:
- 减少SRAM占用,为其他任务留出空间
- 降低DMA传输量,提升刷新帧率
- 加快像素填充与拷贝操作(16位对齐访问)
2.5 像素坐标与窗口设置
ST7789通过CASET(列地址设置)和RASET(行地址设置)命令定义像素写入窗口。理解窗口与显存映射的关系,是实现局部刷新和区域裁剪的前提。
2.6 颜色格式转换实战
在实际项目中,经常需要将图像数据从RGB888转换为RGB565。以下是一个高效的C语言转换函数示例:
/**
* @brief 将RGB888像素转换为RGB565格式
* @param r 红色分量 (0-255)
* @param g 绿色分量 (0-255)
* @param b 蓝色分量 (0-255)
* @return 16位RGB565颜色值
*/
uint16_t rgb888_to_rgb565(uint8_t r, uint8_t g, uint8_t b) {
return ((r >> 3) << 11) | // R: 5位
((g >> 2) << 5) | // G: 6位
(b >> 3); // B: 5位
}
/**
* @brief 批量转换RGB888缓冲区到RGB565
* @param src RGB888源数据 (每像素3字节)
* @param dst RGB565目标数据 (每像素2字节)
* @param pixel_count 像素数量
*/
void rgb888_batch_to_rgb565(const uint8_t *src, uint16_t *dst, uint32_t pixel_count) {
for (uint32_t i = 0; i < pixel_count; i++) {
uint8_t r = src[i * 3 + 0];
uint8_t g = src[i * 3 + 1];
uint8_t b = src[i * 3 + 2];
dst[i] = rgb888_to_rgb565(r, g, b);
}
}
优化建议:在批量转换时,可以使用查表法(LUT)将8位R/B分量预计算为5位值,将8位G分量预计算为6位值,从而将每次转换从移位+或运算简化为三次查表+一次或运算,在无硬件乘法器的MCU上可提升30%以上性能。
2.7 本章小结
- RGB565是ST7789最常用的颜色格式,5-6-5位分配兼顾色彩与效率。
- 显存采用行优先线性映射,地址偏移 = (y × 宽度 + x) × 2。
- SPI传输时先高字节后低字节,字节序错误会导致颜色通道错乱。
- 16位色深相比18/24位在存储占用和传输带宽上优势明显,是双缓冲方案的首选。
- 窗口设置(CASET/RASET)与显存映射配合,可实现高效的局部刷新。