1. 硬件准备与引脚分析在开始移植FBTFT驱动之前首先要确保硬件连接正确。LuckFox Pico开发板通过SPI接口与LCD屏幕通信我们需要明确每个引脚的功能定义。以ST7735和GC9306两款屏幕为例它们的典型引脚包括SCKSPI时钟信号MOSISPI主设备输出从设备输入CS片选信号低电平有效DC数据/命令选择线RESET硬件复位线BL背光控制实际项目中我遇到过引脚复用冲突的问题。比如某次调试时发现屏幕无响应最终发现是因为SPI0的MISO引脚被默认配置为UART功能。解决方法是在设备树中注释掉相关UART节点就像这样uart4 { status disabled; // 释放GPIO1_PC3引脚 };2. 设备树配置实战设备树(DTS)是Linux内核识别硬件的关键。对于SPI LCD的配置需要重点关注以下几个部分2.1 GPIO引脚定义首先为每个控制引脚创建节点例如背光控制引脚gpio0pa4: gpio0pa4 { compatible regulator-fixed; pinctrl-names default; pinctrl-0 gpio0_pa4; regulator-name gpio0_pa4; regulator-always-on; };2.2 SPI控制器配置配置SPI0控制器时需要特别注意时钟频率的设置。根据我的实测ST7735在6MHz下工作稳定而GC9306可以跑到24MHzspi0 { status okay; pinctrl-0 spi0m0_pins; spi-max-frequency 6000000; // 6MHz时钟 lcd: lcd0 { compatible sitronix,st7735; reg 0; spi-cpol; // 时钟极性 spi-cpha; // 时钟相位 rotate 0; // 显示方向 }; };3. 内核驱动移植详解3.1 Makefile修改在drivers/staging/fbtft/Makefile中添加驱动编译选项obj-$(CONFIG_FB_TFT_ST7735) fb_st7735.o obj-$(CONFIG_FB_TFT_GC9306) fb_gc9306.o3.2 Kconfig配置为驱动添加菜单选项config FB_TFT_ST7735 tristate FB driver for ST7735 LCD depends on FB_TFT help Support for ST7735 based displays3.3 核心驱动修改由于内核版本差异fbtft-core.c可能需要适配。关键修改点包括GPIO请求函数改造static int fbtft_request_one_gpio(struct fbtft_par *par, const char *name, int index, struct gpio_desc **gpiop) { // 添加OF_GPIO_ACTIVE_LOW标志处理 flags (of_flags OF_GPIO_ACTIVE_LOW) ? GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH; }复位时序优化static void fbtft_reset(struct fbtft_par *par) { gpiod_set_value_cansleep(par-gpio.reset, 1); usleep_range(20, 40); gpiod_set_value_cansleep(par-gpio.reset, 0); msleep(120); }4. 屏幕驱动开发实战4.1 ST7735驱动实现初始化序列需要严格按照数据手册编写static int init_display(struct fbtft_par *par) { write_reg(par, 0xB1, 0x05, 0x3C, 0x3C); // 帧率控制 write_reg(par, 0xC0, 0x28, 0x08, 0x04); // 电源控制1 write_reg(par, 0x36, 0xC0); // 内存访问控制 write_reg(par, MIPI_DCS_SET_DISPLAY_ON); // 开启显示 return 0; }4.2 GC9306驱动特点GC9306需要特殊的Gamma校正设置static int set_gamma(struct fbtft_par *par, u32 *curves) { write_reg(par, 0xF0, 0x02, 0x00, 0x00, 0x1B, 0x1F, 0x0B); write_reg(par, 0xF1, 0x01, 0x03, 0x00, 0x28, 0x2B, 0x0E); return 0; }5. 驱动验证与调试编译烧录后通过以下命令验证驱动查看内核日志dmesg | grep fb_ # 正常应显示类似 # fb_gc9306 frame buffer, 240x320, 150 KiB video memory测试屏幕显示# 花屏测试 cat /dev/urandom /dev/fb0 # 清屏测试 cat /dev/zero /dev/fb0常见问题排查屏幕白屏检查背光电路和BL引脚配置显示错位确认rotate参数和扫描方向设置颜色异常检查SPI数据位宽和像素格式6. 进阶优化建议性能调优增大SPI时钟频率需确保信号质量启用DMA传输减少CPU占用调整fps参数平衡刷新率和功耗电源管理lcd: lcd0 { power-supply vcc_lcd; // 添加电源控制 backlight backlight; // 背光控制节点 };多屏幕支持spi0 { lcd1: lcd0 { reg 0; }; lcd2: lcd1 { reg 1; }; // 第二个屏幕 };移植过程中最耗时的往往是硬件时序调试。建议准备逻辑分析仪观察SPI波形确保时钟极性(CPOL)和相位(CPHA)设置与屏幕规格一致。我曾遇到某款GC9306屏幕必须设置CPHA1才能正常显示而数据手册却标注为可选这种特殊情况只能通过实际测试验证。
【LuckFox Pico】SPI LCD驱动移植实战:基于FBTFT适配ST7735与GC9306
发布时间:2026/6/11 19:12:08
1. 硬件准备与引脚分析在开始移植FBTFT驱动之前首先要确保硬件连接正确。LuckFox Pico开发板通过SPI接口与LCD屏幕通信我们需要明确每个引脚的功能定义。以ST7735和GC9306两款屏幕为例它们的典型引脚包括SCKSPI时钟信号MOSISPI主设备输出从设备输入CS片选信号低电平有效DC数据/命令选择线RESET硬件复位线BL背光控制实际项目中我遇到过引脚复用冲突的问题。比如某次调试时发现屏幕无响应最终发现是因为SPI0的MISO引脚被默认配置为UART功能。解决方法是在设备树中注释掉相关UART节点就像这样uart4 { status disabled; // 释放GPIO1_PC3引脚 };2. 设备树配置实战设备树(DTS)是Linux内核识别硬件的关键。对于SPI LCD的配置需要重点关注以下几个部分2.1 GPIO引脚定义首先为每个控制引脚创建节点例如背光控制引脚gpio0pa4: gpio0pa4 { compatible regulator-fixed; pinctrl-names default; pinctrl-0 gpio0_pa4; regulator-name gpio0_pa4; regulator-always-on; };2.2 SPI控制器配置配置SPI0控制器时需要特别注意时钟频率的设置。根据我的实测ST7735在6MHz下工作稳定而GC9306可以跑到24MHzspi0 { status okay; pinctrl-0 spi0m0_pins; spi-max-frequency 6000000; // 6MHz时钟 lcd: lcd0 { compatible sitronix,st7735; reg 0; spi-cpol; // 时钟极性 spi-cpha; // 时钟相位 rotate 0; // 显示方向 }; };3. 内核驱动移植详解3.1 Makefile修改在drivers/staging/fbtft/Makefile中添加驱动编译选项obj-$(CONFIG_FB_TFT_ST7735) fb_st7735.o obj-$(CONFIG_FB_TFT_GC9306) fb_gc9306.o3.2 Kconfig配置为驱动添加菜单选项config FB_TFT_ST7735 tristate FB driver for ST7735 LCD depends on FB_TFT help Support for ST7735 based displays3.3 核心驱动修改由于内核版本差异fbtft-core.c可能需要适配。关键修改点包括GPIO请求函数改造static int fbtft_request_one_gpio(struct fbtft_par *par, const char *name, int index, struct gpio_desc **gpiop) { // 添加OF_GPIO_ACTIVE_LOW标志处理 flags (of_flags OF_GPIO_ACTIVE_LOW) ? GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH; }复位时序优化static void fbtft_reset(struct fbtft_par *par) { gpiod_set_value_cansleep(par-gpio.reset, 1); usleep_range(20, 40); gpiod_set_value_cansleep(par-gpio.reset, 0); msleep(120); }4. 屏幕驱动开发实战4.1 ST7735驱动实现初始化序列需要严格按照数据手册编写static int init_display(struct fbtft_par *par) { write_reg(par, 0xB1, 0x05, 0x3C, 0x3C); // 帧率控制 write_reg(par, 0xC0, 0x28, 0x08, 0x04); // 电源控制1 write_reg(par, 0x36, 0xC0); // 内存访问控制 write_reg(par, MIPI_DCS_SET_DISPLAY_ON); // 开启显示 return 0; }4.2 GC9306驱动特点GC9306需要特殊的Gamma校正设置static int set_gamma(struct fbtft_par *par, u32 *curves) { write_reg(par, 0xF0, 0x02, 0x00, 0x00, 0x1B, 0x1F, 0x0B); write_reg(par, 0xF1, 0x01, 0x03, 0x00, 0x28, 0x2B, 0x0E); return 0; }5. 驱动验证与调试编译烧录后通过以下命令验证驱动查看内核日志dmesg | grep fb_ # 正常应显示类似 # fb_gc9306 frame buffer, 240x320, 150 KiB video memory测试屏幕显示# 花屏测试 cat /dev/urandom /dev/fb0 # 清屏测试 cat /dev/zero /dev/fb0常见问题排查屏幕白屏检查背光电路和BL引脚配置显示错位确认rotate参数和扫描方向设置颜色异常检查SPI数据位宽和像素格式6. 进阶优化建议性能调优增大SPI时钟频率需确保信号质量启用DMA传输减少CPU占用调整fps参数平衡刷新率和功耗电源管理lcd: lcd0 { power-supply vcc_lcd; // 添加电源控制 backlight backlight; // 背光控制节点 };多屏幕支持spi0 { lcd1: lcd0 { reg 0; }; lcd2: lcd1 { reg 1; }; // 第二个屏幕 };移植过程中最耗时的往往是硬件时序调试。建议准备逻辑分析仪观察SPI波形确保时钟极性(CPOL)和相位(CPHA)设置与屏幕规格一致。我曾遇到某款GC9306屏幕必须设置CPHA1才能正常显示而数据手册却标注为可选这种特殊情况只能通过实际测试验证。