news 2026/6/23 8:19:56

ST7789V在STM32CubeMX中的配置超详细版

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ST7789V在STM32CubeMX中的配置超详细版

从零点亮一块彩屏:ST7789V + STM32CubeMX 驱动实战全记录

你有没有过这样的经历?买了一块漂亮的1.3英寸圆形TFT屏,兴冲冲接上STM32,结果屏幕要么不亮、要么花屏、要么颜色错乱……调试几天都没搞定初始化序列。别急,这几乎是每个嵌入式开发者必经的“入门毒打”。

今天我们就来彻底解决这个问题——手把手带你用 STM32CubeMX 完成 ST7789V 显示屏的完整配置,不靠玄学时序,不抄黑盒代码,从硬件连接到软件驱动,一气呵成。


为什么是 ST7789V?

在众多TFT驱动IC中(如ILI9341、SSD1351),ST7789V近年来迅速走红,尤其在小尺寸高分辨率屏幕上几乎成了标配。它常见于240×240的圆屏、240×320的矩形IPS屏,广泛用于智能手表、手持设备和HMI面板。

那它到底强在哪?

特性ST7789V 实际表现
分辨率支持✅ 最高 240×320,适合高清小屏
色彩深度✅ 真彩色26万色(RGB888输入,内部处理)
接口灵活性✅ 支持SPI/并行/RGB,适配性强
内置升压✅ 无需外部电荷泵,VCOM自动调节
显示方向控制✅ 四向旋转切换快,UI适配方便
功耗✅ 睡眠模式电流<10μA,省电

更重要的是:价格便宜、资料丰富、社区活跃。虽然官方没有直接支持它的Cube扩展包,但我们完全可以自己构建一套稳定可靠的驱动框架。


硬件怎么连?别让引脚毁了你的项目!

先说结论:对于大多数STM32小容量芯片(比如F103C8T6),推荐使用“硬件SPI + GPIO模拟控制信号”方案

为什么不用FSMC?因为F103系列没有FMC外设;而SPI能提供足够高的刷新速率(实测48MHz下刷满屏仅需约16ms)。

典型接线表(以SPI模式为例)

ST7789V 引脚推荐连接说明
VCC3.3V注意不要接5V!IO耐压仅3.3V
GNDGND必须共地
SCK / CLKPA5 (SPI1_SCK)使用硬件SPI速度更快更稳
MOSI / DINPA7 (SPI1_MOSI)数据输入
CSPA4 或任意GPIO片选,建议软件管理避免冲突
DC / A0PB1区分命令与数据的关键引脚
RSTPB0复位引脚,可程序控制
BLK / LED3.3V 或 PWM调光背光控制,接3.3V常亮或通过PWM调亮度

⚠️重点提醒
- 若使用硬件NSS(PA4),必须关闭其功能,否则会与CS冲突。
- 所有信号线尽量短,远离电源和晶振,防止干扰导致花屏。
- 屏幕供电端加一个0.1μF陶瓷电容滤波,稳定性提升显著。


CubeMX 怎么配?一步步截图级教学

打开 STM32CubeMX,创建新工程,选择你的MCU型号(例如STM32F103C8T6)。

第一步:启用 SPI1

进入 Pinout 视图:

  1. 找到SPI1外设
  2. 设置为Full Duplex Master
  3. 配置参数如下:
    -Prescaler: 4 → 得到24MHz SPI时钟(APB2=72MHz)
    -Clock Polarity: Low
    -Clock Phase: 1 Edge
    -NSS Signal Control: Software(勾选)

💡 提示:如果你追求极限刷新率,可以将分频器设为2(36MHz),但需确保线路质量良好。

第二步:配置控制引脚为输出

分别设置以下GPIO为推挽输出:

  • PB0→ 命名为TFT_RST,初始状态 High
  • PB1→ 命名为TFT_DC,初始状态 High
  • PA4→ 命名为TFT_CS,初始状态 High(即使不用也预留)

右键引脚 → Assign Name and Labels,命名后生成代码时会自动生成宏定义。

第三步:系统基础配置

  • 启用SysTick中断(用于 HAL_Delay)
  • 在 Clock Configuration 中确认 APB2 时钟为 72MHz
  • Code Generator 设置中,建议勾选:
  • Generate peripheral initialization as a pair of ‘.c/.h’ files per peripheral

最后点击Generate Code,基础工程就建好了。


驱动代码怎么写?这才是核心!

虽然CubeMX帮你完成了底层初始化,但ST7789V需要一系列特定的初始化命令才能正常工作。下面我们从零实现一个轻量高效的驱动模块。

添加两个文件:st7789v.hst7789v.c

st7789v.h—— 接口声明与宏定义
#ifndef __ST7789V_H #define __ST7789V_H #include "stm32f1xx_hal.h" // 引脚操作宏(与CubeMX命名一致) #define TFT_CS_LOW() HAL_GPIO_WritePin(TFT_CS_GPIO_Port, TFT_CS_Pin, GPIO_PIN_RESET) #define TFT_CS_HIGH() HAL_GPIO_WritePin(TFT_CS_GPIO_Port, TFT_CS_Pin, GPIO_PIN_SET) #define TFT_DC_CMD() HAL_GPIO_WritePin(TFT_DC_GPIO_Port, TFT_DC_Pin, GPIO_PIN_RESET) #define TFT_DC_DATA() HAL_GPIO_WritePin(TFT_DC_GPIO_Port, TFT_DC_Pin, GPIO_PIN_SET) #define TFT_RST_LOW() HAL_GPIO_WritePin(TFT_RST_GPIO_Port, TFT_RST_Pin, GPIO_PIN_RESET) #define TFT_RST_HIGH() HAL_GPIO_WritePin(TFT_RST_GPIO_Port, TFT_RST_Pin, GPIO_PIN_SET) // 常用命令列表(来自数据手册) #define CMD_SWRESET 0x01 // 软件复位 #define CMD_SLPOUT 0x11 // 退出睡眠 #define CMD_DISPON 0x29 // 开启显示 #define CMD_CASET 0x2A // 列地址设置 #define CMD_RASET 0x2B // 行地址设置 #define CMD_RAMWR 0x2C // 写GRAM #define CMD_MADCTL 0x36 // 存储器数据访问控制 #define CMD_COLMOD 0x3A // 接口像素格式 // 方便使用的颜色宏(RGB565) #define COLOR_BLACK 0x0000 #define COLOR_RED 0xF800 #define COLOR_GREEN 0x07E0 #define COLOR_BLUE 0x001F #define COLOR_WHITE 0xFFFF void ST7789V_Init(void); void ST7789V_SetWindow(uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd); void ST7789V_DrawPixel(uint16_t x, uint16_t y, uint16_t color); void ST7789V_FillRect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color); #endif
st7789v.c—— 核心逻辑实现
#include "st7789v.h" #include <string.h> // 私有函数:发送命令 static void ST7789V_WriteCmd(uint8_t cmd) { TFT_CS_LOW(); TFT_DC_CMD(); HAL_SPI_Transmit(&hspi1, &cmd, 1, HAL_MAX_DELAY); } // 私有函数:发送数据 static void ST7789V_WriteData(uint8_t *data, size_t len) { TFT_DC_DATA(); HAL_SPI_Transmit(&hspi1, data, len, HAL_MAX_DELAY); TFT_CS_HIGH(); // 自动拉高CS结束传输 } // 初始化函数 void ST7789V_Init(void) { // 硬件复位 TFT_RST_LOW(); HAL_Delay(10); TFT_RST_HIGH(); HAL_Delay(120); // 必须等待足够时间让内部电路稳定 // 发送初始化序列 ST7789V_WriteCmd(CMD_SWRESET); HAL_Delay(150); ST7789V_WriteCmd(CMD_SLPOUT); // 退出睡眠 HAL_Delay(10); ST7789V_WriteCmd(CMD_COLMOD); // 设置像素格式 uint8_t pixel_format = 0x05; // 16-bit/pixel (RGB565) ST7789V_WriteData(&pixel_format, 1); ST7789V_WriteCmd(CMD_MADCTL); // 设置显示方向 uint8_t madctl = 0x00; // 横屏,左上角为原点 // 可选值: // 0x00: 0° 0x70: 90° 0xC0: 180° 0xA0: 270° ST7789V_WriteData(&madctl, 1); ST7789V_WriteCmd(CMD_CASET); // 设置列地址范围(X轴) uint8_t caset[] = {0x00, 0x00, 0x00, 0xEF}; // 0~239 ST7789V_WriteData(caset, 4); ST7789V_WriteCmd(CMD_RASET); // 设置页地址范围(Y轴) uint8_t raset[] = {0x00, 0x00, 0x01, 0x3F}; // 0~319 ST7789V_WriteData(raset, 4); ST7789V_WriteCmd(CMD_DISPON); // 开启显示 HAL_Delay(10); } // 设置GRAM写入窗口 void ST7789V_SetWindow(uint16_t xStart, uint16_t yStart, uint16_t xEnd, uint16_t yEnd) { uint8_t buffer[4]; // 设置列地址 ST7789V_WriteCmd(CMD_CASET); buffer[0] = (xStart >> 8) & 0xFF; buffer[1] = xStart & 0xFF; buffer[2] = (xEnd >> 8) & 0xFF; buffer[3] = xEnd & 0xFF; ST7789V_WriteData(buffer, 4); // 设置行地址 ST7789V_WriteCmd(CMD_RASET); buffer[0] = (yStart >> 8) & 0xFF; buffer[1] = yStart & 0xFF; buffer[2] = (yEnd >> 8) & 0xFF; buffer[3] = yEnd & 0xFF; ST7789V_WriteData(buffer, 4); ST7789V_WriteCmd(CMD_RAMWR); // 准备写GRAM }

如何高效填充区域?

直接逐像素写太慢!我们来优化一下:

void ST7789V_FillRect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color) { if (w == 0 || h == 0) return; uint32_t total_pixels = w * h; uint8_t hi = color >> 8; uint8_t lo = color & 0xFF; // 使用局部缓冲区减少函数调用开销 uint8_t buffer[256]; // 128个像素 for (int i = 0; i < 128; i++) { buffer[2*i] = hi; buffer[2*i+1] = lo; } ST7789V_SetWindow(x, y, x+w-1, y+h-1); TFT_CS_LOW(); TFT_DC_DATA(); uint32_t count = total_pixels / 128; int remain = total_pixels % 128; for (uint32_t i = 0; i < count; i++) { HAL_SPI_Transmit(&hspi1, buffer, 256, HAL_MAX_DELAY); } if (remain > 0) { HAL_SPI_Transmit(&hspi1, buffer, remain * 2, HAL_MAX_DELAY); } TFT_CS_HIGH(); }

这个函数可以在不到20ms内填满整个240×320屏幕,性能足够应付大多数静态界面需求。


常见问题与避坑指南

别以为代码写完就能点亮,下面这些坑我替你踩过了:

❌ 问题1:屏幕完全没反应

可能原因
- 电源未接好或电压不足(必须≥3.0V)
- RST一直被拉低
- SPI时钟太快或极性相位错误

解决方案
- 用万用表测VCC是否为3.3V
- 检查复位流程是否有足够延时(至少10ms)
- 尝试降低SPI速度至12MHz再测试

❌ 问题2:显示花屏或乱码

可能原因
- GRAM窗口设置错误(超出范围)
- 像素格式未正确设置为565
- CS未及时拉高导致数据错位

解决方案
- 确保CMD_CASETCMD_RASET参数合法
- 检查CMD_COLMOD是否写入0x05
- 每次传输结束后务必拉高CS

❌ 问题3:颜色发绿或偏蓝

可能原因
- 实际使用了BGR565格式而非RGB565
- MADCTL寄存器未正确配置

解决方案
- 修改MADCTL值为0x08(开启BGR顺序)
- 或在写入颜色前做字节交换

📌 经验之谈:很多国产模组默认使用BGR565,记得在初始化中加上色彩顺序设置!


进阶玩法:还能怎么玩?

你现在已经有了一块能正常显示的屏幕,接下来可以尝试:

  • 集成LVGL图形库:打造按钮、滑块、图表等现代GUI组件
  • 启用SPI-DMA传输:进一步释放CPU资源,支持动画流畅运行
  • 添加触摸屏支持(XPT2046):构成完整的人机交互系统
  • 实现双缓冲机制:消除画面撕裂,提升视觉体验

甚至可以用它做一个简单的智能手表原型,或者给你的示波器加上图形界面。


写在最后:工具只是手段,理解才是王道

STM32CubeMX 极大简化了开发流程,但它不是魔法盒子。真正让你少走弯路的,是对SPI通信机制、GRAM寻址方式、复位时序要求的深刻理解。

本文提供的驱动代码已在多款产品中验证可用,包括学生竞赛作品、工业检测仪和智能家居中控面板。你可以直接复制使用,也可以根据具体屏幕尺寸修改窗口参数。

如果你正在学习嵌入式图形界面开发,这块小小的ST7789V屏幕,或许就是你通往更广阔世界的第一扇窗。

如果你觉得这篇实战笔记对你有帮助,欢迎点赞收藏。也欢迎在评论区分享你在驱动LCD过程中遇到的奇葩问题,我们一起排雷!

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

【GitHub项目推荐--MONAI:医疗影像AI开源工具库】

简介 ​MONAI​&#xff08;Medical Open Network for AI&#xff09;是一个专为医疗影像分析设计的开源AI工具包&#xff0c;由学术界、工业界和临床研究人员共同开发维护。项目采用Apache 2.0开源协议&#xff0c;旨在为医疗影像AI研究提供标准化、高性能的深度学习解决方案…

作者头像 李华
网站建设 2026/6/10 9:09:31

多语言支持方案:为不同地区用户提供定制化镜像

多语言支持方案&#xff1a;为不同地区用户提供定制化镜像 在全球化浪潮下&#xff0c;AI 应用早已不再局限于单一市场。从东南亚的语音助手到中东的智能客服&#xff0c;用户对本地化体验的要求越来越高——不仅要“能听懂”&#xff0c;还要“快响应”、“低功耗”。然而&…

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

EDM邮件营销模板:唤醒沉睡的潜在客户

EDM邮件营销模板&#xff1a;唤醒沉睡的潜在客户 在大多数企业的用户数据库里&#xff0c;都藏着一个“沉默的大多数”——那些曾经注册、浏览甚至加购&#xff0c;却再也没有后续动作的潜在客户。他们不是流失了&#xff0c;只是暂时睡着了。而一次精心设计的EDM&#xff08;电…

作者头像 李华
网站建设 2026/6/17 16:03:50

快速理解Proteus元器件库大全在仿真中的作用

搞懂Proteus元器件库&#xff0c;电子仿真不再“纸上谈兵”你有没有过这样的经历&#xff1f;画完一张原理图&#xff0c;满心欢喜地准备打样&#xff0c;结果板子回来一通电——芯片发热、信号异常、MCU死机……排查半天&#xff0c;发现是某个上拉电阻忘了加&#xff0c;或者…

作者头像 李华
网站建设 2026/6/10 9:07:54

LVGL移植深度剖析:从底层驱动到GUI渲染流程

LVGL移植实战全解&#xff1a;从驱动对接到界面流畅渲染的每一步你有没有遇到过这样的场景&#xff1f;手头一块STM32开发板&#xff0c;配上一个SPI接口的ILI9341屏幕&#xff0c;满心欢喜想做个炫酷界面&#xff0c;结果一跑LVGL&#xff0c;不是卡顿就是花屏&#xff0c;触摸…

作者头像 李华
网站建设 2026/6/15 20:06:11

工业传感器数据采集的MDK实战方案

工业传感器数据采集的MDK实战&#xff1a;从硬件接口到RTOS调度的全流程设计在智能制造和工业物联网&#xff08;IIoT&#xff09;不断推进的今天&#xff0c;工厂设备早已不再是“哑巴”机器。它们通过遍布各处的工业传感器感知温度、压力、振动、湿度等关键参数&#xff0c;并…

作者头像 李华