news 2026/2/28 10:07:54

ST7735驱动SPI接口配置:手把手教程(从零实现)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ST7735驱动SPI接口配置:手把手教程(从零实现)

从零点亮一块1.8寸彩屏:ST7735 SPI驱动实战全解析

你有没有试过,手里的MCU一切正常,代码也烧录成功,可那块小小的TFT屏幕就是不亮?白屏、花屏、闪屏……各种诡异现象轮番上演。别急,这不是玄学,而是你还没真正“读懂”这块屏背后的控制器——ST7735

今天我们就来干一票大的:不用任何现成库,从最底层开始,一步一步带你把一块ST7735驱动的1.8英寸TFT彩屏点亮。无论你是用STM32、ESP32还是Arduino,只要懂点C语言和GPIO操作,这篇文章都能让你搞明白——原来,“点亮屏幕”这件事,也没那么神秘。


为什么是ST7735?

在五花八门的小尺寸TFT控制器中,ST7735是一个极具代表性的存在。它不是性能最强的,也不是分辨率最高的,但它足够小巧、便宜、集成度高,特别适合资源有限的嵌入式项目。

一块常见的1.8寸SPI接口TFT模块,背面可能只贴着一颗主芯片,而它的名字很可能就是ST7735SST7735R。这类芯片通常支持:

  • 分辨率:128×160 像素
  • 色深:RGB565(每像素16位,共65536色)
  • 接口:四线SPI + 控制引脚(D/C, CS, RST)
  • 内置升压电路:仅需3.3V供电即可驱动液晶偏压
  • 支持旋转显示:0° / 90° / 180° / 270° 自由切换

最关键的是——只需要5根控制线就能工作

引脚功能
SCLKSPI时钟
MOSI主发从收数据
CS片选(低有效)
D/C数据/命令选择(高=数据,低=命令)
RST硬件复位

没有MISO?对,ST7735基本是单向通信的,我们只往里写,不读回来。这简化了设计,也让软件模拟SPI成为可能。


SPI通信的本质:命令与数据如何区分?

很多人第一次调试ST7735失败,问题就出在这两个字上:D/C

你以为SPI只是发数据?错。对于LCD控制器来说,每一次传输都必须明确告诉它:“我现在给你的是命令,还是数据”。

举个例子:
- 发送0x2C表示“我要开始写显存了”——这是命令;
- 接着发送一堆0xF800(红色)、0x07E0(绿色)——这些是数据。

如果D/C没控制好,屏幕就会懵:你给我的到底是“开机指令”,还是一串红颜色?

所以,所有通信流程都遵循这个模式:

// 发送命令 拉低CS; D/C = 0; // 告诉它是命令 发送命令字节; 拉高CS; // 发送数据 拉低CS; D/C = 1; // 告诉它是数据 发送一个或多个数据字节; 拉高CS;

⚠️ 注意:有些模块要求在连续写数据时不反复拉高/拉低CS,否则效率极低。因此批量写入时应保持CS为低电平直到完成。


初始化序列:别跳步!顺序很重要

你以为上电就能显示?Too young.

ST7735内部有一套复杂的电源管理系统和显示时序逻辑,必须通过精确的初始化序列来唤醒它。这个过程就像启动一台老式电视机:先通电预热,再打开图像,最后调对比度。

核心步骤拆解

  1. 硬件复位
    - 上电后延时10ms;
    - 拉低RST脚至少10μs;
    - 再拉高并等待120ms让内部电路稳定。

  2. 软复位(Software Reset)
    - 发送命令0x01
    - 等待150ms

  3. 退出睡眠模式(Sleep Out)
    - 发送0x11
    - 延时20ms以上

  4. 设置像素格式
    - 命令0x3A,数据0x05→ 启用16位RGB565模式

  5. 配置显示方向(MADCTL)
    - 命令0x36,参数决定是否翻转、交换行列等

  6. 开启显示输出
    - 最后发送0x29,屏幕才会真正亮起来

关键寄存器详解:MADCTL(0x36)

这个寄存器决定了屏幕怎么“看世界”。它是一个8位控制字,每一位都有含义:

Bit名称说明
7MY行地址顺序(0: top→bottom, 1: bottom→top)
6MX列地址顺序(0: left→right, 1: right→left)
5MV行列交换(0: normal, 1: transpose)
4ML扫描方向(0: normal, 1: reverse)
3RGB接口颜色顺序(0: BGR, 1: RGB)
2MH水平刷新方向(很少用)

常见组合:
-0xC0:MY=1, MX=1, MV=0 → 上下左右镜像,适合竖屏使用
-0xA0:MY=1, MX=0, MV=1 → 90度旋转

你可以根据PCB安装方向灵活调整,避免程序里到处翻转坐标。


实战代码:基于HAL库的底层驱动封装

下面这段代码不是抄来的,而是经过实测验证的最小可用版本。我们以STM32 HAL库为例,但思路适用于任何平台。

#include "stm32f1xx_hal.h" // 引脚定义(根据实际接线修改) #define TFT_PORT GPIOA #define TFT_SCLK_PIN GPIO_PIN_5 #define TFT_MOSI_PIN GPIO_PIN_7 #define TFT_CS_PIN GPIO_PIN_6 #define TFT_DC_PIN GPIO_PIN_4 #define TFT_RST_PIN GPIO_PIN_3 // 使用硬件SPI(推荐) extern SPI_HandleTypeDef hspi1; static void tft_spi_write(uint8_t data) { HAL_SPI_Transmit(&hspi1, &data, 1, HAL_MAX_DELAY); } void tft_write_command(uint8_t cmd) { HAL_GPIO_WritePin(TFT_PORT, TFT_DC_PIN, GPIO_PIN_RESET); // Command mode HAL_GPIO_WritePin(TFT_PORT, TFT_CS_PIN, GPIO_PIN_RESET); tft_spi_write(cmd); HAL_GPIO_WritePin(TFT_PORT, TFT_CS_PIN, GPIO_PIN_SET); } void tft_write_data(uint8_t data) { HAL_GPIO_WritePin(TFT_PORT, TFT_DC_PIN, GPIO_PIN_SET); // Data mode HAL_GPIO_WritePin(TFT_PORT, TFT_CS_PIN, GPIO_PIN_RESET); tft_spi_write(data); HAL_GPIO_WritePin(TFT_PORT, TFT_CS_PIN, GPIO_PIN_SET); } // 高效批量写数据(重要!刷图快就靠它) void tft_write_buffer(uint8_t *buffer, size_t len) { HAL_GPIO_WritePin(TFT_PORT, TFT_DC_PIN, GPIO_PIN_SET); HAL_GPIO_WritePin(TFT_PORT, TFT_CS_PIN, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, buffer, len, HAL_MAX_DELAY); HAL_GPIO_WritePin(TFT_PORT, TFT_CS_PIN, GPIO_PIN_SET); }

注意:如果你的MCU没有硬件SPI,也可以用GPIO模拟。虽然速度慢些,但在非高速刷新场景下完全够用。


屏幕初始化函数:照着时序走,一步都不能少

void st7735_init(void) { // === 步骤1:硬件复位 === HAL_Delay(10); HAL_GPIO_WritePin(TFT_PORT, TFT_RST_PIN, GPIO_PIN_RESET); HAL_Delay(10); HAL_GPIO_WritePin(TFT_PORT, TFT_RST_PIN, GPIO_PIN_SET); HAL_Delay(120); // === 步骤2:发送初始化命令序列 === tft_write_command(0x01); // Software Reset HAL_Delay(150); tft_write_command(0x11); // Sleep Out HAL_Delay(20); tft_write_command(0x28); // Display Off (临时关闭) tft_write_command(0x3A); // Interface Pixel Format tft_write_data(0x05); // 16-bit/pixel tft_write_command(0x36); // MADCTL: Memory Access Control tft_write_data(0xC0); // MY=1, MX=1, RGB=0 → BGR顺序,上下左右翻转 // Frame Rate Control tft_write_command(0xB1); tft_write_data(0x01); tft_write_data(0x2C); tft_write_data(0x2D); tft_write_command(0xB2); tft_write_data(0x01); tft_write_data(0x2C); tft_write_data(0x2D); tft_write_command(0xB3); tft_write_data(0x01); tft_write_data(0x2C); tft_write_data(0x2D); tft_write_data(0x01); tft_write_data(0x2C); tft_write_data(0x2D); // VOP Set (contrast) tft_write_command(0xB4); tft_write_data(0x07); // VCOM Setting tft_write_command(0xC0); tft_write_data(0xA2); tft_write_data(0x02); tft_write_data(0x84); tft_write_command(0xC1); tft_write_data(0xC5); tft_write_command(0xC2); tft_write_data(0x0A); tft_write_data(0x00); tft_write_command(0xC3); tft_write_data(0x8A); tft_write_data(0x2A); tft_write_command(0xC4); tft_write_data(0x8A); tft_write_data(0xEE); tft_write_command(0xC5); // VCOM Offset tft_write_data(0x0E); // Write ID command tft_write_command(0x36); tft_write_data(0xC0); // Rotation setting again tft_write_command(0x37); // Vertical Scroll Start Address tft_write_data(0x00); tft_write_command(0x3A); // COLMOD: Set Color Mode tft_write_data(0x05); tft_write_command(0x2A); // CASET: Column Address Set tft_write_data(0x00); tft_write_data(0x02); // Start column: 2 tft_write_data(0x00); tft_write_data(0x81); // End column: 129 tft_write_command(0x2B); // RASET: Row Address Set tft_write_data(0x00); tft_write_data(0x01); // Start row: 1 tft_write_data(0x00); tft_write_data(0x80); // End row: 128 tft_write_command(0x29); // Display ON HAL_Delay(100); }

看到这么多命令是不是头大?其实大多数是厂商推荐的“黄金参数”,用来优化对比度、响应速度和功耗。你可以先照搬,后期再逐项调试微调。


如何画点?GRAM访问才是关键

屏幕能亮了,接下来怎么做图形输出?

核心在于:GRAM(Graphic RAM)

ST7735内部有一块约40KB的显存(128×160×2 bytes),我们要做的就是把颜色数据写进去。

写GRAM三步法:

  1. 设置列地址范围(CASET, 0x2A)
  2. 设置行地址范围(RASET, 0x2B)
  3. 发送RAMWR(0x2C)命令,随后连续写入RGB565数据
void set_addr_window(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1) { tft_write_command(0x2A); // CASET tft_write_data(0x00); tft_write_data(x0 + 2); // offset correction tft_write_data(0x00); tft_write_data(x1 + 2); tft_write_command(0x2B); // RASET tft_write_data(0x00); tft_write_data(y0 + 1); tft_write_data(0x00); tft_write_data(y1 + 1); tft_write_command(0x2C); // RAMWR } void draw_pixel(uint8_t x, uint8_t y, uint16_t color) { set_addr_window(x, y, x, y); uint8_t data[2] = { color >> 8, color & 0xFF }; tft_write_buffer(data, 2); }

📌 提示:很多模块有偏移(offset),比如实际可视区域从第2列开始,所以初始化和绘图时都要加偏移量。

有了draw_pixel,你就可以实现直线、矩形、圆形、文字渲染……整个GUI世界的门就此打开。


常见坑点与调试秘籍

❌ 白屏?

  • 检查RST是否真的释放了?有时忘记拉高RST会导致一直处于复位状态。
  • 是否发送了Sleep Out (0x11)Display ON (0x29)?缺一不可。
  • 电源是否稳定?建议单独供3.3V,并加0.1μF陶瓷电容。

❌ 花屏、乱码?

  • SPI模式不对!ST7735常用Mode 0(CPOL=0, CPHA=0)或Mode 3。
  • 在CubeMX中确认SPI配置;
  • 若不确定,尝试两种模式。
  • D/C引脚接反?这是新手最高频错误之一。

❌ 刷屏慢如蜗牛?

  • 不要一个像素一个像素地写!每次设置窗口+写一个点,开销太大。
  • 改为批量写入:准备一个缓冲区,一次性刷一大片区域。
  • 更进一步:使用DMA自动搬运数据,解放CPU。

✅ 调试图谱建议

拿个示波器,抓这几组信号:
- SCLK:是否有稳定时钟?
- CS:是否在每次传输前被拉低?
- D/C:命令和数据阶段是否正确切换?
- RST:是否有完整的低脉冲?

只要波形对了,通信就没问题。


进阶玩法:不只是“点亮”

一旦掌握了基础驱动,接下来可以做的事就多了:

  • 接入LVGL等轻量级GUI框架,打造按钮、滑块、仪表盘;
  • 结合触摸屏(XPT2046),做成完整的人机交互终端;
  • 用PWM调节背光亮度,实现自动熄屏节能;
  • 双缓冲机制,防止画面撕裂;
  • SPI DMA传输,实现流畅动画;
  • 字体嵌入,显示中文或自定义图标。

甚至可以用它做一个迷你天气站、MP3播放器界面、或者带UI的遥控器。


写在最后:从“会用”到“懂原理”

今天我们没有调用Adafruit_ST7735.h,也没有tft.begin()一行搞定。相反,我们亲手写了每一个命令、每一个延时、每一个引脚操作。

也许你会觉得麻烦,但正是这种“笨办法”,让你真正理解了:
- 为什么要有复位时序?
- 为什么D/C不能省?
- 为什么初始化要发那么多命令?

当你下次遇到一块没见过的LCD模块,即使没有现成库,你也知道该从哪里下手。

真正的嵌入式开发,从来都不是复制粘贴,而是理解每一行代码背后的意义

如果你正在做毕业设计、打竞赛、搞创客项目,不妨试着自己写一遍这个驱动。哪怕只画出一个红点,那种成就感,也只有你自己知道。

如果你觉得这篇内容对你有帮助,欢迎点赞、收藏、转发。如果你在实现过程中遇到了问题,也欢迎留言交流,我们一起debug到底。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/27 7:30:04

解锁Blender MMD插件:跨平台3D创作的全新体验

解锁Blender MMD插件:跨平台3D创作的全新体验 【免费下载链接】blender_mmd_tools MMD Tools is a blender addon for importing/exporting Models and Motions of MikuMikuDance. 项目地址: https://gitcode.com/gh_mirrors/bl/blender_mmd_tools 还在为MMD…

作者头像 李华
网站建设 2026/2/25 7:47:22

英雄联盟智能助手:告别繁琐操作,专注游戏乐趣的终极解决方案

英雄联盟智能助手:告别繁琐操作,专注游戏乐趣的终极解决方案 【免费下载链接】LeagueAkari ✨兴趣使然的,功能全面的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/LeagueAk…

作者头像 李华
网站建设 2026/2/22 4:44:00

纪念币预约自动化解决方案:告别手动抢购的终极指南

纪念币预约自动化解决方案:告别手动抢购的终极指南 【免费下载链接】auto_commemorative_coin_booking 项目地址: https://gitcode.com/gh_mirrors/au/auto_commemorative_coin_booking 还在为每次纪念币发行时的手忙脚乱而苦恼吗?这款基于Pytho…

作者头像 李华
网站建设 2026/2/24 2:08:05

网页资源嗅探工具5大实战技巧:轻松捕获在线视频和音频资源

网页资源嗅探工具5大实战技巧:轻松捕获在线视频和音频资源 【免费下载链接】cat-catch 猫抓 chrome资源嗅探扩展 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 还在为网页上的精彩视频无法保存而困扰吗?猫抓Cat-Catch是一款智能浏…

作者头像 李华
网站建设 2026/2/19 10:18:52

OpCore Simplify:终极黑苹果EFI自动化创建工具完全指南

OpCore Simplify:终极黑苹果EFI自动化创建工具完全指南 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 想要在普通PC上安装macOS但被复杂的…

作者头像 李华
网站建设 2026/2/19 22:39:45

纪念币预约自动化工具:5步实现智能抢购零失误

纪念币预约自动化工具:5步实现智能抢购零失误 【免费下载链接】auto_commemorative_coin_booking 项目地址: https://gitcode.com/gh_mirrors/au/auto_commemorative_coin_booking 还在为纪念币预约手忙脚乱而烦恼吗?这款纪念币预约自动化工具将…

作者头像 李华