
1. 初识FBTFTSPI显示屏的救星第一次接触嵌入式开发时我被SPI显示屏的配置问题折磨得够呛。直到发现了FBTFT这个神器它就像给Linux系统装上了显示屏翻译器让那些非标准SPI屏幕也能轻松工作。FBTFT本质上是一个Linux内核帧缓冲驱动框架专门为各种小型LCD屏提供支持。你可能遇到过这种情况买了一块便宜的ST7789或ILI9341屏幕却发现官方内核没有预装驱动。这时候FBTFT就能大显身手了。它通过软件模拟的方式把SPI接口的显示屏映射成标准的Linux帧缓冲设备/dev/fbX让系统认为这就是块普通显示屏。实测下来从240x240的小屏到320x480的中等尺寸FBTFT都能稳定驱动。这个方案特别适合树莓派、香橙派等开发板用户。我最近就用它在一台全志H3开发板上点亮了中景园的ST7789屏幕整个过程比想象中简单。下面我会手把手带你走完整个流程包括硬件连接、内核配置、驱动移植这些关键步骤。2. 硬件准备与接线指南2.1 物料清单检查在开始前你需要准备以下硬件开发板树莓派/香橙派等SPI接口LCD屏如ST7789、ILI9341杜邦线若干可选逻辑分析仪调试用以常见的ST7789 240x240屏幕为例它的引脚通常包括VCC/GND电源SCLSPI时钟线SDASPI数据线RES复位引脚DC数据/命令选择CS片选信号2.2 接线避坑指南接SPI屏最常犯的错误就是引脚接反。我建议先用万用表确认开发板的SPI引脚定义不同开发板的SPI0引脚位置可能完全不同。比如在树莓派上SPI0_CLKGPIO11SPI0_MOSIGPIO10SPI0_CS0GPIO8而在香橙派Zero上SPI0_CLKPC2SPI0_MOSIPC0SPI0_CS0PC3实际接线时要注意电平匹配。有些3.3V的屏幕接到5V开发板上会烧毁这时候需要电平转换模块。我第一次就犯了这个错误导致屏幕冒烟损失了50大洋。3. 内核配置与驱动移植3.1 启用FBTFT内核模块现代Linux内核已经内置了FBTFT驱动但默认可能没启用。通过menuconfig配置make menuconfig依次进入Device Drivers - Staging drivers - Support for small TFT LCD display modules - M FB driver for the ST7789V LCD controller记得把对应的控制器编译为模块M这样方便后期调试。3.2 添加自定义设备配置FBTFT采用设备描述驱动实现的架构。我们需要在drivers/staging/fbtft/fbtft_device.c中添加设备信息。找到displays数组在末尾新增{ .name my_st7789, // 自定义设备名 .spi (struct spi_board_info) { .modalias fb_st7789v, // 驱动名称 .max_speed_hz 64000000, // SPI时钟频率 .mode SPI_MODE_0, // SPI模式 .platform_data (struct fbtft_platform_data) { .display { .buswidth 8, // 数据位宽 .backlight 1, // 背光控制 }, .gpios (const struct fbtft_gpio []) { { reset, 25 }, // 复位引脚 { dc, 24 }, // DC引脚 { led, 18 }, // 背光引脚 }, } } }这里的gpios要根据实际接线修改。我曾经因为把DC和RESET引脚搞反导致屏幕一直白屏调试了整整一天。4. 驱动开发实战4.1 编写初始化序列每个LCD控制器都需要特定的初始化序列。新建st7789v.c驱动文件关键部分如下static int init_display(struct fbtft_par *par) { // 硬件复位 par-fbtftops.reset(par); mdelay(120); // 必须的延时 // 初始化命令序列 write_reg(par, 0x11); // 退出睡眠模式 mdelay(120); write_reg(par, 0x3A, 0x05); // 设置颜色格式 write_reg(par, 0xB2, 0x0C, 0x0C, 0x00, 0x33, 0x33); // 门控控制 write_reg(par, 0xB7, 0x35); // 门电压设置 write_reg(par, 0x21); // 反色模式 write_reg(par, 0x29); // 开启显示 return 0; }这些命令来自屏幕的数据手册。有个技巧先用逻辑分析仪抓取厂商demo板的初始化序列能省去很多调试时间。4.2 实现显存操作设置显存窗口的函数很关键static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) { write_reg(par, 0x2A, xs8, xs0xFF, xe8, xe0xFF); // 列地址设置 write_reg(par, 0x2B, ys8, ys0xFF, ye8, ye0xFF); // 行地址设置 write_reg(par, 0x2C); // 开始写入内存 }这里要注意坐标系统。有些屏幕的(0,0)点在左下角有些在右上角写错会导致显示内容上下或左右颠倒。5. 调试与性能优化5.1 常见问题排查当屏幕出现花屏、闪烁时可以按以下步骤检查用示波器查看SPI信号质量检查电源是否稳定建议并联100μF电容降低SPI时钟频率测试确认初始化序列中的延时是否足够我曾经遇到一个诡异问题屏幕在低温下工作不正常。后来发现是复位时序不够长修改mdelay(120)为mdelay(150)后解决。5.2 提升刷新率技巧默认配置下240x240屏幕的刷新率可能只有10fps左右。通过以下方法可以优化提高SPI时钟频率最高不超过屏幕规格使用DMA传输模式修改fbtft的dirty区域更新机制在香橙派H3上经过优化后我的ST7789屏幕能达到30fps的刷新率足够流畅显示简单动画。6. 进阶应用实例6.1 整合到桌面系统想让屏幕显示系统桌面需要配置Xorgsudo apt install xserver-xorg-video-fbdev然后在/usr/share/X11/xorg.conf.d/99-fbdev.conf中添加Section Device Identifier myLCD Driver fbdev Option fbdev /dev/fb1 EndSection这样就能把SPI屏作为扩展显示器使用了。不过要注意复杂的图形界面可能会很卡建议使用轻量级桌面如LXDE。6.2 开发图形应用基于帧缓冲开发GUI应用很简单。以下是用Python显示图片的示例import pygame pygame.init() screen pygame.display.set_mode((240,240)) image pygame.image.load(test.jpg) screen.blit(image, (0,0)) pygame.display.flip()对于嵌入式设备可以考虑使用LVGL这样的轻量级图形库它能很好地与FBTFT配合工作。