树莓派点亮ILI9341:从驱动配置到帧缓冲显示全指南

📅 发布时间:2026/9/16 11:21:21
树莓派点亮ILI9341:从驱动配置到帧缓冲显示全指南
简介面向嵌入式开发者的轻量级ILI9341驱动源码包配合芯片技术详解帮助读者解决TFT液晶屏初始化、绘图、显示文本等驱动开发难题。适用于电子竞赛、课程设计、智能设备界面开发等场景也适合正在从基础模块向寄存器级编程进阶的嵌入式学习者。压缩包内含1个ili9341.c源文件整体大小约2KB代码精简便于快速移植到Arduino、Raspberry Pi等常用平台可单独阅读也可作为配套工程的一部分。ILI9341是一颗支持800x480分辨率、16.7M色、SPI与8/16位并行接口的TFT液晶控制器在智能手机、导航仪、工业控制显示面板中都有广泛应用。驱动源码覆盖芯片复位、初始化序列、写命令/写数据、清屏、绘制基本图形和文本显示等关键环节并预留扩展接口读者可在此基础上进一步实现触摸交互、图像显示等功能有效缩短显示模块的调试周期。目前已有233人学习下载适合对LCD底层驱动原理感兴趣并希望在实际项目里快速应用ILI9341的开发者。1. 为什么你的 ili9341 插上树莓派只亮背光ili9341_这个标题像随手起的工程名但至少见过这块屏的人都会把它补完。ILI9341 是一颗几乎统治了 2.4/2.8 寸 SPI 液晶模组的驱动 IC从 Arduino 到树莓派都能遇到它。难点不在焊接而在树莓派上“点亮后没法好好用”默认 HDMI 占着 fb0屏幕却自己注册成 fb1背光亮着却在跑雪花旋转方向、触摸坐标、刷新率全是坑。这篇文章会从树莓派官方内核里已有的 fbtft 驱动出发给出最小可复现的 config.txt 配置、设备树参数和排错手段适合第一次碰 SPI LCD或想把这块小屏做成监控面板的工程师。2. ILI9341 的官方驱动在哪fbtft、overlay 与设备树2.1 没有“安装包”驱动早就编进树莓派内核了不少人搜索“ili9341 树莓派官方驱动”期望在 GitHub 上下载一个驱动源码包编译安装。实际情况是树莓派 OS 的内核里已经把上游 fbtft 子系统的ili9341驱动编译进去了树莓派官方固件又额外提供了一个名为rpi-display的设备树 overlay把驱动实例挂到 SPI0 的 CE0 上。也就是说官方驱动的形态是“内核模块 设备树 overlay”不是一个独立安装包。在这种架构下点亮屏幕要做的不是装驱动而是让内核在启动阶段创建一个名为ili9341的 SPI 设备并把它注册成/dev/fb1。fbtft 是一个把液晶控制器抽象成 Linux 帧缓冲framebuffer的框架它负责类型无关的那部分内存映射、刷新机制、颜色格式转换具体的 ILI9341 寄存器序列则写在drivers/staging/fbtft/fb_ili9341.c里包括 INITGAMMA、MADCTL、COLOR 等初始化命令。2.2 三种点亮 ILI9341 的方式与选型在树莓派上接入 ILI9341常见的路径大致有三条它们之间的选择直接决定你后面能不能顺利叠加触摸、旋转和终端。接入方式配置入口适合谁与官方内核的关系dtoverlayrpi-display/boot/config.txt绝大多数串口 SPI 屏用户官方固件自带推荐首选dtoverlayfbtft 参数动态指定 name/boot/config.txt需要调整片选、GPIO 复用的高级用户基于内核 fbtft 模块DRM/KMS 面板驱动内核配置 设备树需要硬解旋转、合成画面主线新方案树莓派固件覆盖还不完整rpi-display这个名字容易让人以为它只适配某种特定型号的屏实际上它正是针对 ILI9341 这类 320x240 面板定制的 overlay把 compatible 指向ilitek,ili9341。我一般会直接用这个 overlay只有需要把屏幕挂到 SPI1、SPI2 或者换成非标引脚时才退回fbtft参数化方式。DRM 方案更现代但在树莓派上还没有成为开箱即用的默认路线暂不作为新手首选。2.3 从设备树反编译确认 overlay 的真实参数官方固件里的 overlay 文件是编译过的二进制 DTB想看它到底暴露了哪些参数可以用设备树编译器解包不用去猜测 READMEsudo apt install device-tree-compiler dtc -I dtb -O dts /boot/overlays/rpi-display.dtbo 2/dev/null | grep -E compatible|rotate|speed|fps这个命令把rpi-display.dtbo反编译成可读的 DTS 文本然后过滤出驱动绑定和可调参数。逻辑上dtc -I dtb告诉工具输入是二进制设备树-O dts要求输出明文源码2/dev/null丢弃反编译过程中的警告噪音。看到输出里有ilitek,ili9341以及rotate、speed、fps这些属性名说明这块 overlay 就是可配置的 ILI9341 驱动入口后面所有调参都是往这里走。3. 点亮 ILI9341 的最小步骤SPI、config.txt 与帧缓冲验证3.1 开启 SPI 总线并装载 rpi-display overlay第一步先把树莓派的 SPI 主控制器打开否则设备树里的spi0.0节点不会被挂载驱动。命令行方式比进入raspi-config逐层点更快sudo raspi-config nonint do_spi 0 echo dtoverlayrpi-display | sudo tee -a /boot/config.txt sudo rebootraspi-config nonint是它在非交互模式下的接口do_spi 0表示把 SPI 设为启用tee -a把 overlay 配置追加到/boot/config.txt末尾。重启后可以检查两处/dev/fb*里是不是多了 fb1以及dmesg里是否出现 fbtft 与 ILI9341 的注册信息。注意如果 config.txt 里已有过dtoverlayrpi-display先删掉旧行再追加重复覆盖不会叠加生效反而可能因参数冲突启动失败。3.2 确认 /dev/fb1 与内核日志重启后依次执行下面三条命令ls -l /dev/fb* dmesg | grep -iE fbtft|ili9341 sudo fbi -d /dev/fb1 -T 1 ./test.png第一行确认 fb 设备数量第二行看内核日志里驱动实例名和 SPI 速率如果看到fb1: fbtft相关的注册行说明驱动已经跑起来了第三行用fbi把一个测试图片直接画到 fb1 上-d指定设备-T指定虚拟终端。fbi 需要 root 权限因为/dev/fb1默认属主是 root:video。如果屏幕上出现完整画面说明 SPI 接线、供电、驱动链路全部正常接下来的旋转和触摸才有意义。3.3 用 numpy 往帧缓冲写一张渐变图没有现成图片时可以直接往/dev/fb1的映射内存里写像素这是验证帧缓冲最干净的手段不依赖任何图形库import mmap import time import numpy as np # 从 sysfs 读取 fb1 的实际分辨率避免手动猜横竖方向 with open(/sys/class/graphics/fb1/virtual_size) as f: w, h map(int, f.read().strip().split(,)) with open(/dev/fb1, rb) as fb: fb_map mmap.mmap(fb.fileno(), w * h * 2, accessmmap.ACCESS_WRITE) # 构造 RGB565 渐变帧R 随 x 变化G 随 x 一次方变化B 随 y 变化 y, x np.mgrid[0:h, 0:w] r (x * 31 // (w - 1)).astype(np.uint16) 11 g (x * 63 // (w - 1)).astype(np.uint16) 5 b (y * 31 // (h - 1)).astype(np.uint16) frame (r | g | b).astype(u2) # 小端 RGB565 # 连续写 120 帧模拟 60fps 的写入节奏 for _ in range(120): fb_map[:] frame.tobytes() time.sleep(0.016) fb_map.close()这段代码的关键在virtual_size的读取fb1 在旋转后可能是 320x240也可能是 240x320直接读 sysfs 比硬编码安全。RGB565 的位布局是高 5 位红、中间 6 位绿、低 5 位蓝所以r左移 11 位、g左移 5 位、b直接放低位最后转成小端字节序。平滑渐变不花屏说明像素格式和内存长度都正确。4. 把 ILI9341 调到能用的状态旋转、分辨率与触摸参数4.1 三个最常改的 overlay 参数rotate、speed、fps点亮只是一个开始绝大多数用户卡在“画面方向不对”和“刷新慢”上。rpi-display暴露的参数里最有价值的三个是参数常见取值作用与踩坑rotate0 / 90 / 180 / 270顺时针旋转画面0 是面板物理正向排线在侧面的模组往往要用 90 或 270speed16000000 / 32000000SPI 通信时钟单位 Hz跳线过长时 32MHz 容易花屏降到 16MHzfps20 / 25 / 30fbtft 的内置刷新上限设得太高会让 CPU 花费大量时间在刷屏上设置方式是在/boot/config.txt的dtoverlay后面追加参数dtoverlayrpi-display,speed32000000,rotate90,fps30rotate90在 fbtft 里是软旋转驱动会交换画面的宽高并改写 MADCTL 寄存器比在应用层做坐标变换省事得多。speed是 SPI 时钟不是帧率两回事如果屏幕出现雪花状噪声直接看这一项。fps适合作为上限保护实际吞吐还受总线带宽限制所以不要指望调到 60 帧2.4 寸串口屏能稳定 25 帧已经够看了。4.2 背面触摸屏 XPT2046 的设备树接入与校准大部分 3.5 寸的 ILI9341 模组背面还带着一块 XPT2046 触摸芯片它与 TI 的 ADS7846 兼容树莓派官方固件里同样有 overlay。触摸屏和显示共用 SPI0但片选要错开显示用 CE0触摸用 CE1。dtoverlayads7846,cs1,penirq25,penirq_pull2,speed2000000,swapxy1cs1表示使用 SPI0 的 CE1避免与屏幕的 CE0 冲突penirq指定触摸中断引脚25 是一个对外设冲突较少的 GPIOpenirq_pull2启用内部上拉防止浮空误触发speed2000000是触摸芯片的 SPI 采样时钟不需要跟着屏幕跑到 32MHz保持低速率更抗干扰。校准方式是在 X 环境下安装并运行校准器sudo apt install xinput-calibrator DISPLAY:0 xinput_calibrator --device $(evtest --query /dev/input/event* 21 | sed -n s/.*\(ADS7846[^]*\).*/\1/p)先重启一次让ads7846自动生成 input 设备再用evtest逐个确认设备名最后用校准器生成一组五点的校准矩阵。走过这个流程后触控坐标就会和显示像素对齐不用在应用层再写坐标换算。4.3 一份可直接抄的 config.txt 完整片段把前面内容合成一份可复制的配置按顺序写在/boot/config.txt即可dtparamspion dtoverlayrpi-display,speed32000000,rotate90,fps30 dtoverlayads7846,cs1,penirq25,penirq_pull2,speed2000000,swapxy1dtparamspion和raspi-config nonint do_spi 0等价写进文件里更不容易被后续操作覆盖。第一行和第二行的顺序有讲究必须先保证 SPI 控制器存在overlay 才能把子设备挂上去第三行与第二行互不干扰可以并行存在。swapxy 是否保留取决于触摸屏模组若校准后 Y 轴反向就把它去掉。提示如果你用的是只有 4 根 SPI 线的裸屏没有触摸芯片第三行不要加否则 dmesg 里会出现 CS1 设备挂载失败的错误虽然不影响显示但会污染日志排查视线。5. ILI9341 花屏排查与把它变成串口日志终端5.1 白屏、花屏、颜色错误分别是什么原因亮度正常但画面乱是串口屏最常见的失败模式先按症状分类再动手。现象优先检查项背光亮、全白VCC 电压不足、RESET 引脚被拉低、DC 引脚接错 GPIO斜向雪花/横纹SPI 时钟过高speed降到 16000000杜邦线长度超过 15cm颜色反相dtoverlayrpi-display追加invert1屏幕偏暗LED 背光引脚供电不够需要单独接 3.3V 或 5V看模组标识花屏问题里SPI 速率过高的比例最大。树莓派的 SPI 主控能跑到 100MHz 不代表模块能跟上fbtft 的speed参数是直接写给 SPI 驱动的请求速率出错时优先减半。还有一个隐蔽问题DCRS引脚在很多模块上标为DC但某些厂商会标成RS或A0接错时初始化指令全部错位表现就是白屏或纯色屏不一定是驱动问题。5.2 让 ILI9341 常驻滚动日志con2fbmap 与 fbterm 组合屏幕大部分时间不用来跑 GUI而是当作服务器监控副屏最省资源的做法是把 Linux 控制台直接映射到 fb1 上。con2fbmap可以把指定虚拟终端绑定到 fb1再用fbterm提供不依赖 X 的文字渲染sudo con2fbmap 1 1 sudo chvt 1 sudo fbterm -s 16 -- /bin/bashcon2fbmap的第一个参数是 tty 编号第二个参数是 fb 编号合起来的意思是把 tty1 从 HDMI 的 fb0 移动到 ILI9341 的 fb1 上。之后chvt 1切换到该终端fbterm 就会以 16 号字体渲染文本。这时在 fbterm 里面执行sudo fbterm -s 16 -- tail -f /var/log/syslogfbterm 是把终端输出画到帧缓冲而不是走显卡合成因此屏幕小也不卡。如果想要日志自动带时间过滤可以把它包到/etc/rc.local里配合systemctl把 tty1 的登录 shell 替换成 fbterm整个 ILI9341 就变成一块常年滚动的 syslog 终端屏不再依赖任何桌面环境占的内存比一张浏览器标签页还小。本文还有配套的精品资源点击获取