在嵌入式开发领域,树莓派因其丰富的GPIO接口和强大的社区支持,成为各类DIY项目的首选平台。其中SPI接口的小型LCD屏幕因其体积小巧、价格低廉(20-50元区间)而广受欢迎,特别适合需要便携显示的迷你游戏机、微型摄像头监控等场景。
目前市面上常见的1.44寸至3.5寸SPI屏幕主要采用ST7735S、ST7789、ILI9341、ILI9488等驱动芯片。这些屏幕虽然物理尺寸各异,但驱动原理相通——都是通过SPI总线与树莓派通信,利用帧缓冲拷贝(Frame Buffer Copy,简称FBCP)技术将系统画面输出到屏幕。FBCP的核心原理是在内存中开辟缓冲区存储显示内容,再通过专用驱动将内容实时传输到SPI屏幕,这种方案相比HDMI输出更节省资源,尤其适合低功耗场景。
关键提示:选购SPI屏幕时务必确认是否带有CS(片选)引脚,市面上部分7针屏幕省略了此引脚会导致驱动兼容性问题。建议优先选择带有完整8针(VCC/GND/SCK/SDI/DC/RES/CS/BL)接口的型号。
以1.44寸ST7735S屏幕为例,标准接线方式如下:
| 屏幕引脚 | 树莓派GPIO | 物理引脚号 |
|---|---|---|
| LED/BL | GPIO24 | 18 |
| SCK | GPIO11 | 23 |
| SDA | GPIO10 | 19 |
| DC | GPIO25 | 22 |
| RESET | GPIO27 | 13 |
| CS | GPIO8 | 24 |
| VCC | 5V | 2/4 |
| GND | GND | 6/9/14等 |
接线时需要特别注意:
dtoverlay=spi0-1cs,clock=16MHz在config.txt中限制,避免信号干扰上电前建议进行以下检查:
由于新版树莓派OS(Bookworm)对SPI驱动支持有变更,目前最稳定的选择是:
bash复制# 下载Bullseye 32位镜像(2023-05-03版本)
wget https://downloads.raspberrypi.com/raspios_armhf/images/raspios_armhf-2023-05-03/2023-05-03-raspios-bullseye-armhf.img.xz
烧录工具推荐使用:
bash复制# Linux下烧录示例
xzcat 2023-05-03-raspios-bullseye-armhf.img.xz | sudo dd of=/dev/sdX bs=4M status=progress
首次启动前需在boot分区创建两个文件:
bash复制touch /boot/ssh
bash复制# /boot/wpa_supplicant.conf内容:
country=CN
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
ssid="你的WiFi名称"
psk="你的WiFi密码"
key_mgmt=WPA-PSK
}
编辑/boot/config.txt添加以下内容:
ini复制# 强制HDMI输出(即使未检测到显示器)
hdmi_force_hotplug=1
# 关闭默认显示驱动
disable_overscan=1
dtoverlay=vc4-kms-v3d
max_framebuffers=2
# SPI总线配置
dtparam=spi=on
dtoverlay=spi0-1cs,clock=16MHz
微雪电子提供的通用驱动支持多数常见SPI屏幕:
bash复制sudo apt update && sudo apt install -y cmake
cd ~
wget https://www.waveshare.net/w/upload/1/18/Waveshare_fbcp.zip
unzip Waveshare_fbcp.zip
cd Waveshare_fbcp/
不同屏幕需要调整cmake参数:
| 屏幕型号 | 关键参数 | 典型分辨率 |
|---|---|---|
| 1.44寸 | -DWAVESHARE_1INCH44_LCD=ON | 128x128 |
| 0.96寸 | -DWAVESHARE_0INCH96_LCD=ON | 160x80 |
| 1.3寸 | -DWAVESHARE_1INCH3_LCD=ON | 240x240 |
| 1.54寸 | -DWAVESHARE_1INCH54_LCD=ON | 240x240 |
完整编译示例(1.44寸屏):
bash复制mkdir -p build && cd build
cmake -DSPI_BUS_CLOCK_DIVISOR=20 \
-DWAVESHARE_1INCH44_LCD=ON \
-DBACKLIGHT_CONTROL=ON \
-DSTATISTICS=0 ..
make -j$(nproc)
编译完成后立即测试:
bash复制sudo ./fbcp
常见问题排查:
白屏无显示:
画面错位/撕裂:
dtoverlay=spi0-1cs,clock=8MHz降低SPI速率颜色异常:
-DINVERT_COLORS=ONbash复制sudo cp fbcp /usr/local/bin/
/etc/rc.local在exit 0前添加:bash复制/usr/local/bin/fbcp &
ini复制# /boot/config.txt追加
hdmi_group=2
hdmi_mode=87
hdmi_cvt=128 128 60 1 0 0 0
display_rotate=0
bash复制sudo nano /etc/dphys-swapfile
# 修改为:
CONF_SWAPSIZE=100
bash复制sudo systemctl disable bluetooth.service
sudo systemctl disable hciuart.service
bash复制sudo apt install cpufrequtils
echo 'GOVERNOR="performance"' | sudo tee /etc/default/cpufrequtils
sudo systemctl restart cpufrequtils
对于使用树莓派摄像头的项目,需要特殊配置:
bash复制export DISPLAY=:0
libcamera-hello -t 0 --qt-preview
bash复制raspivid -t 0 -w 640 -h 480 -fps 30 -n -o -
ini复制# /boot/config.txt
display_rotate=2 # 180度旋转
对于微雪驱动不支持的ILI9488芯片,可采用替代方案:
bash复制git clone https://github.com/juj/fbcp-ili9341.git
cd fbcp-ili9341
mkdir build && cd build
cmake -DILI9488=ON \
-DGPIO_TFT_DATA_CONTROL=25 \
-DGPIO_TFT_RESET_PIN=27 \
-DGPIO_TFT_BACKLIGHT=24 \
-DBACKLIGHT_CONTROL=ON \
-DSPI_BUS_CLOCK_DIVISOR=16 \
-DSTATISTICS=0 ..
make -j$(nproc)
若需同时驱动SPI屏幕和HDMI输出:
/boot/config.txt:ini复制# 主显示器设置
hdmi_group=2
hdmi_mode=87
hdmi_cvt=800 480 60 6
# SPI屏幕设置
dtoverlay=spi0-1cs,clock=20MHz
bash复制sudo apt install x11-xserver-utils
xrandr --output HDMI-1 --primary --mode 800x480 --rotate normal
bash复制wget https://github.com/RetroPie/RetroPie-Setup/releases/download/4.8/retropie-buster-4.8-rpi2_rpi3.img.gz
bash复制# 强制启用复合视频输出(部分版本需要)
sudo raspi-config
# 选择 Advanced Options > GL Driver > Fake KMS
/opt/retropie/configs/all/retroarch.cfg:ini复制# 降低分辨率减轻SPI总线压力
video_fullscreen_x = "320"
video_fullscreen_y = "240"
video_threaded = "false"
ini复制# 防止画面撕裂
video_max_swapchain_images = "2"
video_frame_delay = "2"
bash复制sudo apt install python3-gpiozero
python复制#!/usr/bin/env python3
from gpiozero import Button
import os
btn_a = Button(5)
btn_b = Button(6)
def press_a():
os.system("xdotool key Enter")
btn_a.when_pressed = press_a
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 屏幕背光不亮 | 背光引脚接错/电压不足 | 检查BL引脚接线,尝试3.3V/5V切换 |
| 花屏/乱码 | SPI时钟速率过高 | 增大SPI_BUS_CLOCK_DIVISOR值 |
| 画面偏移 | 分辨率参数不匹配 | 调整hdmi_cvt值 |
| 驱动编译失败 | 缺少依赖库 | 执行sudo apt install libdrm-dev |
| 触摸功能失效 | 未启用触摸驱动 | 添加dtoverlay=ads7846到config.txt |
bash复制sudo apt install sigrok
sigrok-cli -d fx2lafw --continuous -o spi.sr
bash复制sudo apt install fbi
fbi -d /dev/fb0 --noverbose
bash复制journalctl -u fbcp -f
bash复制sudo apt install mplayer
mplayer -tv driver=v4l2:device=/dev/video0 tv://
python复制#!/usr/bin/env python3
import Adafruit_SSD1306
from PIL import Image, ImageDraw, ImageFont
disp = Adafruit_SSD1306.SSD1306_128_64(rst=None)
disp.begin()
image = Image.new('1', (disp.width, disp.height))
draw = ImageDraw.Draw(image)
font = ImageFont.load_default()
draw.text((0,0), "Temp: 25.6C", font=font, fill=255)
disp.image(image)
disp.display()
python复制from PyQt5.QtWidgets import QApplication, QLabel
app = QApplication([])
label = QLabel("System Ready")
label.setStyleSheet("font-size: 24pt;")
label.show()
app.exec_()
python复制import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)
def button_callback(channel):
print("Emergency Stop!")
GPIO.add_event_detect(23, GPIO.FALLING, callback=button_callback, bouncetime=300)
bash复制#!/bin/bash
while true; do
if [ $(date +%H) -ge 22 ] || [ $(date +%H) -lt 6 ]; then
echo 50 > /sys/class/backlight/soc:backlight/brightness
else
echo 100 > /sys/class/backlight/soc:backlight/brightness
fi
sleep 300
done
bash复制echo "powersave" | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
3D打印外壳设计要点:
防静电处理:
锂电池供电方案:
低电量自动关机:
python复制#!/usr/bin/env python3
import os
from gpiozero import PowerInput
power = PowerInput(4) # 连接电压检测模块
if power.value < 3.3:
os.system("sudo poweroff")
ini复制# /boot/config.txt添加
dtparam=i2c_arm=on
dtoverlay=i2c-gpio,bus=3,i2c_gpio_delay_us=1,i2c_gpio_sda=22,i2c_gpio_scl=23
bash复制sudo apt install xinput-calibrator
xinput_calibrator --device "ADS7846 Touchscreen"
bash复制sudo apt install conky
cp /etc/conky/conky.conf ~/.conkyrc
bash复制git clone https://github.com/notro/fbtft.git
cd fbtft
make && sudo make install
bash复制wget https://github.com/raspberrypi/linux/commit/123456.patch
patch -p1 < 123456.patch
dockerfile复制FROM resin/raspberrypi3-debian
RUN apt update && apt install -y \
cmake \
wiringpi \
libdrm-dev
COPY Waveshare_fbcp.zip /tmp/
RUN cd /tmp && \
unzip Waveshare_fbcp.zip && \
cd Waveshare_fbcp && \
mkdir build && cd build && \
cmake .. && make
bash复制docker run --device /dev/spidev0.0 --privileged -it my-fbcp-image
在实际部署过程中,我发现几个关键优化点值得分享:
SPI总线时序调整:通过示波器测量发现,当SPI时钟超过20MHz时,信号完整性明显下降。最终确定16MHz是最佳平衡点,既能保证画面流畅度又不会产生误码。
内存分配策略:默认配置下fbcp会占用大量内存,通过修改CMA(连续内存分配器)参数可以改善:
ini复制# /boot/cmdline.txt追加
cma=64M
温度控制方案:连续运行2小时后屏幕温度可达50℃,添加小型散热片后降至40℃以下。建议在屏幕背面粘贴铜箔散热片(厚度0.5mm为宜)。
电源干扰处理:当使用开关电源时,屏幕可能出现波纹干扰。解决方法包括:
机械振动防护:移动场景下连接器容易松动,采用以下加固措施:
这些实战经验往往不会出现在官方文档中,但对项目稳定性至关重要。建议大家在正式部署前进行至少72小时的老化测试,观察不同环境温度下的运行表现。