4. MCU与屏幕的接口匹配:SPI/QSPI/8080并口模式配置

花屏问题里,有一类特别隐蔽——就是MCU和屏幕之间的接口没对上。说白了,两边握手的方式不一样,数据传过去就乱了。我见过不少项目,代码逻辑查了三遍都没问题,最后发现是SPI的时钟极性配反了。

这一章,咱们就把接口匹配这件事彻底讲透。你搞清楚了,至少能排除一半的花屏原因。

4.1 三种主流接口:SPI、QSPI、8080并口

先看一张总览图,把三种接口的核心差异搞清楚。

MCU与屏幕接口类型对比 SPI (4线) SCLK, MOSI, MISO, CS 1 bit/时钟周期 速度:10~40 MHz 引脚最少,适合小屏 QSPI (6线) SCLK, IO0-IO3, CS 4 bit/时钟周期 速度:40~80 MHz 中等引脚,性价比高 8080 并口 D0-D15 + 控制线 8/16 bit/时钟周期 速度:最高可达100+ MHz 引脚多,适合大屏/高刷 选型建议 • 320×240 以下小屏:SPI 足够,引脚省,布线简单 • 480×320 中屏:QSPI 是甜点,速度翻倍,引脚只多2根 • 800×480 以上大屏或需要高帧率:8080 并口是必须的 • 注意:部分MCU没有8080控制器,只能用SPI/QSPI

4.2 SPI模式配置:CPOL和CPHA是花屏的隐形杀手

SPI接口有4种模式,由时钟极性(CPOL)和时钟相位(CPHA)决定。很多工程师在这里栽过跟头——包括我自己。

CPOL:空闲时时钟线的电平。
CPOL=0,空闲时低电平;CPOL=1,空闲时高电平。

CPHA:数据在哪个时钟沿被采样。
CPHA=0,第一个时钟沿采样;CPHA=1,第二个时钟沿采样。

模式 CPOL CPHA 采样沿 常见屏幕驱动
模式0 0 0 上升沿 ILI9341, ST7789, SSD1306
模式1 0 1 下降沿 部分老款驱动
模式2 1 0 下降沿 某些特殊传感器
模式3 1 1 上升沿 部分高速屏

核心原则:MCU的SPI模式必须和屏幕数据手册里写的一模一样。差一个沿,数据就全错了。

我的经验:ILI9341和ST7789这类主流小屏,90%都工作在模式0。我习惯先把模式0试一遍,不行再换模式3——这两个是最常见的。

4.3 实战:STM32 HAL库配置SPI

拿STM32举例,配置SPI的代码长这样。注意看CPOL和CPHA的赋值。

// SPI句柄初始化
SPI_HandleTypeDef hspi1;

hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;   // CPOL = 0
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;       // CPHA = 0
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 10;

HAL_SPI_Init(&hspi1);

这里有个坑——SPI_POLARITY_LOW对应CPOL=0,SPI_PHASE_1EDGE对应CPHA=0。如果你配反了,屏幕能收到数据,但全是错的。花屏就来了。

我曾经踩过的坑:有一次我用的屏幕数据手册写的是“SPI mode 3”,但我习惯性配成了mode 0。结果屏幕能亮,能显示,但颜色完全不对——红色变成了蓝色,绿色变成了紫色。查了整整一天,最后用逻辑分析仪抓波形才发现,时钟沿差了半个周期。

4.4 QSPI配置:四线模式下的额外注意事项

QSPI比SPI多了3根数据线,速度更快,但配置也更讲究。

  • 时钟频率:QSPI通常跑40~80 MHz,注意PCB走线长度,超过10cm就要考虑信号完整性。
  • 采样模式:和SPI一样,CPOL/CPHA必须匹配。QSPI屏幕通常也工作在模式0。
  • DDR模式:部分QSPI控制器支持双沿采样(DDR),时钟上升和下降都传数据。这个模式容易出问题,我建议新手先避开。
  • IO引脚顺序:QSPI的IO0~IO3必须和屏幕一一对应,不能乱接。接反了数据就乱了。
// QSPI配置示例(STM32H7系列)
QSPI_HandleTypeDef hqspi;

hqspi.Instance = QUADSPI;
hqspi.Init.ClockPrescaler = 2;          // 分频系数
hqspi.Init.FifoThreshold = 4;
hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE;
hqspi.Init.FlashSize = POSITION_VAL(0x800000);  // 8MB
hqspi.Init.ChipSelectHighTime = 2;
hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;       // CPOL=0, CPHA=0
hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;

HAL_QSPI_Init(&hqspi);

我个人的习惯:QSPI初始化后,先发一个读ID的命令(0x9F),看看返回的数据对不对。如果读回来的ID和屏幕手册对不上,那肯定是配置有问题,别急着调LVGL。

4.5 8080并口模式:时序参数要抠细

8080并口是并行传输,速度最快,但时序参数也最多。主要关注这几个:

参数 含义 典型值 配错后果
WR周期 写脉冲宽度 50~100 ns 数据写不进去,花屏
RD周期 读脉冲宽度 50~100 ns 读回数据错误
数据建立时间 数据在WR上升沿前需稳定 10~20 ns 数据采样错误
数据保持时间 数据在WR上升沿后需保持 5~10 ns 数据丢失
CS片选建立时间 CS拉低到WR有效 10~20 ns 片选未稳定就操作

这些参数在屏幕的数据手册里都有。你想想看,如果MCU的FSMC/FMC控制器配的时序比屏幕要求的快,数据还没稳定就被采样了——花屏就来了。

// STM32 FMC配置8080并口示例
FMC_NORSRAM_TimingTypeDef Timing;

Timing.AddressSetupTime = 3;       // 地址建立时间
Timing.AddressHoldTime = 1;        // 地址保持时间
Timing.DataSetupTime = 4;          // 数据建立时间
Timing.BusTurnAroundDuration = 1;
Timing.CLKDivision = 0;
Timing.DataLatency = 0;
Timing.AccessMode = FMC_ACCESS_MODE_A;

HAL_SRAM_Init(&hsram1, &Timing, NULL);

注意:这些时序参数的单位是HCLK周期。如果你的HCLK是200 MHz,一个周期就是5 ns。配成3就是15 ns。一定要换算成实际时间,和屏幕手册对比。

4.6 排查流程:接口问题导致花屏的定位方法

如果你遇到花屏,怀疑是接口配置问题,按这个流程走:

  1. 确认接口类型:看屏幕数据手册,确认是SPI、QSPI还是8080。
  2. 核对CPOL/CPHA:SPI/QSPI的话,确认模式0/1/2/3。
  3. 检查时钟频率:降低分频系数,让SPI跑慢一点(比如1 MHz)。如果慢速下正常,说明是信号质量问题。
  4. 用逻辑分析仪抓波形:看SCLK、MOSI、CS的时序对不对。这是最直接的方法。
  5. 读屏幕ID:发读ID命令,看返回值是否匹配。不匹配就是配置错了。
  6. 检查接线:特别是QSPI的IO顺序和8080的数据线顺序。

一句话总结:接口匹配是屏幕正常工作的前提。CPOL/CPHA配错、时钟太快、时序参数不对——任何一个都能导致花屏。先确认接口配置,再调LVGL,能省下大量排查时间。