1. SPI TFT屏驱动开发入门指南

第一次接触嵌入式Linux下的SPI TFT屏驱动开发时,我完全被各种专业术语搞晕了。SPI接口、设备树、内核模块...这些概念对新手来说确实不太友好。不过别担心,经过几个项目的实战,我发现只要掌握几个关键点,搞定一块SPI屏幕其实并不难。

SPI(Serial Peripheral Interface)是一种常见的串行通信协议,在嵌入式系统中广泛用于连接各种外设。相比并行接口,SPI只需要4根线就能实现数据传输,特别适合小型TFT显示屏。我们常见的ST7735S、ILI9341等屏幕都支持SPI接口。

在Linux系统中,fbtft驱动框架专门用于支持这类小型TFT显示屏。它提供了一套统一的接口,开发者只需要针对具体屏幕型号进行少量适配,就能快速实现显示功能。我最近在一个全志H3开发板上成功驱动了ST7735S屏幕,整个过程虽然踩了不少坑,但最终效果令人满意。

开发环境准备很简单:一块支持SPI的嵌入式开发板(比如NanoPi-NEO)、SPI接口的TFT屏幕、5V电源,以及安装了Ubuntu的PC机。建议使用16.04或18.04版本,这两个版本的稳定性经过验证。全志H3这类主流芯片都有完善的社区支持,遇到问题容易找到解决方案。

2. 设备树配置详解

设备树(Device Tree)是嵌入式Linux中描述硬件的重要机制。第一次修改设备树时,我完全摸不着头脑,但现在回头看,其实逻辑很清晰。以全志H3平台为例,设备树文件通常位于linux/arch/arm/boot/dts目录下。

对于SPI TFT屏,我们需要重点关注spi0节点。下面是一个典型的配置示例:

&spi0 {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&spi0_pins &spi0_cs_pins>;
    cs-gpios = <&pio 6 9 GPIO_ACTIVE_HIGH>;
    
    matrix: matrix@0 {
        compatible = "fb_st7735s";
        reg = <0>;
        status = "okay";
        spi-max-frequency = <32000000>;
        fps = <33>;
        rotate = <90>;
        buswidth = <8>;
        dc-gpios = <&pio 0 17 GPIO_ACTIVE_HIGH>;
        reset-gpios = <&pio 0 3 GPIO_ACTIVE_HIGH>;
        debug = <0x0>;
    };
};

这里有几个关键点需要注意:

  1. status必须设为"okay"启用SPI控制器
  2. cs-gpios指定片选引脚,根据实际硬件连接修改
  3. compatible属性要与驱动匹配
  4. dc-gpios和reset-gpios根据屏幕规格书配置

引脚冲突是常见问题。我曾经遇到过SPI和UART引脚复用冲突,导致屏幕无法正常工作。解决方法是在pinctrl节点中明确配置:

&pio {
    spi0_cs_pins: spi0_cs_pins {
        pins = "PG9"; 
        function = "gpio_out";
    };
};

另一个坑是HDMI输出冲突。很多开发板默认启用HDMI,会导致SPI屏幕无显示。需要在设备树中禁用HDMI:

&hdmi {
    status = "disabled";
};

3. 内核驱动移植实战

Linux主线内核通常已经包含了fbtft驱动框架,但具体型号的屏幕驱动可能需要自行添加。以ST7735S为例,如果内核中没有对应驱动,可以从厂商SDK或其他开源项目获取。

驱动移植主要涉及三个文件:

  1. st7735s.c - 屏幕专用驱动
  2. fbtft_device.c - 设备注册
  3. Makefile/Kconfig - 编译配置

在st7735s.c中,最重要的是初始化序列和分辨率设置。我遇到的一个典型问题是屏幕旋转后显示异常,需要在驱动中调整起始坐标:

static int init_display(struct fbtft_par *par)
{
    /* 初始化命令序列 */
    write_reg(par, 0x11); // Sleep out
    mdelay(120);
    write_reg(par, 0x36, 0xA0); // 设置旋转方向
    write_reg(par, 0x3A, 0x05); // 颜色格式
    /* 更多初始化命令... */
    return 0;
}

fbtft_device.c需要添加设备信息,确保与设备树匹配:

{
    .name = "matrix-st7735s",
    .spi = &(struct spi_board_info) {
        .modalias = "fb_st7735s",
        .max_speed_hz = 32000000,
        .bus_num = 0,
        .chip_select = 0,
        .mode = SPI_MODE_0,
        .platform_data = &(struct fbtft_platform_data) {
            .display = {
                .buswidth = 8,
            },
            .gpios = (const struct fbtft_gpio []) {
                { "reset", 3 },
                { "dc", 17 },
                { "led", 1 },
            },
        }
    }
}

配置内核时,需要勾选相关选项:

Device Drivers → Staging drivers → Support for small TFT LCD display modules

然后选择具体的屏幕驱动,编译为模块(.ko)形式便于调试。

4. 调试技巧与问题排查

驱动开发过程中,调试是最耗时的环节。掌握有效的调试方法可以事半功倍。我最常用的工具是dmesg,它能显示内核日志信息。

加载驱动模块时遇到问题,可以这样排查:

sudo insmod fbtft_device.ko name=matrix-st7735s busnum=0 gpios="reset:3,dc:17"
dmesg | grep "fb"

常见错误包括:

  1. 引脚配置错误 - 检查设备树中的GPIO编号
  2. SPI频率过高 - 降低spi-max-frequency试试
  3. 电源不足 - 确保使用2A以上的电源
  4. 屏幕初始化序列错误 - 核对规格书中的命令

屏幕显示异常时,可以尝试以下调整:

  1. 修改rotate参数(0,90,180,270)
  2. 调整fps值,避免闪烁
  3. 检查颜色格式设置(RGB565/RGB888)

我曾经遇到屏幕上半部分显示异常的问题,最终发现是驱动中的分辨率设置与设备树不匹配。修改以下参数后解决:

#define DEFAULT_WIDTH 128
#define DEFAULT_HEIGHT 128

另一个有用的技巧是通过debug参数输出调试信息:

debug = <0x7>; // 启用所有调试级别

5. 开机自动加载配置

调试成功后,我们需要让系统开机自动加载驱动。这需要几个步骤:

首先,将编译好的.ko文件复制到文件系统:

sudo cp fb_st7735s.ko /lib/modules/$(uname -r)/kernel/drivers/staging/fbtft/
sudo cp fbtft_device.ko /lib/modules/$(uname -r)/kernel/drivers/staging/fbtft/

然后更新模块依赖关系:

sudo depmod -a

创建/etc/modules-load.d/fbtft.conf文件,内容为:

fb_st7735s
fbtft_device

配置模块参数,创建/etc/modprobe.d/fbtft.conf:

options fbtft_device name=matrix-st7735s busnum=0 gpios=reset:3,dc:17 rotate=90

最后,可以测试配置是否正确:

sudo modprobe -r fb_st7735s fbtft_device
sudo modprobe fb_st7735s fbtft_device

如果一切正常,重启后屏幕应该能自动点亮。我在实际项目中发现,有时模块加载顺序会影响显示效果。如果遇到问题,可以尝试在/etc/rc.local中添加延迟:

sleep 3
modprobe fb_st7735s
modprobe fbtft_device

6. 进阶优化与图形界面集成

基础功能实现后,我们可以进一步优化显示效果。fbtft支持多种像素格式,通过修改设备树的buswidth和驱动中的颜色格式设置,可以获得更好的显示效果。

对于需要图形界面的项目,可以配置FrameBuffer作为显示输出。修改/usr/share/X11/xorg.conf.d/99-fbdev.conf:

Section "Device"
    Identifier "FBDEV"
    Driver "fbdev"
    Option "fbdev" "/dev/fb0"
EndSection

调整控制台字体大小,改善命令行显示体验:

sudo apt install console-setup
sudo dpkg-reconfigure console-setup

为了提高SPI传输效率,可以尝试以下优化:

  1. 启用DMA传输
  2. 调整SPI时钟分频
  3. 使用双缓冲机制

最后,如果项目需要触摸功能,还需要配置触摸屏驱动。这通常涉及另一个SPI设备或I2C接口,需要额外注意中断引脚的配置。

更多推荐