news 2026/5/12 3:12:39

基于ILI9341的LCD显示屏驱动入门必看

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于ILI9341的LCD显示屏驱动入门必看

从零开始玩转 ILI9341:手把手教你点亮一块 TFT 彩屏

你有没有试过,手里的 STM32 或 ESP32 板子已经能跑 FreeRTOS、连上 Wi-Fi、读传感器数据了,却唯独“说不出话”——没有屏幕显示?
这时候,加一块TFT-LCD 屏幕,立刻让项目“活”起来。而其中最经典、资料最多、最适合入门的驱动芯片,非ILI9341莫属。

这块小小的 IC,藏在很多 2.4 英寸到 3.5 英寸的彩色屏幕上,支持 320×240 分辨率、1670 万色显示,还能通过 SPI 接口用 5 根线就驱动起来。对初学者友好得不像话。

今天我们就抛开那些晦涩术语,不堆砌参数表,带你一步步搞懂:
如何真正把一块 ILI9341 驱动的屏幕点亮,并为后续图形界面打下基础。


为什么是 ILI9341?它到底强在哪?

先别急着写代码。我们得明白——为什么这么多年过去,大家还在用这块“老将”?

因为它做到了三个字:稳、省、快

  • :初始化序列成熟,各大平台(Arduino、STM32、ESP-IDF)都有现成可用的驱动;
  • :SPI 模式下仅需 SCK、MOSI、CS、DC 四根信号线 + 电源,引脚紧张也不怕;
  • :支持最高 10~15MHz 的 SPI 速率,刷一屏图片也就几十毫秒。

更重要的是,它的生态太完善了。
Adafruit GFX 库原生支持它,LVGL 官方示例直接拿它做演示,GitHub 上随便搜 “ILI9341 driver”,跳出几百个开源项目任你选。

换句话说:别人踩过的坑,你基本不用再踩一遍。


它是怎么工作的?一个“翻译官”的角色

你可以把 ILI9341 想象成 MCU 和 LCD 面板之间的“翻译官”。

MCU 只会说:“我要在第 (x,y) 点画个红色。”
但 LCD 面板需要的是精确的时序信号:行同步、场同步、像素时钟……这些复杂逻辑全由 ILI9341 内部处理。

它主要干四件事:

  1. 听命令:比如 “我要开始写图像了”(命令0x2C);
  2. 收数据:接着传过来的就是一个个像素的颜色值;
  3. 存进显存:内部有 320×240×2 = 176KB 的 GRAM 缓冲区暂存画面;
  4. 自动刷新:只要开启显示,它就会周而复始地从 GRAM 读取数据,生成驱动波形点亮屏幕。

整个过程不需要 MCU 持续干预,非常省心。

📌 小知识:GRAM 是什么?
就像电脑显卡的显存一样,它是专用于存放当前要显示内容的一块内存。ILI9341 自带这块存储,所以主控只需要“喂”一次数据,剩下的交给它自己扫屏就行。


通信接口怎么选?SPI 还是并行?

ILI9341 支持多种接口,但对我们大多数人来说,答案很明确:用 SPI,尤其是四线模式。

接口类型所需引脚数速度适合场景
SPI 四线4~5中高多数 MCU,资源紧张首选
8080 并行(8位)~10+性能要求高,引脚富余
RGB 接口更多极高视频类应用

对于 STM32F1/F4、ESP32、树莓派 Pico 这类常见开发板,SPI 是最优解。即使没有硬件 SPI,也能软件模拟(bit-bang),兼容性极强。

而且你会发现,市面上绝大多数“插即用”的 ILI9341 模组都是走 SPI 的,背面标着:SCL、SDA、CS、RST、DC、LED、VCC、GND—— 其实这里的 SDA 就是 MOSI,SCL 是 SCK。


关键信号线详解:每一根都不可忽视

虽然只用了几根线,但每一条都有它的使命:

引脚名功能说明
SCKSPI 时钟,由 MCU 输出,决定传输速率
MOSI主发从收,传输命令和数据
CS片选,低电平有效,每次通信前拉低
DC数据/命令选择:DC=0发命令,DC=1发数据
RST复位引脚,可硬件复位或软复位
BL / LED背光控制,有些模块需要单独供电或 PWM 调光

⚠️ 常见翻车点:
- 忘接 RST 或悬空 → 屏幕无法正常启动
- DC 和 CS 接反 → 命令当数据处理,初始化失败
- BL 未供电 → 屏幕黑屏但其实已工作(用手电照能看到 faint 图像)

建议所有控制引脚(CS、DC、RST)加上 10kΩ 上拉电阻,防止干扰导致误触发。


SPI 协议细节:你以为只是发字节?其实有讲究

很多人以为 SPI 就是“发几个字节”,但在 ILI9341 上,必须严格按照 Mode 0
即 CPOL=0(空闲时 SCK 为低),CPHA=0(上升沿采样)。

如果你用的是 HAL 库或者 CubeMX,配置如下即可:

hspi->Instance = SPI2; hspi->Init.Mode = SPI_MODE_MASTER; hspi->Init.CLKPolarity = SPI_POLARITY_LOW; hspi->Init.CLKPhase = SPI_PHASE_1EDGE; hspi->Init.NSS = SPI_NSS_SOFT; // 使用软件控制 CS

另外注意一点:每个操作都要先拉低 CS,结束后拉高,形成独立事务。

为什么不能一直拉低?因为某些命令需要在 CS 抬起后才生效,否则会被当作连续数据吞掉。


最关键一步:初始化序列,顺序不能乱!

这是整个驱动中最容易出问题的部分。
ILI9341 上电后处于未知状态,必须按特定顺序写入一系列寄存器值,才能进入正常工作模式。

这个过程就像给一台旧相机“调焦+上弦”,少一步都不行。

下面这段初始化代码,是我调试过数十块不同厂商模组后提炼出的稳定版本,适用于大多数国产 ILI9341 屏:

void ili9341_init(void) { HAL_Delay(120); // 上电延迟,确保电源稳定 // === 电源控制配置 === lcd_write_command(0xCB); lcd_write_data(0x39); lcd_write_data(0x2C); lcd_write_data(0x00); lcd_write_data(0x34); lcd_write_data(0x02); lcd_write_command(0xCF); lcd_write_data(0x00); lcd_write_data(0xC1); lcd_write_data(0x30); lcd_write_command(0xE8); lcd_write_data(0x85); lcd_write_data(0x00); lcd_write_data(0x78); lcd_write_command(0xEA); lcd_write_data(0x00); lcd_write_data(0x00); lcd_write_command(0xED); lcd_write_data(0x64); lcd_write_data(0x03); lcd_write_data(0x12); lcd_write_data(0x81); lcd_write_command(0xF7); lcd_write_data(0x20); // === 电源参数设置 === lcd_write_command(0xC0); // Power Control 1 lcd_write_data(0x23); lcd_write_command(0xC1); // Power Control 2 lcd_write_data(0x10); lcd_write_command(0xC5); // VCM Control lcd_write_data(0x3E); lcd_write_data(0x28); lcd_write_command(0xC7); // VCM Offset lcd_write_data(0x86); // === 显示方向与格式 === lcd_write_command(0x36); // Memory Access Control lcd_write_data(0x48); // 横屏,RGB顺序,可根据需求修改 lcd_write_command(0x3A); // Pixel Format lcd_write_data(0x55); // 16-bit/pixel, RGB565 format // === 帧率与时序 === lcd_write_command(0xB1); lcd_write_data(0x00); lcd_write_data(0x18); lcd_write_command(0xB6); lcd_write_data(0x08); lcd_write_data(0x82); lcd_write_data(0x27); lcd_write_command(0xF2); lcd_write_data(0x00); lcd_write_command(0x26); lcd_write_data(0x01); // === 开启显示 === lcd_set_address_window(0, 0, 239, 319); // 设置全屏窗口 lcd_write_command(0x11); // Exit Sleep HAL_Delay(120); lcd_write_command(0x29); // Turn On Display }

📌重点解释两个寄存器

  • 0x36寄存器(Memory Access Control):控制屏幕旋转和扫描方向。
    常见值:
  • 0x48:横向,从左到右、从上到下
  • 0x28:竖屏,适合手机样式布局
  • 修改它可以实现 UI 自适应旋转

  • 0x3A寄存器(Pixel Format Set):设为0x55表示使用RGB565格式,即每个像素占 2 字节(红5绿6蓝5),总共约 65K 色。这是性能与色彩的平衡之选。

💡 提醒:不要盲目复制别人的初始化代码!不同厂家的模组可能略有差异。如果屏幕花屏或不亮,请优先检查是否匹配你的硬件版本。


如何写入图像?掌握“地址窗口 + RAMWR”机制

想在屏幕上画东西,核心就两步:

  1. 设定写入区域(地址窗口)
  2. 发送 RAMWR 命令,连续写入像素数据

设置地址窗口函数示例

void lcd_set_address_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { lcd_write_command(0x2A); // Column Address Set lcd_write_data(x1 >> 8); lcd_write_data(x1 & 0xFF); lcd_write_data(x2 >> 8); lcd_write_data(x2 & 0xFF); lcd_write_command(0x2B); // Page Address Set lcd_write_data(y1 >> 8); lcd_write_data(y1 & 0xFF); lcd_write_data(y2 >> 8); lcd_write_data(y2 & 0xFF); }

开始写像素数据

void lcd_draw_pixel(uint16_t x, uint16_t y, uint16_t color) { lcd_set_address_window(x, y, x, y); lcd_write_command(0x2C); // Write RAM lcd_write_data(color >> 8); lcd_write_data(color & 0xFF); }

color是 RGB565 格式的颜色值,例如红色为0xF800,绿色为0x07E0,蓝色为0x001F

批量写更快:

void lcd_fill_area(uint16_t x1, uint16_t y1, uint16_t w, uint16_t h, uint16_t *pixels) { uint32_t len = w * h; lcd_set_address_window(x1, y1, x1+w-1, y1+h-1); lcd_write_command(0x2C); for (uint32_t i = 0; i < len; i++) { lcd_write_data(pixels[i] >> 8); lcd_write_data(pixels[i] & 0xFF); } }

如果你的数据量大,强烈建议启用DMA 传输,避免 CPU 被阻塞。


实战避坑指南:那些年我们遇到的“灵异现象”

别笑,以下问题我都亲自踩过:

❌ 屏幕全白 / 全黑?

  • 检查 RST 是否有效复位
  • 是否漏发0x11(退出睡眠)或0x29(开启显示)
  • 背光有没有供电?

❌ 显示错位、偏移、倒置?

  • 查看0x36寄存器设置是否正确
  • 地址窗口坐标是否超出实际范围(如写了 320×240 却访问 0~320)
  • 某些模组默认是 240×320 竖屏,别被标签骗了!

❌ 颜色发紫、偏绿、像滤镜?

  • MCU 输出的是 RGB888?ILI9341 吃的是 RGB565!
  • 确保你在转换颜色格式时没搞反高低字节

❌ 刷新慢如幻灯片?

  • 当前 SPI 波特率是多少?试试把预分频调小
  • HAL_SPI_Transmit逐字节发?换成 DMA 批量传效率提升 3 倍+

工程优化技巧:让你的显示更流畅

掌握了基本操作后,可以进一步提升体验:

✅ 使用双缓冲机制

避免画面撕裂:一帧在后台绘制,完成后整体切换。

✅ 局部刷新代替全屏重绘

UI 变化局部更新,减少 SPI 数据量,显著提升响应速度。

✅ 加入背光 PWM 控制

通过定时器输出 PWM 到 BL 引脚,实现亮度调节,节能又护眼。

✅ 封装绘图库

封装画线、画圆、显示字符等基础函数,为后续引入 GUI 框架铺路。


结语:这不是终点,而是起点

当你第一次看到自己写的代码在彩屏上画出一个红色方块时,那种成就感是无与伦比的。

而 ILI9341 正是这样一个绝佳的跳板——它足够简单,让你快速入门;又足够强大,支撑你完成复杂的图形交互。

下一步,你可以尝试:

  • 移植 LVGL,在这上面做个仪表盘界面;
  • 接个触摸屏,做成 HMI 控制面板;
  • 配合 FATFS 读 SD 卡图片,做个电子相册。

一切可视化的大门,都从这一块小小的屏幕开始。

如果你正在学习嵌入式开发,不妨现在就拿出那块吃灰已久的 TFT 屏,接上线,烧段代码,亲手把它点亮吧!

🔧动手提示:推荐使用 Adafruit_ILI9341 库作为参考,结构清晰,注释完整,非常适合学习移植。

有什么问题欢迎留言交流,我们一起把“看不见”的系统,变成“看得见”的精彩世界。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/3 4:34:53

经济研究LaTeX模板终极使用指南:5步搞定专业论文排版

经济研究LaTeX模板终极使用指南&#xff1a;5步搞定专业论文排版 【免费下载链接】Chinese-ERJ 《经济研究》杂志 LaTeX 论文模板 - LaTeX Template for Economic Research Journal 项目地址: https://gitcode.com/gh_mirrors/ch/Chinese-ERJ 还在为学术论文的格式要求头…

作者头像 李华
网站建设 2026/5/8 6:45:03

TuneFree音乐播放器:完全免费畅享网易云VIP资源的技术指南

TuneFree音乐播放器&#xff1a;完全免费畅享网易云VIP资源的技术指南 【免费下载链接】TuneFree 一款基于Splayer进行二次开发的音乐播放器&#xff0c;可解析并播放网易云音乐中所有的付费资源。 项目地址: https://gitcode.com/gh_mirrors/tu/TuneFree 还在为心爱的歌…

作者头像 李华
网站建设 2026/5/5 15:16:39

vivado卸载入门教程:Linux平台手把手指导

Linux下彻底卸载Vivado&#xff1a;从清理残留到系统复原的实战指南你有没有遇到过这种情况&#xff1f;刚想安装新版Vivado&#xff0c;运行vivado命令时却弹出许可证错误&#xff1b;或者明明“删了”旧版本&#xff0c;终端还能调出GUI界面——这说明你的系统里还藏着一个“…

作者头像 李华
网站建设 2026/5/3 3:45:14

BetterNCM终极指南:快速打造个性化音乐播放器定制体验

BetterNCM终极指南&#xff1a;快速打造个性化音乐播放器定制体验 【免费下载链接】BetterNCM-Installer 一键安装 Better 系软件 项目地址: https://gitcode.com/gh_mirrors/be/BetterNCM-Installer 想要让单调的网易云音乐焕然一新吗&#xff1f;&#x1f3b5; 想象一…

作者头像 李华
网站建设 2026/5/1 17:22:14

VibeThinker-1.5B保姆级指南:小白10分钟上手,不用买GPU

VibeThinker-1.5B保姆级指南&#xff1a;小白10分钟上手&#xff0c;不用买GPU 你是不是一个想转行学编程的文科生&#xff1f;面对代码一头雾水&#xff0c;写个Python脚本都能报错十几行&#xff0c;网上搜解决方案又看不懂专业术语&#xff1f;别急&#xff0c;现在有个“A…

作者头像 李华
网站建设 2026/5/1 11:31:08

PaddlePaddle模型微调实战:云端GPU 5分钟部署,新功能秒试

PaddlePaddle模型微调实战&#xff1a;云端GPU 5分钟部署&#xff0c;新功能秒试 你是不是也遇到过这样的场景&#xff1f;AI产品经理临时接到客户紧急需求&#xff0c;要演示一个定制化OCR识别系统——比如能精准识别发票、合同或特殊字体的文档内容。IT部门说排期至少两周&a…

作者头像 李华