上节使用fbtft来驱动SPI接口TFT屏幕,但是是编译进内核的方式。
本节再来测试下编译成模块的用法。
240x240分辨率,1.3寸,主控为ST7789VW。
与开发板的引脚连接确定如下:
| 功能 | IO |
|---|---|
| GND | Pin6 |
| 5V | Pin2 |
| LCD_RESET | Pin7-PG11 |
| LCD_DC | Pin22-PA1 |
| SPICLK | Pin23-PC2 |
| SPIMOSI | Pin19-PC0 |
从开发板的引脚图发现,开发板使用的SPI0。
打开/home/ql/linux/H3/linux/arch/arm/boot/dts/sun8i-h3-nanopi.dtsi,找到spi0节点,把上节添加的节点注释掉,避免干扰本节的测试。修改为如下:
&spi0 {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins &spi0_cs_pins>;
cs-gpios = <&pio 2 3 GPIO_ACTIVE_HIGH>, <&pio 0 6 GPIO_ACTIVE_HIGH>;
pitft: pitft@0{
compatible = "sitronix,st7789vw";
reg = <0>;
status = "okay";
spi-max-frequency = <96000000>;
rotate = <0>;
fps = <33>;
buswidth = <8>;
dc-gpios = <&pio 0 1 GPIO_ACTIVE_HIGH>;
reset-gpios = <&pio 6 11 GPIO_ACTIVE_HIGH>;
led-gpios = <&pio 0 0 GPIO_ACTIVE_LOW>;
debug = <0x0>;
};
};
&pio {
leds_npi: led_pins {
pins = "PA10";
function = "gpio_out";
};
pinctrl_testTFTRes: testTFTRes_pins {
pins = "PG11";
function = "gpio_out";
};
pinctrl_testTFTDc: testTFTDc_pins {
pins = "PA1";
function = "gpio_out";
};
pinctrl_testTFTBk: testTFTBk_pins {
pins = "PA0";
function = "gpio_out";
};
spi0_cs_pins: spi0_cs_pins {
pins = "PC3", "PA6";
function = "gpio_out";
};
};
关闭HDMI,否则设备默认HDMI输出,tft黑屏
&hdmi {
//status = "okay";
status = "disable";
};
&hdmi_out {
hdmi_out_con: endpoint {
remote-endpoint = <&hdmi_con_in>;
};
};
&sound_hdmi {
//status = "okay";
status = "disable";
};
编辑Device
根据Linux统一设备模型思想:Device提供硬件信息描述,Driver提供使用硬件信息的方法。
我们打开 /kernel/driver/staging/fbtft/fbtft_device.c文件,看到
static struct fbtft_device_display displays[] = {
{
.name = "adafruit18",
.spi = &(struct spi_board_info) {
.modalias = "fb_st7735r",
.max_speed_hz = 32000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
},
.gamma = ADAFRUIT18_GAMMA,
}
}
}, {
.name = "adafruit18_green",
.spi = &(struct spi_board_info) {
.modalias = "fb_st7735r",
.max_speed_hz = 4000000,
.mode = SPI_MODE_0,
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8,
.backlight = 1,
.fbtftops.set_addr_win =
adafruit18_green_tab_set_addr_win,
},
.bgr = true,
.gamma = ADAFRUIT18_GAMMA,
}
}
}, {
......................省略
上面的结构体描述了大量的显示屏信息,我们在最后面仿造前面的,加上ST7789VW屏幕的描述
}, {
.name = "qlexceltft", //你自己取,后面加载模块的时候要用
.spi = &(struct spi_board_info) {
.modalias = "fb_st7789vW", //匹配显示屏的名字
.max_speed_hz = 96000000, //最大SPI速率
.mode = SPI_MODE_0, //spi的模式
.bus_num=0, //使用SPI0
.chip_select = 0, //使用SPI0的CS0管脚
.platform_data = &(struct fbtft_platform_data) {
.display = {
.buswidth = 8, //8位总线
.backlight = 1, //有背光
},
// .bgr = true,
.gpios = (const struct fbtft_gpio []) {
{ "reset", 203 }, //PG11 reset占用的管脚号
{ "dc", 1 }, //PA1 dc占用的管脚号
{ "led", 0 }, //PA0 背光占用的管脚号
},
}
}
}
添加Driver
接着我们修改位于统一设备模型中的driver
打开/home/ql/linux/H3/linux/drivers/staging/fbtft/路径,看下有没有fb_st7789vw.c文件,如果有下面的步骤就可以忽略了。
如果没有,那么新建一个fb_st7789vw.c文件,把下面内容复制进去,保存。
#include#include #include #include #include #include
在Makefile中添加obj-$(CONFIG_FB_TFT_ST7789VW) += fb_st7789vw.o
在Kconfig中添加
config FB_TFT_ST7789VW tristate "FB driver for the ST7789VW LCD Controller" depends on FB_TFT help This enables generic framebuffer support for the Sitronix ST7789VW display controller. The controller is intended for small color displays with a resolution of up to 240x240 pixels. Say Y if you have such a display that utilizes this controller.编译
到menuconfig中使能此驱动
make menuconfig ARCH=arm CROSS_COMPILE=arm-linux-
Device Drivers ---> [*] Staging drivers ---> <*> Support for small TFT LCD display modules --->
将FB driver for the ST7789VW LCD Controller和Module to for adding FBTFT devices选择成模块
# 编译内核、设备树、模块 make zImage dtbs modules ARCH=arm CROSS_COMPILE=arm-linux- # 网络更新内核 scp arch/arm/boot/zImage root@192.168.0.101:/boot # 网络更新设备树 scp arch/arm/boot/dts/sun8i-h3-nanopi-neo-air.dtb root@192.168.0.101:/boot # 网络上传模块 scp drivers/staging/fbtft/fbtft_device.ko root@192.168.0.101:/lib/modules/4.14.111/ scp drivers/staging/fbtft/fb_st7789vw.ko root@192.168.0.101:/lib/modules/4.14.111/上电测试
上电后,切换root,加载模块
insmod fbtft_device.ko name=qlexceltft busnum=0 cs=0 rotate=0 debug=7 insmod fb_st7789vw.ko
insmod fbtft_device.ko后面的参数解释如下:
- name:fbtft_device里你自己设置的
- busnum:用于指定使用第几个spi控制器
- CS:SPI的第几个CS片选线
- rotate:屏幕翻转角度
- debug:数字越大,调试的时候打印的信息越多,debug的时候可以设置为7.
执行成功的话屏幕应该点亮了,通过lsmod命令就能看到模块已被加载,在/dev目录下,会产生fb0设备,如果执行失败,可以通过dmesg | grep "fb" 来查看内核日志,分析具体原因,一般都是由于参数错了导致;
设置开机自动加载模块1、在st7735s.ko fbtft_device.ko 驱动模块目录下(/lib/modules/4.x.x/kernel/driver/staging/fbtft)执行sudo depmod -A 生成map文件。
2、编辑文件 /etc/modules,添加如下:
fb_st7735s fbtft_device
3、新建配置文件 /etc/modprobe.d/fbtft.conf,内容如下:
options fbtft_device name=qlexceltft busnum=0 gpios=reset:3,dc:17 rotate=90 custom=1 height=128 width=128
4、上面 3 步完成后重启,应该就可以看到屏幕被点亮并显示了 console,说明驱动被自动加载了
参考:
嵌入式Linux fbtft(SPI TFT屏)驱动移植及调试



