news 2026/4/16 17:21:50

使用HAL库驱动ST7735:超详细版调试记录

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用HAL库驱动ST7735:超详细版调试记录

从点不亮到流畅显示:我在STM32上用HAL库驱动ST7735的实战全记录

最近在做一个基于STM32F103C8T6的小型人机界面项目,需要接入一块1.8英寸的彩色TFT屏。市面上最常见的就是ST7735控制器的模组了——便宜、小巧、接口简单。理想很丰满,但真正动手才发现,“接上线就能亮”只是幻想

我花了整整三天时间,才把这块看似简单的屏幕从黑屏、花屏、乱码一步步调到正常显示。期间踩遍了SPI时序不对、初始化序列错配、DC引脚控制混乱等几乎所有坑。今天这篇记录,不是什么高大上的技术论文,而是一个普通嵌入式工程师的真实调试手记,希望能帮你少走弯路。


为什么选ST7735?又为什么这么难搞?

先说结论:ST7735本身是一款非常优秀的TFT驱动IC,尤其适合资源有限的MCU平台。它支持RGB565格式、128×160分辨率,仅需4根SPI线(SCK、MOSI、CS、DC)即可工作,连RST都可以省掉。

那问题出在哪?

答案是:“不同厂家、不同批次、不同标签颜色”的模组,内部初始化流程可能完全不同

你没看错。同样是写着“ST7735”的屏幕,有“Green Tab”、“Black Tab”、“Red Tab”甚至“White Tab”版本,它们的初始化命令序列差异巨大。网上随便搜一份代码,很可能只能点亮某一类模组,换一块就罢工。

更坑的是,这些信息往往藏在数据手册的角落里,或者根本就没写清楚。于是我们只能靠试、靠猜、靠逻辑分析仪抓波形。


硬件连接:别小看这几根线

我的开发环境如下:

  • MCU:STM32F103C8T6(蓝 pill)
  • 显示屏:1.8” SPI TFT,背面贴着绿色胶布(即所谓“Green Tab”版)
  • 接口方式:四线SPI + DC + RST + CS
  • 供电:3.3V(来自板载LDO)

连接关系如下:

STM32ST7735
PB13 (SCK)SCK
PB15 (MOSI)MOSI
PB12CS
PB14DC
PB11RST
GNDGND
3.3VVCC, LED

⚠️ 注意:虽然ST7735标称兼容5V信号输入,但我建议全部使用3.3V系统,避免电平冲突风险。如果你的主控是5V(如Arduino),务必加电平转换!

SPI配置在CubeMX中设置为:

  • Mode: Master
  • Clock Polarity: Low (CPOL=0)
  • Clock Phase: 1 Edge (CPHA=0) → 即SPI Mode 0
  • Baud Rate Prescaler: fpclk/16 (初始调试设慢点,后面再提速)
  • First Bit: MSB
  • NSS: Software (由GPIO手动控制CS)

这个Mode 0很重要!有些模组要求Mode 3,但绝大多数Green/Black Tab版本都用Mode 0。错了直接通信失败。


驱动框架设计:命令和数据必须分家

ST7735最核心的设计之一就是通过DC引脚区分命令和数据

  • DC = 0:接下来传输的是命令字节(比如0x2C表示开始写显存)
  • DC = 1:接下来传输的是数据内容(比如像素颜色值)

这看起来很简单,但在代码实现时很容易出错。很多人图省事,在SPI传输过程中动态切换DC电平,结果导致第一个字节就被误判。

所以我的做法是:封装两个独立函数,确保每次传输前状态明确。

// st7735.h #ifndef __ST7735_H #define __ST7735_H #include "stm32f1xx_hal.h" // 引脚定义(根据实际PCB修改) #define ST7735_CS_PORT GPIOB #define ST7735_CS_PIN GPIO_PIN_12 #define ST7735_DC_PORT GPIOB #define ST7735_DC_PIN GPIO_PIN_13 #define ST7735_RST_PORT GPIOB #define ST7735_RST_PIN GPIO_PIN_11 // 模式宏 #define CMD_MODE() HAL_GPIO_WritePin(ST7735_DC_PORT, ST7735_DC_PIN, GPIO_PIN_RESET) #define DAT_MODE() HAL_GPIO_WritePin(ST7735_DC_PORT, ST7735_DC_PIN, GPIO_PIN_SET) // 片选操作 #define CS_LOW() HAL_GPIO_WritePin(ST7735_CS_PORT, ST7735_CS_PIN, GPIO_PIN_RESET) #define CS_HIGH() HAL_GPIO_WritePin(ST7735_CS_PORT, ST7735_CS_PIN, GPIO_PIN_SET) // 函数声明 void ST7735_Init(void); void ST7735_WriteCmd(uint8_t cmd); void ST7735_WriteData(uint8_t data); void ST7735_WriteBuffer(uint8_t *buffer, uint16_t len); void ST7735_SetAddressWindow(uint8_t x, uint8_t y, uint8_t w, uint8_t h); void ST7735_FillRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint16_t color); #endif

对应的底层传输函数:

// st7735.c #include "st7735.h" #include <string.h> extern SPI_HandleTypeDef hspi1; // 假设使用SPI1 void ST7735_WriteCmd(uint8_t cmd) { CS_LOW(); CMD_MODE(); // 先设为命令模式 HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); CS_HIGH(); } void ST7735_WriteData(uint8_t data) { CS_LOW(); DAT_MODE(); // 设为数据模式 HAL_SPI_Transmit(&hspi1, &data, 1, HAL_MAX_DELAY); CS_HIGH(); } void ST7735_WriteBuffer(uint8_t *buffer, uint16_t len) { CS_LOW(); DAT_MODE(); HAL_SPI_Transmit(&hspi1, buffer, len, HAL_MAX_DELAY); CS_HIGH(); }

这里的关键点在于:每次传输都完整经历“拉低CS → 设置DC → 发送 → 拉高CS”全过程。虽然效率不高,但稳定性极佳,特别适合调试阶段。


初始化序列:成败在此一举

这是整个驱动中最关键的部分。ST7735上电后处于睡眠状态,必须按特定顺序发送几十条寄存器配置命令才能唤醒

而不同厂商的模组,所需的初始化流程天差地别。

以下是我实测可用的“Green Tab”版本初始化代码(适用于大多数淘宝常见绿屏):

void ST7735_Reset(void) { HAL_GPIO_WritePin(ST7735_RST_PORT, ST7735_RST_PIN, GPIO_PIN_RESET); HAL_Delay(10); HAL_GPIO_WritePin(ST7735_RST_PORT, ST7735_RST_PIN, GPIO_PIN_SET); HAL_Delay(120); // 必须等待足够长时间! } void ST7735_Init(void) { ST7735_Reset(); // --- 开始初始化序列 --- ST7735_WriteCmd(0x11); // Sleep Out HAL_Delay(120); ST7735_WriteCmd(0xB1); ST7735_WriteData(0x01); ST7735_WriteData(0x2C); ST7735_WriteData(0x2D); ST7735_WriteCmd(0xB2); ST7735_WriteData(0x01); ST7735_WriteData(0x2C); ST7735_WriteData(0x2D); ST7735_WriteCmd(0xB3); ST7735_WriteData(0x01); ST7735_WriteData(0x2C); ST7735_WriteData(0x2D); ST7735_WriteData(0x01); ST7735_WriteData(0x2C); ST7735_WriteData(0x2D); ST7735_WriteCmd(0xB4); // Inversion Off ST7735_WriteData(0x07); ST7735_WriteCmd(0xC0); ST7735_WriteData(0xA2); ST7735_WriteData(0x02); ST7735_WriteData(0x84); ST7735_WriteData(0xC5); // VL63 ST7735_WriteCmd(0xC1); ST7735_WriteData(0xC5); ST7735_WriteCmd(0xC2); ST7735_WriteData(0x0A); ST7735_WriteData(0x00); ST7735_WriteCmd(0xC3); ST7735_WriteData(0x8A); ST7735_WriteData(0x2A); ST7735_WriteData(0x8A); ST7735_WriteCmd(0xC4); ST7735_WriteData(0x8A); ST7735_WriteData(0xEE); ST7735_WriteCmd(0xC5); // VCOM ST7735_WriteData(0x0E); ST7735_WriteCmd(0x36); // MADCTL: 内存访问控制 ST7735_WriteData(0xC0); // 旋转方向 + BGR顺序 ST7735_WriteCmd(0x3A); // COLMOD: 接口像素格式 ST7735_WriteData(0x05); // 16位色 (RGB565) ST7735_WriteCmd(0x21); // Display Inversion On HAL_Delay(10); ST7735_WriteCmd(0x13); // Normal Display Mode On ST7735_WriteCmd(0x29); // Display On HAL_Delay(10); }

📌重点说明几个关键命令

  • 0x36 (MADCTL):决定屏幕旋转方向和颜色排列。常用值:
  • 0x00: 0°, RGB
  • 0x60: 90°, RGB
  • 0xA0: 180°, RGB
  • 0xC0: 270°, BGR ← 我这块屏需要这个
  • 0x3A (COLMOD):必须设为0x05启用16位色模式,否则颜色会异常。
  • 0x110x29:分别是“退出睡眠”和“开启显示”,缺一不可。
  • 所有延时都不能删!特别是复位后的120ms,是芯片启动所需时间。

如果换成了“Black Tab”模组,你可能需要换成另一套初始化序列(例如先发0x0C,0x0F等)。建议准备多套init函数备用。


实际测试:画个红色方块验证

为了快速验证是否成功,我写了个最简单的填充函数:

void ST7735_FillRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint16_t color) { uint8_t x1 = x + w - 1; uint8_t y1 = y + h - 1; ST7735_SetAddressWindow(x, y, x1, y1); uint32_t total_pixels = w * h; uint8_t *buffer = malloc(total_pixels * 2); // 每像素2字节 if (!buffer) return; for (int i = 0; i < total_pixels; i++) { buffer[2*i] = color >> 8; // 高字节 buffer[2*i + 1] = color & 0xFF; // 低字节 } ST7735_WriteCmd(0x2C); // 开始写GRAM ST7735_WriteBuffer(buffer, total_pixels * 2); free(buffer); }

配合地址窗口设置函数:

void ST7735_SetAddressWindow(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1) { ST7735_WriteCmd(0x2A); // Column Address Set ST7735_WriteData(0x00); ST7735_WriteData(x0 + 2); // XSTART偏移修正 ST7735_WriteData(0x00); ST7735_WriteData(x1 + 2); // XEND ST7735_WriteCmd(0x2B); // Row Address Set ST7735_WriteData(0x00); ST7735_WriteData(y0 + 1); ST7735_WriteData(0x00); ST7735_WriteData(y1 + 1); }

🔍 注意:很多ST7735模组的实际可视区域是128×160,但它物理RAM是132×162,所以通常要加偏移(+1或+2)才能对齐。这也是常被忽略的细节。

主函数中调用:

int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_SPI1_Init(); ST7735_Init(); ST7735_FillRect(10, 10, 50, 50, 0xF800); // 红色矩形(RGB565) while (1) {} }

当看到屏幕上真的出现一个鲜红的方块时,那一刻的成就感,懂的人都懂。


踩过的坑与避坑指南

❌ 问题1:屏幕全黑,什么也不显示

排查思路
- 是否执行了0x110x29
- RST有没有正确释放?有没有加足够延时?
- SPI Mode是否正确?用逻辑分析仪看一下SCK空闲电平是不是低?

✅ 解决方案:加入完整的复位流程 + 使用示波器确认SPI波形。


❌ 问题2:显示花屏、条纹、雪花

典型表现:颜色错乱、图像撕裂、部分区域乱码。

原因
- SPI速率太快(>8MHz在F1上容易出错)
- DC引脚控制时机错误
- 地址窗口未正确设置,写到了无效区域

✅ 解决方案:
- 将SPI降频至4MHz以下测试;
- 检查ST7735_WriteCmd/Data中CS和DC的顺序;
- 绘图前务必调用SetAddressWindow


❌ 问题3:刷新卡顿,CPU占用100%

原因:每发一个像素都要调一次HAL_SPI_Transmit,加上CS反复切换,开销极大。

✅ 优化建议:
- 改用DMA传输(配合SPI双缓冲更佳);
- 对静态内容做缓存,只刷新变动区域;
- 使用局部更新而非全屏重绘。

未来可以引入LVGL这类轻量GUI库,进一步提升交互体验。


总结:稳定比炫技更重要

回顾这次调试过程,最大的体会是:嵌入式开发没有银弹,细节决定成败

一块小小的TFT屏背后,藏着SPI时序、电源管理、初始化流程、内存映射等多个技术点的协同。任何一个环节出问题,都会表现为“点不亮”。

但我相信,只要你掌握了以下几点,就能应对绝大多数ST7735模组:

  1. 硬件连接准确无误(尤其是DC、CS、RST);
  2. SPI配置为Mode 0,初始速率不宜过高
  3. 初始化序列必须匹配你的模组类型(Green/Black Tab);
  4. 每个传输步骤都要有明确的状态控制
  5. 善用延时和逻辑分析仪定位问题

现在我已经把这套驱动打包成一个可复用模块,后续还会加入字体渲染、图片解码、触摸响应等功能。如果你也在做类似项目,欢迎留言交流经验。

毕竟,每一个能点亮屏幕的夜晚,都是值得庆祝的胜利

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

基于springboot和vue框架的防疫站疫苗预约管理系统_3h5p1541

目录具体实现截图项目介绍论文大纲核心代码部分展示可定制开发之亮点部门介绍结论源码获取详细视频演示 &#xff1a;文章底部获取博主联系方式&#xff01;同行可合作具体实现截图 本系统&#xff08;程序源码数据库调试部署讲解&#xff09;同时还支持Python(flask,django)、…

作者头像 李华
网站建设 2026/4/15 21:39:41

Open-AutoGLM 电脑版本地部署全教程,手把手教你搭建离线AI编程环境

第一章&#xff1a;Open-AutoGLM 电脑版概述 Open-AutoGLM 是一款面向本地化大模型推理与自动化任务执行的开源工具&#xff0c;专为桌面环境设计&#xff0c;支持 Windows、macOS 和 Linux 系统。该工具基于 GLM 架构深度优化&#xff0c;能够在无网络依赖的情况下运行自然语言…

作者头像 李华
网站建设 2026/4/16 14:26:13

如何快速解决OpenSpeedy常见故障:实用排查指南全解析

如何快速解决OpenSpeedy常见故障&#xff1a;实用排查指南全解析 【免费下载链接】OpenSpeedy 项目地址: https://gitcode.com/gh_mirrors/op/OpenSpeedy 当你满怀期待地启动OpenSpeedy准备加速游戏时&#xff0c;突然遇到"打开进程失败"或"内存分配错误…

作者头像 李华
网站建设 2026/4/16 12:43:13

AMD Ryzen处理器性能优化实战:SMUDebugTool从入门到精通

AMD Ryzen处理器性能优化实战&#xff1a;SMUDebugTool从入门到精通 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: https://…

作者头像 李华
网站建设 2026/4/16 12:57:49

KLayout终极指南:5步掌握专业版图设计工具

KLayout终极指南&#xff1a;5步掌握专业版图设计工具 【免费下载链接】klayout KLayout Main Sources 项目地址: https://gitcode.com/gh_mirrors/kl/klayout KLayout是一款功能强大的开源版图设计工具&#xff0c;为半导体工程师提供完整的集成电路设计解决方案。无论…

作者头像 李华