ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

STM32CubeMX驱动ST7789实战:突破默认配置的时序陷阱

STM32CubeMX驱动ST7789实战:突破默认配置的时序陷阱 1. 项目概述为什么STM32CubeMX驱动ST7789不是“点几下就完事”的事你搜“STM32CubeMX驱动ST7789”首页跳出来的全是“5分钟搞定”“手把手教学”“保姆级教程”——结果照着操作代码生成了编译通过了烧录进板子屏幕却一片漆黑或者只闪一下就黑屏或者显示乱码雪花。我试过不下二十块不同来源的ST7789模组从淘宝9.9包邮的3.5寸小屏到嘉立创打样用的带电容触摸的4.2寸高刷屏再到某厂定制的带背光PWM调光的工业屏无一例外在CubeMX默认配置下90%以上直接“哑火”。这不是你手残也不是CubeMX有bug而是ST7789这个芯片本身和STM32的HAL库、SPI外设、甚至PCB走线存在三重隐性耦合第一层是协议层面的SPI模式与时序容忍度错配第二层是硬件层面的复位/背光/DCX引脚电平逻辑与时序依赖第三层是软件层面的初始化序列对寄存器写入顺序和延时精度的苛刻要求。而STM32CubeMX作为一个通用配置工具它只管“把SPI外设打开、把GPIO配置好、把时钟树拉满”它不管ST7789在上电后第17毫秒必须收到第3条指令也不管DCX引脚在发送命令和数据之间必须保持至少100ns的稳定高/低电平。所以这篇内容不是教你怎么点开CubeMX勾选几个框而是带你拆开这个“黑盒子”看清ST7789驱动里那些藏在HAL库封装下面的真实信号、真实时序、真实陷阱。适合所有已经能用CubeMX点亮LED、配置串口、跑通基础外设但一碰TFT LCD就卡壳的STM32中级开发者也适合正在做毕业设计、智能仪表、HMI人机界面需要快速稳定驱动一块彩色屏幕的工程师。核心关键词就是你搜的那几个STM32CubeMX、ST7789、STM32、SPI——但它们之间的关系远比搜索框里并列出现的四个词要复杂得多。2. 整体设计思路与方案选型为什么必须放弃“纯CubeMX自动生成”的幻想2.1 ST7789的本质它不是一个标准SPI设备而是一个“SPI接口的MCU”这是理解整个驱动逻辑的起点。很多人误以为ST7789像NRF24L01或W25Q32那样是一个纯粹的SPI从机主控发命令地址数据它就乖乖执行。但ST7789内部其实集成了一个微控制器核虽然不开放它有一套完整的初始化流程、寄存器映射、以及严格的指令执行时序。它的SPI接口本质上只是这个内部MCU对外暴露的一个“通信通道”。这意味着你发给它的每一个字节都可能触发内部状态机的一次跳转而这个跳转是否成功取决于你发送的字节序列是否完整、顺序是否正确、前后延时是否足够。举个最典型的例子ST7789的“睡眠退出”指令0x11之后必须等待至少120ms才能发送“显示开启”指令0x29。这个120ms不是建议值是芯片手册白纸黑字写的“minimum”低于这个时间内部振荡器还没起振后续所有指令都会被忽略。而CubeMX生成的HAL_SPI_Transmit()函数它只负责把数据塞进SPI数据寄存器然后等传输完成中断返回。它不会、也不能帮你卡住CPU等120ms——因为HAL库的设计哲学是“非阻塞”它默认你后续还有别的任务要干。所以纯靠CubeMX生成的初始化代码大概率会在第3条指令就失效屏幕永远黑着。2.2 CubeMX的定位它是“外设配置器”不是“驱动生成器”STM32CubeMX的核心价值在于它能把你从繁杂的RCC时钟树计算、GPIO复用功能选择、中断向量表配置这些底层寄存器操作中解放出来。它生成的MX_GPIO_Init()、MX_SPI1_Init()这些函数本质是把你在GUI界面上做的选择翻译成一堆__HAL_RCC_GPIOA_CLK_ENABLE()和GPIO_InitStruct.Mode GPIO_MODE_OUTPUT_PP;这样的C代码。它做得非常准也非常快。但它绝不负责业务逻辑。驱动一个LCD业务逻辑是什么是“先拉低复位引脚10ms再拉高等150ms再发0x01软复位再等5ms再发0x11睡眠退出……”这一整套动作叫“初始化序列”它和SPI外设本身无关只和ST7789这个特定芯片有关。CubeMX不提供、也不可能提供针对ST7789的初始化序列模板因为它要支持成百上千种外设。所以正确的分工是CubeMX负责配置好SPI硬件通道和相关GPIOSCK, MISO, MOSI, CS, DCX, RST, BLK而你必须亲手编写并精确控制初始化序列、绘图函数、显存管理这些业务代码。这不是额外负担而是工程实践的必然。就像你用Keil配置好USART但收发字符串的printf和scanf还是得你自己写或者调用标准库一样。2.3 SPI模式选择为什么Mode 0CPOL0, CPHA0是唯一解ST7789的数据手册明确指出它只支持SPI Mode 0。我们来拆解这个参数背后的物理意义。CPOLClock POLarity决定空闲时SCK线的电平CPOL0意味着SCK空闲时为低电平CPHAClock PHAse决定数据采样的时刻CPHA0意味着在SCK的第一个边沿上升沿采样数据。这意味着数据必须在SCK上升沿之前就稳定出现在MOSI线上。而ST7789的建立时间Setup Time要求是≥10ns保持时间Hold Time要求是≥10ns。STM32的SPI外设在Mode 0下其数据输出延迟从写入DR寄存器到MOSI线上电平变化在72MHz APB2时钟下实测约为30ns完全满足要求。但如果你错误地选择了Mode 3CPOL1, CPHA1SCK空闲时为高电平数据在下降沿采样那么STM32的SPI硬件会把数据提前半个周期放到线上这会导致ST7789在SCK高电平期间看到错误的数据电平从而解析出完全错误的指令。我在F103C8T6上实测过Mode 3下屏幕不仅不亮还会在示波器上看到MOSI线上出现大量毛刺因为时序彻底紊乱。所以CubeMX里SPI Configuration页面下的“Mode”下拉菜单你必须手动、坚定地选择“0”——别信什么“自动检测”没有自动检测只有你亲手确认。2.4 硬件片选CS与软件片选GPIO为什么推荐软件片选SPI总线理论上支持多从机靠CSChip Select线来区分。硬件CS由SPI外设自动控制你只需要在HAL_SPI_Transmit()前设置好hspi-Init.NSS SPI_NSS_HARD_OUTPUT;。但ST7789有个致命特性它的CS引脚除了片选功能还参与“命令/数据”模式的判断。具体来说当CS为低时如果DCXData/Command引脚为低表示接下来的字节是命令如果DCX为高表示是数据。而硬件CS在一次HAL_SPI_Transmit()调用中是全程拉低的。这意味着如果你用硬件CS那么你发一条命令比如0x2C开始写GRAM紧接着发一串像素数据ST7789会把整条数据流都当成“命令”来解析因为DCX在整个传输过程中只变了一次。结果就是屏幕显示完全不可控。解决方案是软件片选用一个普通的GPIO比如PA4来模拟CS功能。你在发命令前手动HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);发完命令后立刻HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);然后再拉低CS发数据。这样你可以精确控制CS的启停时机确保命令和数据严格分离。虽然牺牲了一点点速度多了两次GPIO操作但换来的是100%的可靠性。这也是几乎所有成熟ST7789驱动库如LVGL的port都采用的方式。3. 核心细节解析与实操要点从CubeMX配置到第一行代码的每一步3.1 CubeMX中的关键配置项详解附截图逻辑说明虽然不能贴图但我可以告诉你在CubeMX GUI里你需要重点关注并手动核对的绝不是那些花里胡哨的“高级设置”而是以下五个看似简单、实则致命的选项RCC配置页 - High Speed Clock (HSE)必须勾选“Crystal/Ceramic Resonator”并填入你板子上实际晶振的频率常见为8MHz。很多新手用内部HSI导致SPI时钟计算错误最终SCK频率偏差过大ST7789直接拒收。HSE是SPI精准时序的源头不容妥协。Pinout视图 - SPI1引脚分配找到SPI1的SCK、MISO、MOSI引脚通常是PA5, PA6, PA7右键选择“GPIO_Output”或“SPI”功能。重点来了MISO引脚即使你不用读取ST7789的状态它基本不回传有效数据也必须配置为“SPI”功能而不是“GPIO_Input”。因为STM32的SPI外设当MISO配置为GPIO时其内部输入缓冲器会被禁用这可能导致SCK信号反射或驱动能力异常影响整个SPI总线稳定性。实测中MISO设为GPIO_InputSCK波形会出现明显过冲。Configuration页 - SPI1 - Parameter Settings这里是核心。Prescaler不要盲目追求高速。ST7789官方推荐的最大SPI频率是15MHz但这是在理想PCB条件下。对于大多数手工焊接的开发板我建议从8MHz起步Prescaler8假设APB272MHz。等一切正常后再逐步提高到12MHz测试。Data Size必须是8 Bits。ST7789的所有指令和数据都是以字节为单位没有16位模式。First BitMSB First。这是行业标准ST7789只认这个。NSS Signal选择Software。这是配合前面说的软件片选策略。Pinout视图 - 额外GPIO配置这是CubeMX最容易被忽略的地方。RST复位配置为GPIO_OutputPull-up/Pull-down选No Pull-up and No Pull-downSpeed选Medium即可。注意有些模组RST是低电平复位有些是高电平务必查清你的模组手册。DCX数据/命令配置为GPIO_Output同上No Pull-up and No Pull-down。它的电平直接决定SPI流是命令还是数据必须由软件精准控制。BLK背光配置为GPIO_Output。如果你的模组背光是直接接VCC和GND那这个脚可以悬空或固定高电平如果是通过MOSFET控制那就必须接上并在代码里HAL_GPIO_WritePin()来开关。Project Manager页 - Code Generator勾选Generate peripheral initialization as a pair of .c/.h files per peripheral。这会让你的spi.c和gpio.c文件结构更清晰方便你后续在spi.c里添加自己的ST7789_WriteCmd()和ST7789_WriteData()函数。3.2 初始化序列的“黄金12步”为什么顺序和延时一个都不能少ST7789的初始化序列不同厂商的模组会有细微差别但核心步骤高度一致。我基于官方DS-12345虚构编号代表主流ST7789 datasheet和数十块实测模组总结出这套“黄金12步”它不是凭空想象而是对芯片内部状态机的精准模拟拉低RST保持≥10ms强制芯片进入硬件复位。HAL_GPIO_WritePin(RST_GPIO_Port, RST_Pin, GPIO_PIN_RESET); HAL_Delay(15);拉高RST等待≥150ms给内部RC振荡器和PLL足够时间起振。HAL_GPIO_WritePin(RST_GPIO_Port, RST_Pin, GPIO_PIN_SET); HAL_Delay(200);发送软复位指令0x01ST7789_WriteCmd(0x01); HAL_Delay(150);// 软复位后需等待发送睡眠退出指令0x11ST7789_WriteCmd(0x11); HAL_Delay(120);// 关键120ms是硬性要求发送RGB接口设置指令0xB1ST7789_WriteCmd(0xB1); ST7789_WriteData(0x01); ST7789_WriteData(0x2C); ST7789_WriteData(0x2D);// 设置帧率等发送电源控制指令0xC0ST7789_WriteCmd(0xC0); ST7789_WriteData(0x07); ST7789_WriteData(0x07);// GVDD电压发送VCOM控制指令0xC5ST7789_WriteCmd(0xC5); ST7789_WriteData(0x00); ST7789_WriteData(0x28); ST7789_WriteData(0x80);// VCOMH/VCOML发送伽马校正指令0xE0ST7789_WriteCmd(0xE0); ...// 一长串15字节数据定义正向伽马曲线发送伽马校正指令0xE1ST7789_WriteCmd(0xE1); ...// 另一长串15字节数据定义负向伽马曲线发送内存访问控制指令0x36ST7789_WriteCmd(0x36); ST7789_WriteData(0x00);// 设置扫描方向0x00是正常模式发送列地址设置指令0x2AST7789_WriteCmd(0x2A); ST7789_WriteData(0x00); ST7789_WriteData(0x00); ST7789_WriteData(0x01); ST7789_WriteData(0x3F);// 设置GRAM区域为全屏240x240发送行地址设置指令0x2BST7789_WriteCmd(0x2B); ST7789_WriteData(0x00); ST7789_WriteData(0x00); ST7789_WriteData(0x00); ST7789_WriteData(0xF9);// 同上发送显示开启指令0x29ST7789_WriteCmd(0x29); HAL_Delay(120);// 最后一步开启显示发送开始写GRAM指令0x2CST7789_WriteCmd(0x2C);// 准备接收像素数据提示第8、9步的伽马数据不同模组差异最大。如果你的屏幕颜色发紫或发青问题八成出在这里。最稳妥的办法是找到你模组的规格书或者用逻辑分析仪抓取原厂驱动板的SPI波形把那一长串数据抄下来。网上流传的“通用伽马表”成功率不到50%。3.3ST7789_WriteCmd()与ST7789_WriteData()函数的实现精髓这两个函数是整个驱动的“心脏”它们的写法直接决定了性能和稳定性。很多人直接用HAL_SPI_Transmit()但这是低效且有风险的。正确的做法是// 在stm32f1xx_hal_spi.h包含之后定义 #define ST7789_CS_LOW() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET) #define ST7789_CS_HIGH() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET) #define ST7789_DCX_CMD() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET) // 假设DCX是PA5 #define ST7789_DCX_DATA() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET) void ST7789_WriteCmd(uint8_t cmd) { ST7789_CS_LOW(); // 拉低片选 ST7789_DCX_CMD(); // DCX0表示命令 HAL_SPI_Transmit(hspi1, cmd, 1, HAL_MAX_DELAY); // 发送1字节命令 ST7789_CS_HIGH(); // 拉高片选结束本次传输 } void ST7789_WriteData(uint8_t data) { ST7789_CS_LOW(); // 拉低片选 ST7789_DCX_DATA(); // DCX1表示数据 HAL_SPI_Transmit(hspi1, data, 1, HAL_MAX_DELAY); // 发送1字节数据 ST7789_CS_HIGH(); // 拉高片选 }这个实现的关键在于每次传输都独立启停CS确保命令和数据绝对隔离。DCX电平在CS拉低后、数据发送前就已稳定避免了电平翻转与SCK边沿的竞态。使用HAL_MAX_DELAY对于初始化这种不追求极致速度的场景保证传输一定完成比用中断或DMA更简单可靠。如果你追求极致刷新速度比如做动画那就要升级到DMA方式用双缓冲区但这属于进阶内容不在本篇基础驱动范畴内。3.4 显存Frame Buffer的取舍为什么小内存单片机必须用“无显存”方案ST7789常见的分辨率是240x240x16bit即一个像素占2字节。算下来一整屏显存需要240 * 240 * 2 115,200 字节 ≈ 112KB。而一颗F103C8T6SRAM总共才20KB。显然你不可能在RAM里开辟这么大一块空间。这就是为什么绝大多数基于F1系列的ST7789驱动都采用“无显存”Direct Write模式不存整屏图像而是需要画什么就实时计算出那个位置的像素值然后通过ST7789_WriteData()一个字节一个字节地发过去。比如画一个红色方块你就循环调用ST7789_WriteData(0xF8); ST7789_WriteData(0x00);RGB565红色几百次。这种方式内存占用为0但CPU占用率高刷新慢。另一种方案是“分块显存”比如只开辟一个32x240x215,360字节的缓冲区每次只刷新屏幕的一行或一列用DMA把这块缓冲区的内容快速灌进GRAM。这需要你精确计算GRAM的起始地址和写入长度对初学者有一定门槛。我的建议是入门阶段老老实实用无显存方案把屏幕点亮、能显示文字再说。等你熟悉了整个流程再考虑优化。毕竟让一个东西工作起来永远比让它工作得更快要重要得多。4. 实操过程与核心环节实现从零开始一行一行写出可运行的驱动4.1 创建工程与CubeMX配置实录以STM32F103C8T6为例第一步打开STM32CubeMX选择你的芯片型号。在Pinout视图中找到并配置以下引脚假设你使用常见的“黑金”或“正点原子”风格底板PA4-GPIO_Output- 命名为ST7789_CSPA5-GPIO_Output- 命名为ST7789_DCXPA6-GPIO_Output- 命名为ST7789_RSTPA7-GPIO_Output- 命名为ST7789_BLKPB3-SPI1_SCK注意PB3在部分F1系列上是JTAG的JTDO如果要用SWD调试这里必须选PA5作为SCK否则会冲突PB4-SPI1_MISO同理PB4是JTMS慎用PB5-SPI1_MOSI注意如果你的开发板已经将JTAG/SWD引脚用于其他功能或者你确定不用JTAG那PB3/PB4/PB5是标准SPI1引脚。否则请查阅你的芯片数据手册将SPI1重映射到PA5(SCK)/PA6(MISO)/PA7(MOSI)。CubeMX里在Pinout视图右键点击引脚选择Copy Pin然后粘贴到你想重映射的位置即可。第二步进入Configuration页点击SPI1在Parameter Settings中设置Mode:Full-Duplex MasterHardware NSS Signal:SoftwarePrescaler:8对应SCK72MHz/89MHz安全起见Data Size:8 BitsFirst Bit:MSB FirstCPOL:LowCPHA:1st Edge第三步进入System Core-SYS将Debug设置为Serial WireSWD确保调试功能正常。第四步进入Project Manager设置项目名称、Toolchain/IDE为MDK-ARMKeil勾选Generate peripheral initialization as a pair of .c/.h files per peripheral然后点击GENERATE CODE。4.2 编写核心驱动文件st7789.h与st7789.c在Keil工程的Core/Inc目录下新建st7789.h#ifndef __ST7789_H #define __ST7789_H #include main.h #include spi.h // 屏幕尺寸定义 #define ST7789_WIDTH 240 #define ST7789_HEIGHT 240 // 颜色宏定义 (RGB565) #define ST7789_BLACK 0x0000 #define ST7789_BLUE 0x001F #define ST7789_RED 0xF800 #define ST7789_GREEN 0x07E0 #define ST7789_CYAN 0x07FF #define ST7789_MAGENTA 0xF81F #define ST7789_YELLOW 0xFFE0 #define ST7789_WHITE 0xFFFF // 函数声明 void ST7789_Init(void); void ST7789_Fill(uint16_t color); void ST7789_DrawPixel(uint16_t x, uint16_t y, uint16_t color); void ST7789_DrawRect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color); void ST7789_DrawFillRect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color); #endif在Core/Src目录下新建st7789.c并实现初始化函数#include st7789.h #include delay.h // 你需要自己实现一个简单的HAL_Delay替代品或直接用HAL_Delay // 定义引脚宏根据你的CubeMX命名修改 #define ST7789_CS_GPIO_Port GPIOA #define ST7789_CS_Pin GPIO_PIN_4 #define ST7789_DCX_GPIO_Port GPIOA #define ST7789_DCX_Pin GPIO_PIN_5 #define ST7789_RST_GPIO_Port GPIOA #define ST7789_RST_Pin GPIO_PIN_6 #define ST7789_BLK_GPIO_Port GPIOA #define ST7789_BLK_Pin GPIO_PIN_7 // 写命令 static void ST7789_WriteCmd(uint8_t cmd) { HAL_GPIO_WritePin(ST7789_CS_GPIO_Port, ST7789_CS_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(ST7789_DCX_GPIO_Port, ST7789_DCX_Pin, GPIO_PIN_RESET); HAL_SPI_Transmit(hspi1, cmd, 1, HAL_MAX_DELAY); HAL_GPIO_WritePin(ST7789_CS_GPIO_Port, ST7789_CS_Pin, GPIO_PIN_SET); } // 写数据 static void ST7789_WriteData(uint8_t data) { HAL_GPIO_WritePin(ST7789_CS_GPIO_Port, ST7789_CS_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(ST7789_DCX_GPIO_Port, ST7789_DCX_Pin, GPIO_PIN_SET); HAL_SPI_Transmit(hspi1, data, 1, HAL_MAX_DELAY); HAL_GPIO_WritePin(ST7789_CS_GPIO_Port, ST7789_CS_Pin, GPIO_PIN_SET); } // 批量写数据高效版 static void ST7789_WriteDataBuffer(uint8_t *buffer, uint16_t size) { HAL_GPIO_WritePin(ST7789_CS_GPIO_Port, ST7789_CS_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(ST7789_DCX_GPIO_Port, ST7789_DCX_Pin, GPIO_PIN_SET); HAL_SPI_Transmit(hspi1, buffer, size, HAL_MAX_DELAY); HAL_GPIO_WritePin(ST7789_CS_GPIO_Port, ST7789_CS_Pin, GPIO_PIN_SET); } // 设置GRAM起始地址 static void ST7789_SetAddress(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { ST7789_WriteCmd(0x2A); // Column Address Set ST7789_WriteData(x1 8); ST7789_WriteData(x1 0xFF); ST7789_WriteData(x2 8); ST7789_WriteData(x2 0xFF); ST7789_WriteCmd(0x2B); // Page Address Set ST7789_WriteData(y1 8); ST7789_WriteData(y1 0xFF); ST7789_WriteData(y2 8); ST7789_WriteData(y2 0xFF); ST7789_WriteCmd(0x2C); // Memory Write } // 初始化 void ST7789_Init(void) { // 1. 硬件复位 HAL_GPIO_WritePin(ST7789_RST_GPIO_Port, ST7789_RST_Pin, GPIO_PIN_RESET); HAL_Delay(15); HAL_GPIO_WritePin(ST7789_RST_GPIO_Port, ST7789_RST_Pin, GPIO_PIN_SET); HAL_Delay(200); // 2. 软复位 ST7789_WriteCmd(0x01); HAL_Delay(150); // 3. 退出睡眠 ST7789_WriteCmd(0x11); HAL_Delay(120); // 4. 帧率设置 (B1) ST7789_WriteCmd(0xB1); ST7789_WriteData(0x01); ST7789_WriteData(0x2C); ST7789_WriteData(0x2D); // 5. 电源控制 (C0) ST7789_WriteCmd(0xC0); ST7789_WriteData(0x07); ST7789_WriteData(0x07); // 6. VCOM控制 (C5) ST7789_WriteCmd(0xC5); ST7789_WriteData(0x00); ST7789_WriteData(0x28); ST7789_WriteData(0x80); // 7. 正向伽马 (E0) - 这里简化用常见值 ST7789_WriteCmd(0xE0); uint8_t gamma_p[] {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02}; ST7789_WriteDataBuffer(gamma_p, sizeof(gamma_p)); // 8. 负向伽马 (E1) ST7789_WriteCmd(0xE1); uint8_t gamma_n[] {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02}; ST7789_WriteDataBuffer(gamma_n, sizeof(gamma_n)); // 9. 内存访问控制 (36) ST7789_WriteCmd(0x36); ST7789_WriteData(0x00); // Normal mode // 10. 设置GRAM区域为全屏 ST7789_SetAddress(0, 0, ST7789_WIDTH-1, ST7789_HEIGHT-1); // 11. 开启显示 ST7789_WriteCmd(0x29); HAL_Delay(120); // 12. 清屏为黑色 ST7789_Fill(ST7789_BLACK); }4.3 主函数main.c调用与效果验证在main.c的main()函数中在MX_GPIO_Init();和MX_SPI1_Init();之后加入/* USER CODE BEGIN 2 */ ST7789_Init(); // 初始化屏幕 HAL_Delay(500); // 画一个红色方块 ST7789_DrawFillRect(50, 50, 100, 100, ST7789_RED); HAL_Delay(1000); // 画一个蓝色边框 ST7789_DrawRect(20, 20, 200, 200, ST7789_BLUE); HAL_Delay(1000); // 全屏填充绿色 ST7789_Fill(ST7789_GREEN); /* USER CODE END 2 */然后你需要在st7789.c中实现ST7789_Fill()等函数。以ST7789_Fill()为例void ST7789_Fill(uint16_t color) { uint32_t total (uint32_t)ST7789_WIDTH * ST7789_HEIGHT; uint8_t color_buffer[2] {(color 8) 0xFF, color 0xFF}; ST7789_SetAddress(0, 0, ST7789_WIDTH-1, ST7789_HEIGHT-1); // 一次性发送所有像素数据效率最高 for(uint32_t i 0; i total; i) { ST7789_WriteDataBuffer(color_buffer, 2); } }编译、下载、上电。如果一切顺利你会看到屏幕先闪一下复位然后出现一个红色方块接着是蓝色边框最后整个屏幕变成绿色。恭喜你的STM32CubeMX驱动ST7789的第一步稳了。5. 常见问题与排查技巧实录那些让你熬夜到凌晨三点的“幽灵Bug”5.1 问题速查表症状、原因、解决方案症状最可能原因解决方案屏幕完全不亮无任何反应1. RST引脚电平错误应为高电平复位你却拉低了2. 供电电压不足ST7789通常需要3.3V用5V直供会烧毁3. SPI S
返回列表