嵌入式Linux SPI TFT屏驱动实战:从设备树到开机自启的完整调试指南
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>;
};
};
这里有几个关键点需要注意:
- status必须设为"okay"启用SPI控制器
- cs-gpios指定片选引脚,根据实际硬件连接修改
- compatible属性要与驱动匹配
- 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或其他开源项目获取。
驱动移植主要涉及三个文件:
- st7735s.c - 屏幕专用驱动
- fbtft_device.c - 设备注册
- 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"
常见错误包括:
- 引脚配置错误 - 检查设备树中的GPIO编号
- SPI频率过高 - 降低spi-max-frequency试试
- 电源不足 - 确保使用2A以上的电源
- 屏幕初始化序列错误 - 核对规格书中的命令
屏幕显示异常时,可以尝试以下调整:
- 修改rotate参数(0,90,180,270)
- 调整fps值,避免闪烁
- 检查颜色格式设置(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传输效率,可以尝试以下优化:
- 启用DMA传输
- 调整SPI时钟分频
- 使用双缓冲机制
最后,如果项目需要触摸功能,还需要配置触摸屏驱动。这通常涉及另一个SPI设备或I2C接口,需要额外注意中断引脚的配置。
更多推荐



所有评论(0)