news 2026/1/15 3:49:03

ST7735色彩显示原理与STM32代码实现全面讲解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ST7735色彩显示原理与STM32代码实现全面讲解

深入剖析ST7735彩色显示驱动:从原理到STM32实战代码全解析

你有没有遇到过这样的情况?手里的1.8寸TFT屏接上STM32后,要么黑屏、要么花屏,调了好久才发现是初始化序列不对,或者颜色发白偏红……别急,这几乎是每个嵌入式开发者在第一次驱动ST7735时都会踩的坑。

今天我们就来彻底讲清楚这块“小黄屏”背后的秘密——它到底是怎么把一串串SPI数据变成绚丽色彩的?又该如何用STM32稳定高效地控制它?不只是贴代码,更要搞懂每一步背后的逻辑。


为什么是ST7735?一块经典TFT控制器的硬核价值

在众多小型彩色显示屏方案中,ST7735能成为“网红级”模组绝非偶然。它常见于1.8英寸、128×160分辨率的TFT模块,价格便宜、资料丰富、兼容性强,尤其适合资源有限的MCU平台如STM32F1系列。

更重要的是,它的通信接口足够简单——支持4线SPI模式下仅需6个GPIO即可工作(SCK、MOSI、CS、DC、RST、BLK),无需外部升压电路,内部集成电荷泵就能驱动栅极电压,极大降低了硬件设计门槛。

但别被“入门级”三个字骗了。想要真正发挥它的性能,比如实现流畅刷新、准确显色、低功耗控制,就必须深入理解其底层机制和初始化流程。否则,轻则画面闪烁,重则烧毁屏幕。


ST7735是怎么工作的?拆解它的三大核心层级

要让一块TFT屏正常显示,不是简单写几个命令就完事了。ST7735的工作可以分为三个层次:命令层 → 配置层 → 显存层。我们一步步来看。

第一层:命令解析 —— 和芯片“对话”的语法

ST7735通过一个简单的状态机来响应主机指令。每次传输前,你需要先告诉它是“接下来我要发命令”还是“我要发数据”。这个切换靠的就是DC引脚(Data/Command)

  • DC = 0:表示接下来发送的是命令字节,例如0x2A表示设置列地址;
  • DC = 1:表示接下来是数据内容,可能是参数或图像像素流。

典型的命令流程如下:

ST7735_WriteCommand(0x2A); // 命令:设置列范围 ST7735_WriteData({0, 0, 0, 127}); // 数据:起始列=0,结束列=127

这些命令都有固定编号,来自数据手册中的指令集表。比如:

命令功能
0x11退出睡眠模式(Sleep Out)
0x29开启显示输出(Display On)
0x2C开始写GRAM(Memory Write)
0x36设置显示方向与颜色顺序(MADCTL)
0x3A设置色彩格式(COLMOD)

掌握这几个关键命令,你就掌握了控制权。


第二层:寄存器配置 —— 上电后的“必修课”

很多人点不亮屏幕,问题就出在这里:没有正确执行初始化序列

ST7735上电后处于未知状态,必须按照特定时序写入一系列寄存器值,才能进入正常工作模式。这些配置包括:

  • 供电电压基准(VOP)
  • 像素格式(RGB565?还是8位?)
  • 显示方向(横屏/竖屏/翻转)
  • 是否启用显示反转、睡眠模式等

其中最关键的两个寄存器是:

✅ MADCTL(0x36):控制显示方向与BGR顺序

该寄存器决定图像如何映射到物理屏幕上。常用配置如下:

含义
0x000°,RGB顺序
0x6090°旋转,RGB
0xC0180°旋转,BGR(很多国产模组默认为此)
0xA0270°旋转,RGB

⚠️ 注意:如果你发现文字上下颠倒,或者颜色偏蓝严重,大概率就是MADCTL没设对!

✅ COLMOD(0x3A):设定色彩深度

必须设置为0x05才能启用16位RGB565模式。其他值对应8位或12位色,会导致颜色异常。


第三层:GRAM显存管理 —— 图像数据存放的地方

ST7735内部有一块图形RAM(GRAM),大小为132×162×2 ≈ 42KB,每个像素占两个字节(RGB565)。MCU不能直接访问这块内存,只能通过命令间接操作。

典型的数据写入流程是:

  1. 使用0x2A0x2B设置要写入的矩形区域(列地址 + 行地址);
  2. 发送0x2C命令,进入“写GRAM”模式;
  3. 连续发送RGB565数据流;
  4. 屏幕自动扫描GRAM并刷新像素。

举个例子:你想在坐标 (10,20) 处画一个红色像素(RGB565中红色为0xF800),流程如下:

SetAddressWindow(10, 20, 10, 20); // 设置窗口为单个像素 WriteCommand(0x2C); // 准备写GRAM WriteData({0xF8, 0x00}); // 写入两个字节

注意:部分模组存在偏移(offset),实际有效区域可能是 [2:130] 列、[1:160] 行,因此设置地址时需要加补偿。


STM32驱动实现:从硬件连接到代码落地

现在我们把目光转向主控端——STM32。以最常见的STM32F103C8T6(Blue Pill)为例,使用硬件SPI1接口进行通信。

硬件连接建议(SPI模式)

ST7735 引脚连接到 STM32
SCL / SCKPA5 (SPI1_SCK)
SDA / MOSIPA7 (SPI1_MOSI)
CSPB12(任意GPIO)
DCPB13(任意GPIO)
RSTPB14(任意GPIO)
VCC3.3V
GNDGND
BLKPB15(可选,用于PWM调光)

🔌 提醒:不要接5V!虽然有些模块标称支持5V逻辑输入,但ST7735核心电压为3.3V,长期使用可能损坏芯片。


初始化SPI与GPIO

我们使用HAL库配置SPI1为主机模式,CPOL=0, CPHA=0(SPI Mode 0),预分频设为4,在72MHz系统时钟下获得约10.5MHz速率,兼顾速度与稳定性。

SPI_HandleTypeDef hspi1; void ST7735_InitHardware(void) { __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_SPI1_CLK_ENABLE(); // CS, DC, RST 配置为推挽输出 GPIO_InitTypeDef gpio = {0}; gpio.Mode = GPIO_MODE_OUTPUT_PP; gpio.Speed = GPIO_SPEED_FREQ_HIGH; gpio.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14; HAL_GPIO_Init(GPIOB, &gpio); // SPI1 配置 hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; // ~10.5MHz hspi1.Init.Direction = SPI_DIRECTION_2LINES; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; HAL_SPI_Init(&hspi1); }

封装基础通信函数

为了清晰分离命令与数据,我们需要两个核心函数:

void ST7735_WriteCommand(uint8_t cmd) { HAL_GPIO_WritePin(TFT_DC_PORT, TFT_DC_PIN, GPIO_PIN_RESET); // DC=0 HAL_GPIO_WritePin(TFT_CS_PORT, TFT_CS_PIN, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); HAL_GPIO_WritePin(TFT_CS_PORT, TFT_CS_PIN, GPIO_PIN_SET); } void ST7735_WriteData(uint8_t *data, size_t len) { HAL_GPIO_WritePin(TFT_DC_PORT, TFT_DC_PIN, GPIO_PIN_SET); // DC=1 HAL_GPIO_WritePin(TFT_CS_PORT, TFT_CS_PIN, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, data, len, HAL_MAX_DELAY); HAL_GPIO_WritePin(TFT_CS_PORT, TFT_CS_PIN, GPIO_PIN_SET); }

这两个函数是整个驱动的基石,后续所有操作都建立在其之上。


关键初始化序列详解

以下是适用于大多数1.8寸ST7735S模组的标准初始化流程(含必要延时):

void ST7735_Init(void) { HAL_Delay(50); // 硬件复位 HAL_GPIO_WritePin(TFT_RST_PORT, TFT_RST_PIN, GPIO_PIN_RESET); HAL_Delay(15); HAL_GPIO_WritePin(TFT_RST_PORT, TFT_RST_PIN, GPIO_PIN_SET); HAL_Delay(150); ST7735_WriteCommand(0x11); // Sleep Out HAL_Delay(20); ST7735_WriteCommand(0x21); // Display Inversion ON HAL_Delay(10); ST7735_WriteCommand(0x36); // MADCTL: 控制显示方向 uint8_t madctl = 0xC0; // 180°旋转 + BGR顺序(常见模组) ST7735_WriteData(&madctl, 1); ST7735_WriteCommand(0x3A); // COLMOD: 设置像素格式 uint8_t color_mode = 0x05; // 16-bit/RGB565 ST7735_WriteData(&color_mode, 1); ST7735_WriteCommand(0x29); // Display ON }

📌重点说明
-0x21启用显示反相,可改善视觉对比度;
-0xC0是很多淘宝“小黄屏”的标准配置,若你的屏是正面安装,请尝试改为0x000x60
- 所有延时不可省略,尤其是复位后和Sleep Out之后。


实现“画点”函数:一切图形绘制的基础

有了初始化,下一步就是真正开始绘图。最基础的操作是DrawPixel

void ST7735_SetAddressWindow(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1) { ST7735_WriteCommand(0x2A); // Column Address Set uint8_t col_addr[4] = {0x00, x0 + 2, 0x00, x1 + 2}; // 偏移补偿 ST7735_WriteData(col_addr, 4); ST7735_WriteCommand(0x2B); // Page Address Set uint8_t row_addr[4] = {0x00, y0 + 1, 0x00, y1 + 1}; ST7735_WriteData(row_addr, 4); } void ST7735_DrawPixel(int16_t x, int16_t y, uint16_t color) { if (x < 0 || x >= 128 || y < 0 || y >= 160) return; ST7735_SetAddressWindow(x, y, x, y); ST7735_WriteCommand(0x2C); // RAMWR - Start Writing to GRAM uint8_t color_data[2] = {(color >> 8), color & 0xFF}; ST7735_WriteData(color_data, 2); }

💡 小技巧:color >> 8取高字节放在前面,是因为SPI按MSB先行传输,而RGB565高位是R(红)。

虽然逐点绘制效率很低,但它是我们构建更高阶函数(如画线、填充矩形、显示字符)的起点。


常见问题排查指南:老司机的经验都在这儿了

别以为写了代码就能点亮。以下是新手最常遇到的问题及解决方案。

❌ 问题1:屏幕全白 / 花屏 / 乱码

可能原因
- 初始化序列错误或缺少关键命令;
- SPI速率过高导致采样失败;
- DC线未正确切换,导致命令被当作数据处理。

解决方法
- 使用逻辑分析仪抓取波形,确认0x11,0x29等命令是否成功下发;
- 调试阶段将SPI降频至2~4MHz验证功能;
- 检查DC引脚电平切换是否准确。


❌ 问题2:颜色明显偏红或发白

典型现象:本该是白色的画面看起来偏粉红,绿色显示不出来。

根源:RGB565字节顺序错乱,或MADCTL设置了BGR但程序仍按RGB处理。

解决方法
- 查看模组规格书,确认是否使用BGR排列;
- 修改MADCTL值测试不同组合(0x00,0x40,0x80,0xC0);
- 在PC端用Python生成测试图验证颜色准确性。


❌ 问题3:刷新慢得像幻灯片

瓶颈分析
- 每次画点都重复设置地址窗口;
- 使用软件模拟SPI而非硬件外设;
- 未启用DMA批量传输。

优化策略
- 绘制大区域前一次性设置窗口,然后连续写入数据;
- 使用硬件SPI并将速率提升至12~15MHz;
- 对于STM32F4及以上型号,可结合DMA实现零CPU干预传输;
- 若RAM不足(如F103仅20KB),避免建立完整帧缓冲,采用“边渲染边发送”。


工程最佳实践:让你的驱动更健壮、更易移植

要想写出工业级可用的驱动代码,光能运行还不够。以下是一些值得遵循的设计原则:

✅ 电源去耦不可少

在ST7735的VCC引脚附近并联10μF电解电容 + 0.1μF陶瓷电容,有效抑制启动瞬间的电流冲击和高频噪声。

✅ 信号走线尽量短

SPI属于高速信号,建议走线不超过10cm,并远离电机、继电器等干扰源。如果使用杜邦线,尽量选择屏蔽线或缩短长度。

✅ 模块化封装驱动文件

将ST7735驱动独立为st7735.c/st7735.h,对外只暴露初始化、清屏、画点等接口,便于跨项目复用。

✅ 添加背光PWM控制

利用定时器通道输出PWM控制BLK引脚,实现亮度调节。例如:

__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, brightness); // 0~100

既能节能,又能延长OLED/TFT寿命。

✅ 加入看门狗防死锁

屏幕卡住可能导致系统无响应。加入独立看门狗(IWDG),定期喂狗,一旦界面冻结超过阈值自动重启。


结语:底层驱动是通往GUI世界的钥匙

当你亲手让第一行文字出现在那块小小的彩屏上时,你会明白:这不仅仅是一个“显示设备”,而是嵌入式系统与用户之间最重要的桥梁之一。

ST7735 + STM32这套组合,正是通往复杂人机交互系统的绝佳起点。它教会我们的不仅是SPI通信、寄存器配置、内存管理,更是一种思维方式——如何在资源受限的环境下,精准掌控每一个硬件细节。

未来如果你想接入LVGL、TouchGFX等轻量级GUI框架,你会发现,这一切的根基,都始于你现在写的这个DrawPixel函数。

所以,不妨现在就打开你的开发板,试试点亮那块沉睡的小屏幕吧。
如果你在调试过程中遇到了奇怪的现象,欢迎在评论区留言交流,我们一起排坑。

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

Z-Image-Turbo为何快?8步生成技术原理与部署优化解析

Z-Image-Turbo为何快&#xff1f;8步生成技术原理与部署优化解析 1. 背景与核心价值 近年来&#xff0c;AI图像生成技术迅速发展&#xff0c;从早期的DALLE、Stable Diffusion到如今的高效蒸馏模型&#xff0c;生成速度和质量不断提升。然而&#xff0c;大多数高质量文生图模…

作者头像 李华
网站建设 2026/1/15 3:48:26

ArduPilot自动航线拍摄设置:手把手教程

ArduPilot自动航线拍摄&#xff1a;从原理到实战的全链路工程解析你有没有遇到过这样的场景&#xff1f;在一片广袤农田上&#xff0c;飞手顶着烈日操控无人机来回穿梭&#xff0c;只为采集一组正射影像。稍有不慎&#xff0c;航向偏移、重叠不足&#xff0c;后期建模直接“破洞…

作者头像 李华
网站建设 2026/1/15 3:48:10

H5GG:5个颠覆性功能重新定义iOS设备无限可能

H5GG&#xff1a;5个颠覆性功能重新定义iOS设备无限可能 【免费下载链接】H5GG an iOS Mod Engine with JavaScript APIs & Html5 UI 项目地址: https://gitcode.com/gh_mirrors/h5/H5GG 在iOS生态系统中&#xff0c;H5GG正以革命性的方式改变着我们对设备功能的认知…

作者头像 李华
网站建设 2026/1/15 3:47:58

中文逆文本标准化避坑指南:云端GPU省去80%配置时间

中文逆文本标准化避坑指南&#xff1a;云端GPU省去80%配置时间 你是不是也遇到过这样的情况&#xff1a;客户要求语音转写系统能把“两千三”自动变成“2300”&#xff0c;“百分之五”转成“5%”&#xff0c;结果本地环境一通折腾&#xff0c;zh_itn.fst 文件编译报错、依赖版…

作者头像 李华
网站建设 2026/1/15 3:47:50

性能翻倍:通义千问3-14B的FP8量化调优指南

性能翻倍&#xff1a;通义千问3-14B的FP8量化调优指南 1. 引言&#xff1a;为何选择Qwen3-14B进行FP8量化优化&#xff1f; 在当前大模型部署成本高企、推理延迟敏感的背景下&#xff0c;如何在有限硬件资源下实现高性能推理成为工程落地的核心挑战。通义千问3-14B&#xff0…

作者头像 李华
网站建设 2026/1/15 3:47:31

EasyFloat:10个技巧让Android悬浮窗开发更简单![特殊字符]

EasyFloat&#xff1a;10个技巧让Android悬浮窗开发更简单&#xff01;&#x1f680; 【免费下载链接】EasyFloat &#x1f525; EasyFloat&#xff1a;浮窗从未如此简单&#xff08;Android可拖拽悬浮窗口&#xff0c;支持页面过滤、自定义动画&#xff0c;可设置单页面浮窗、…

作者头像 李华