🖥️ 嵌入式 LCD 驱动开发全流程详解
在嵌入式世界里,
能不能把"信息显示出来" ,往往决定了一个项目看起来像不像"成品"。
从黑屏到显示画面,
LCD 驱动几乎是每个嵌入式工程师都绕不开的一关。
🧠 一、先搞清楚:LCD 驱动到底在"驱"什么?
很多新手一听"LCD 驱动",就以为是:
"写几个函数,屏就亮了?"
实际上,LCD 驱动至少包含 四个层面:
- 硬件接口通信(SPI / I2C / RGB / MIPI)
- 屏幕控制芯片初始化
- 显存 / 显示缓冲管理
- 图形与字符绘制接口
👉 你驱动的不是"屏",而是 屏后面的控制器。
🧩 二、常见嵌入式 LCD 类型速览
1️⃣ 字符屏(1602 / 2004)
- 并口 / I2C
- 显示字符
- 调试友好,但表现力有限
2️⃣ 图形 LCD(TFT / OLED)
| 类型 | 特点 |
|---|---|
| OLED | 自发光、对比高、功耗低 |
| TFT | 彩色、分辨率高、需背光 |
3️⃣ 常见控制芯片
| 屏幕 | 控制器 |
|---|---|
| 0.96 OLED | SSD1306 |
| 1.3 OLED | SH1106 |
| 2.4 TFT | ILI9341 |
| 1.8 TFT | ST7735 |
| 2.8 TFT | ST7789 |
🔌 三、LCD 硬件连接方式(决定复杂度)
🔹 SPI(最常见)
- 引脚少
- 驱动简单
- 速度中等
text
CS / DC / RST / CLK / MOSI
🔹 I2C(字符屏 & 小 OLED)
- 更省引脚
- 速度慢
- 不适合大分辨率
🔹 RGB 并口(高端项目)
- 速度快
- 硬件复杂
- 占用引脚多
⚙️ 四、LCD 驱动开发的标准流程(重点)
✅ Step 1:确认屏幕参数
你至少要知道:
- 分辨率(如 240×320)
- 控制芯片型号
- 接口类型
- 显示方向
- 供电 & 背光方式
没数据手册,不要写驱动。
✅ Step 2:底层通信驱动(SPI/I2C)
以 SPI 为例,你需要两个最基础函数:
c
void LCD_WriteCmd(uint8_t cmd);
void LCD_WriteData(uint8_t data);
示例:
c
void LCD_WriteCmd(uint8_t cmd)
{
LCD_DC_LOW();
LCD_CS_LOW();
HAL_SPI_Transmit(&hspi1, &cmd, 1, 100);
LCD_CS_HIGH();
}
void LCD_WriteData(uint8_t data)
{
LCD_DC_HIGH();
LCD_CS_LOW();
HAL_SPI_Transmit(&hspi1, &data, 1, 100);
LCD_CS_HIGH();
}
✅ Step 3:复位与初始化时序
LCD 不会上电就能用,必须初始化。
典型流程:
text
硬件复位 → 延时 → 发送初始化命令表
示例:
c
void LCD_Reset(void)
{
LCD_RST_LOW();
HAL_Delay(50);
LCD_RST_HIGH();
HAL_Delay(120);
}
初始化命令通常是一长串:
c
LCD_WriteCmd(0x11); // Sleep Out
HAL_Delay(120);
LCD_WriteCmd(0x29); // Display On
👉 顺序和延时都不能乱。
✅ Step 4:设置显示窗口(GRAM)
LCD 的像素数据,
实际上是写进 显示 RAM(GRAM) 的。
c
void LCD_SetWindow(uint16_t x1, uint16_t y1,
uint16_t x2, uint16_t y2)
{
LCD_WriteCmd(0x2A); // Column addr
LCD_WriteData(x1 >> 8);
LCD_WriteData(x1 & 0xFF);
LCD_WriteData(x2 >> 8);
LCD_WriteData(x2 & 0xFF);
LCD_WriteCmd(0x2B); // Row addr
...
LCD_WriteCmd(0x2C); // Memory write
}
✅ Step 5:写像素(点亮世界的第一步)
c
void LCD_DrawPixel(uint16_t x, uint16_t y, uint16_t color)
{
LCD_SetWindow(x, y, x, y);
LCD_WriteData(color >> 8);
LCD_WriteData(color & 0xFF);
}
当你第一次点亮一个像素时------
LCD 驱动已经成功 50% 了。
🖊️ 五、字符与图形绘制原理
字符是怎么画出来的?
本质是:
点阵字体 + 像素填充
c
if(font[i] & (1 << bit))
LCD_DrawPixel(x, y, color);
常见绘制接口封装
LCD_DrawLine()LCD_DrawRect()LCD_DrawCircle()LCD_ShowChar()LCD_ShowString()
📦 六、显存 vs 直接刷屏
方案 1:直接写 LCD(简单)
- RAM 占用小
- 刷新慢
- 可能闪屏
方案 2:FrameBuffer(进阶)
- MCU RAM 保存整屏
- 双缓冲
- UI 更丝滑
text
240 × 320 × 2Byte ≈ 150KB
🧯 七、新手最常见的 LCD 坑
| 现象 | 原因 |
|---|---|
| 黑屏 | 初始化顺序错误 |
| 白屏 | 方向 / 参数错 |
| 花屏 | 分辨率或窗口错 |
| 颜色反了 | RGB/BGR 顺序 |
| 显示偏移 | 映射没处理 |
| 刷屏慢 | SPI 频率低 |
🚀 八、性能优化思路(工程级)
- SPI 提速(DMA)
- 批量写像素
- 区域刷新
- 字库放 Flash
- RTOS 分离 UI 任务
🧠 九、LCD 驱动的"终极形态"
成熟项目中:
text
底层驱动
↓
显示抽象层
↓
GUI 库(LVGL / emWin)
你写的 LCD 驱动,
就是 GUI 的"地基"。
✅ 十、总结一句话
LCD 驱动 = 通信 + 初始化 + 显存管理 + 绘图接口。
一旦你真正驱动过一块 LCD,
你就会发现:
嵌入式,不只是"能跑程序",
而是"能把系统展示给用户"。