
简介面向需要驱动ST7701液晶控制器的MCU开发者这套代码演示在STM32平台上如何用三线SPI完成屏幕初始化解决小型彩色TFT LCD模块的驱动配置问题。压缩包共两个文件包含C源码文件和波形Word文档整体大小仅三百六十七KB结构精简便于携带分享。核心C代码覆盖GPIO推挽输出配置、模拟SPI时序、初始化寄存器写入流程以及背光与显示模式控制并附有分步骤的代码注释可直接移植到任意支持GPIO模拟的MCU上波形图文档则直观展示MOSI、SCLK、CS等引脚的高低电平变化同时标注了命令与数据阶段的时序关系便于对照调试。初始化序列中涉及分辨率、电压源、偏压比、像素格式等参数设置关键的代码内均有对应实现。资源已有三千三百五十四人学习适合正在调试同型号屏幕或希望理解三线SPI协议细节的嵌入式工程师无论使用哪款STM32型号正确配置GPIO后均可复用也可作为LCD驱动开发的入门参考。 拿到一份“st7701_3线SPI初始化代码.zip”的时候我第一反应是终于不用去啃那几百页英文手册了。做嵌入式这几年凡是ST7701这类LCD驱动芯片屏厂给的资料包里基本就是一份Datasheet加一个压缩包压缩包里躺着一堆C文件乍看杂乱但整包代码的核心其实只有一件事——通过三线SPI把一串初始化寄存器序列喂给ST7701让屏幕先亮起来。这篇就把这份初始化代码从头到尾拆开讲透适合正在调ST7701小屏的嵌入式开发者也适合想搞明白三线SPI和普通SPI区别的新手。1. 先搞清楚ST7701为什么会跟“三线SPI”绑在一起1.1 ST7701本身不是SPI屏SPI只是初始化通道很多新手看到“SPI初始化代码”就默认ST7701是SPI屏这个理解从一开始就跑偏了。ST7701常见应用场景是智能手机、平板或者各种中小尺寸液晶面板它真正用来刷图的接口通常是MIPI DSI或者RGB并口SPI在这里只是个“控制通道”专门用来在开机阶段把寄存器参数写进去让驱动IC内部的工作模式、电源电压、伽马曲线、显示时序都按面板厂的要求配置好。换句话说屏幕正常工作之后SPI总线基本就闲置了像素数据是走RGB/MIPI通道高速传过去的。所以你会发现“初始化代码”通常很短没有刷屏逻辑只有写寄存器的函数加一长串配置表。理解了这一点再看zip包里的文件结构就不会迷茫一个SPI读写模块、一个延时函数、一个初始化序列表顶多加个点和背光控制再多的文件基本都是花架子。1.2 三线SPI把命令/数据选择塞进第9个bit平时我们讲的SPI是四线制SCK、MOSI、MISO、CS主机往从机发数据用MOSI读数据靠MISO。ST7701这里所谓的三线SPI把MISO去掉了只留下SCK、SDA、CS三根线而且数据方向是单向的——只写不读。这样做的原因很简单初始化阶段只需要往寄存器里写值不需要把寄存器内容读回来省一根线对排线布局和FPC连接都很友好。但这引出一个新问题没有专门的DC引脚命令/数据选择脚那怎么区分当前发的是命令还是数据ST7701的做法是把帧格式改成9bit前1bit是DC位后面8bit才是真正的字节内容。DC位为0表示命令为1表示数据。这跟传统SPI按字节收发很不一样也是很多人移植初始化代码时最容易翻车的地方。我用表格理一下接口模式线数帧格式适用场景标准SPI4线SCK/MOSI/MISO/CS8bit/byte可读可写Flash、SD卡、传感器三线SPIST7701SCK/SDA/CS9bit/帧1bit DC 8bit数据LCD初始化、寄存器配置三线SPIDC脚SCK/SDA/DC无CS或CS可选8bit/byteDC脚单独控制部分COG屏驱动IC2. 一份初始化代码zip里装了什么2.1 灵魂是那串寄存表不是那些C文件解压zip后你通常会看到一堆源文件但真正值钱的是一段看起来非常枯燥的寄存器序列数组。比如屏厂给的初始化代码里往往有这种重复性极高的调用LCD_Write_Cmd(0xE0); LCD_Write_Data(0x00); LCD_Write_Data(0x0D); LCD_Write_Data(0x13); ...这段序列就是ST7701的电源和伽马配置。和ILI9488、ST7789等驱动IC类似ST7701也有一堆厂商自定义寄存器——0xE0到0xEF之间的地址段尤其多。这些寄存器用于调节VCOM电压、VGH/VGL升压、正负伽马曲线公开手册里只会给个笼统说明具体数值完全靠面板厂针对特定液晶屏调校所以不同尺寸、不同生产批次的面板同一颗ST7701配出来的初始化序列都可能不一样。这也是为什么我拿到zip后第一件事是找初始化函数把它调用的寄存器序列原封不动地COPY出来而不是“读手册理解后自己写一版”。你可以不懂每个寄存器具体含义但必须保证发送顺序和数值一个不差。曾经有人自作聪明把初始化序列里看起来多余的寄存器删掉结果屏幕发白加闪烁折腾了两天才意识到是自己改了寄存器表。2.2 初始化流程的固定步骤与“关键延时”不管ST7701还是别的驱动IC初始化顺序都有个大致固定的骨架我拆解一下上电等电源稳定这个延时通常10~50ms拉高复位引脚或者先拉低再拉高让IC内部状态机清零延时120ms左右等内部LDO起来按顺序写入电源设置寄存器0xE0系列写入显示时序、分辨率和扫描方向设置写入伽马校正相关寄存器退出睡眠模式命令0x11延时几十毫秒开显示命令0x29。很多人会忽略步骤1和3的延时电源还没稳定就急着一顿猛写结果寄存器丢字节屏幕表现就是“时好时坏”。ST7701在复位后需要时间完成内部初始化这个延时不是玄学手册里明明白白写着。如果你发现手头代码能跑但掉电重启后偶尔不亮优先检查复位到第一条命令之间的延时往往比怀疑时序波形更管用。3. 用GPIO模拟三线SPI把代码写出来3.1 为什么我建议用软件模拟而不是硬件SPI看到九成人的第一反应是MCU自带SPI外设为什么不用硬件SPI原因是ST7701要的是9bit帧格式而绝大多数MCU的硬件SPI只支持8bit或16bit帧。你当然可以把16bit帧的高8位做文章比如把DC位放到bit8然后只发9个SCK时钟但这样用DMA或中断收发都变得极其别扭还容易因为帧长度不匹配把自己坑了。软件模拟三线SPI看似“原始”实际上更可控任意三个GPIO就能干活不占用SPI外设资源留出硬件SPI给SD卡、Flash等更需要带宽的设备出问题排查起来也直观一个GPIO一个GPIO地看波形就行。对于初始化这种高频但量不大的操作软件模拟的性能完全够用ST7701的SPI时钟一般允许10MHz上下IO翻转速度稍慢也能轻松跑到1MHz以上。3.2 9bit发送函数与命令/数据双接口软件模拟的核心函数是这个static void lcd_spi_write_9bit(uint16_t data) { /* data: bit8 为DC位bit7~bit0 为实际内容 */ lcd_cs_write(0); for (int i 8; i 0; i--) { lcd_sck_write(0); lcd_sda_write((data i) 0x01); lcd_sck_write(1); /* 上升沿采样 */ } lcd_cs_write(1); }这个函数把一条完整的9bit帧输出去先拉低CS然后从bit8开始逐位放到SDA上每放一位敲一次SCK上升沿最后拉高CS。SCK空闲为低、上升沿采样对应SPI Mode 0ST7701基本上都吃这一套。需要注意中间那个小延时如果MCU主频不高一次GPIO翻转本身就能形成足够延时如果主频很高或者有RTOS任务切换干扰可以加几个空操作但这个延时不是关键参数差不多就行。在此基础上封装两个写接口所有初始化代码都会变得非常干净void lcd_write_cmd(uint8_t cmd) { lcd_spi_write_9bit((uint16_t)cmd 0x00FF); /* DC位0 */ } void lcd_write_data(uint8_t dat) { lcd_spi_write_9bit((uint16_t)dat | 0x0100); /* DC位1 */ }之后初始化函数就是一堆这样看起来机械重复的调用这正是该有的样子。3.3 接入ST7701初始化序列的调用顺序初始化函数我会写成这样一个结构void st7701_init(void) { /* 1. 复位和上电时序 */ lcd_reset_write(0); delay_ms(10); lcd_reset_write(1); delay_ms(120); /* 2. 电源相关寄存器 */ lcd_write_cmd(0xE0); lcd_write_data(0x00); lcd_write_data(0x0D); /* ... 按屏厂序列写下去 */ /* 3. 显示时序与扫描方向 */ lcd_write_cmd(0xC6); lcd_write_data(0x80); /* 4. 退出睡眠并开显示 */ lcd_write_cmd(0x11); delay_ms(50); lcd_write_cmd(0x29); }代码写到这一步屏幕理论上就应该亮了。如果你打开屏厂给的zip文件会发现它内部实现大概就是这个套路——只不过可能多了几个分模块文件寄存器序列写得更分散。把函数名和变量名规范化之后整包代码的复杂度其实非常低。4. 调屏实录不亮、花屏、颜色不对的排查顺序4.1 先排除供电、复位和背光别一上来就怀疑代码初始化代码移植过去屏幕没反应十有七八不是代码问题。我调试ST7701这类屏幕时有个固定流程先量供电检查IOVCC和VCI电压是否正常很多小屏模块上这两个电压可以分开接接反或者没接会导致IC根本不工作。然后是复位引脚ST7701的复位是高电平有效还是低电平有效取决于面板设计绝大多数是低电平复位但有些模块把复位脚和电源管理IC混在一起实际行为会有点意外需要看原理图。接着是背光。很多屏的背光和显示驱动是两路独立供电显示初始化代码跑通了但背光没开屏幕看起来就是一块黑玻璃。用万用表量背光LED两端电压或者直接把背光PWM强行拉到高电平排除问题都是稳妥的做法。这三项检查完再回头看SPI波形。4.2 示波器看9bit时序比盲改寄存器快得多如果供电、复位、背光都正常屏幕还不亮老老实实把示波器探头架到SCK、SDA、CS三根线上抓初始化过程。重点看三件事第一条命令发出前SDA上是否先出现了DC位为0的电平SCK上升沿采样时SDA是否已经稳定CS是否在整条9bit帧期间保持低电平发完一帧才拉高。我调试时遇到过一个很隐蔽的问题GPIO初始化时SCK和SDA引脚默认电平不对导致IC在上电瞬间把高电平的SDA当作命令头的一部分解析后续所有寄存器对位全偏屏幕花得像马赛克。后来把SCK、SDA都配置成推挽输出并先拉低CS默认高问题立刻消失。还有一次是CS时序问题代码里在写每字节之间把CS拉高又拉低ST7701对CS中间高脉冲的处理和预期不一致导致连续多个寄存器值被吞掉。最后查资料才发现初始化寄存器序列最好在CS拉低期间一口气发完组帧成块避免中间CS跳变。4.3 花屏不一定怪SPIRGB接口的极性设置也要查屏幕能亮但花屏或者颜色不对这时候问题往往不在SPI初始化代码本身而在RGB接口的极性匹配。ST7701在初始化序列中会设置PCLK极性、DE数据使能极性、HSYNC/VSYNC极性和像素时钟分频只要有一项和主控侧配置不一致画面就会出现撕裂、错位或者整体偏色。典型表现是“图像能显示但有斜条纹”多数是PCLK极性反了图像上下颠倒或左右翻转多半是扫描方向寄存器没设颜色发红发蓝多数是RGB888和RGB565格式没对上。这些排查方向在原理上跟SPI初始化代码无关但正是因为初始化代码跑通了、屏幕亮了新手才会把锅扣给SPI。经验是把初始化代码当作一个“已验收”的黑盒出问题先怀疑主控侧那边的RGB时序配置逐项量PCLK频率和DE信号再回头动寄存器。5. 移植到自己的工程前这几件事必须改5.1 移植时最容易翻车的3个点第一是GPIO端口屏厂给的代码大概率基于某款STM32标准库引脚定义跟你自己的板子对不上这个最直观。第二是延时函数ST7701对复位后延时比较敏感建议用你自己的HAL/库函数重新实现delay_ms别直接依赖宏定义否则主频不同、编译器优化不同都会导致实际延时长脚短脚。第三是片选管理。如果你用软件模拟SPICS引脚可以跟其他外设共用GPIO资源但要注意ST7701的初始化序列中CS拉高意味着一次传输结束如果你在写一帧数据的中间被中断打断CS状态乱了后续恢复时IC状态机可能错位。保险做法是在关键发送函数里关闭中断或者用临界区保护尤其在有RTOS的场景下这个细节必须处理。5.2 与其他设备共享SPI总线的取舍初始化代码跑通之后不少人会想既然ST7701只在开机时用SPI那把同一组SCK/SDA引出来给SD卡共用行不行硬件上可行但有几个坑要提前考虑。首先ST7701的SDA在三线模式下是单向输出引脚SD卡则需要双向半双工通信两者共享时线序和方向切换必须处理好。ESP32这类带硬件SPI的MCU上常见做法是硬件SPI接SD卡软件模拟SPI接LCD初始化各自独立GPIO虽然浪费两个引脚但稳定性最高。如果非要共用建议把LCD的CS和SD卡的CS都用软件控制传输前确保只有一个片选为低同时留意SD卡在SPI模式下的初始化时序会不会跟LCD初始化冲突。还有一个容易被忽视的点初始化完成后最好把SCK和SDA引脚从“软件模拟SPI输出”切换回“GPIO普通模式”并拉到固定电平避免两个设备互相干扰。很多屏厂参考代码没有做这一步但实际量产项目中这个切换能省掉不少信号串扰的麻烦。5.3 我的建议把初始化序列原样保留不要“优化”最后分享一个实际教训。有一回我嫌弃屏厂给的初始化代码太啰嗦寄存器序列里有几个值看来看去像是重复写入就自作聪明删了几行结果屏幕在低温环境下出现随机花屏怎么查都查不出原因。后来换回屏厂原始序列问题消失。这类面板驱动IC的寄存器参数是调校出来的不是逻辑推导出来的删一个看似“多余”的写入可能就是把IC某个内部状态推到了不稳定区间。所以我的习惯是初始化数组一字不改地保留用注释把来源标记清楚后面要调伽马或者背光亮度只在上层逻辑里做文章绝不碰初始化序列本身。这份zip里真正值得反复阅读的就是那段看起来枯燥的寄存器表它才是屏厂工程师花时间调出来的核心资产。本文还有配套的精品资源点击获取