1. GD32VW553驱动1.47寸ST7789V3彩屏:硬件SPI移植与汉字显示实战
GD32VW553驱动1.47寸ST7789V3彩屏硬件SPI移植与汉字显示实战最近在做一个基于GD32VW553的小项目需要一块小巧、显示效果好的屏幕来展示信息。在网上找了一圈最终选定了这款1.47英寸的IPS彩屏分辨率172x320驱动芯片是ST7789V3。屏幕到手后发现厂家给的例程是基于标准库的要移植到GD32VW553上还得花点功夫。今天我就把整个移植过程从硬件连接到代码修改再到汉字显示的实现一步步分享给大家希望能帮你少走弯路。这块屏幕用的是SPI接口通信速度快占用MCU引脚少非常适合资源有限的嵌入式项目。咱们的目标是用GD32VW553的硬件SPI来驱动它并且能显示汉字、字符串、图形和变量。下面咱们就开始吧。1. 准备工作了解屏幕与获取资料1.1 屏幕基本信息首先咱们得知道自己手里的屏幕是什么规格。我用的这块屏参数如下参数规格工作电压3.3V工作电流90mA屏幕尺寸30mm x 37mm分辨率172 (H) x 320 (V) RGB驱动芯片ST7789V3通信接口SPI引脚数量8 Pin (2.54mm间距排针)注意屏幕是SPI从设备这意味着MCUGD32VW553要作为主机来控制它。接线时务必确认电压是3.3V接5V可能会烧坏屏幕。1.2 资料下载驱动屏幕离不开厂家提供的资料里面通常有初始化序列、引脚定义和参考代码。我用的屏幕资料可以通过下面的链接获取资料下载链接https://pan.baidu.com/s/15OWpndYzyW8kFPqmfKNfxQ提取码8888下载后你会找到一个压缩包解压后里面有一个【LCD】文件夹这就是咱们移植的基础。里面包含了屏幕的底层驱动代码和字库文件。2. 硬件连接把屏幕接到开发板上屏幕有8个引脚但实际必须接MCU的只有6个。如果MCU的GPIO资源紧张RES复位和BLK背光可以简化处理。2.1 引脚功能说明在接线前先搞清楚每个引脚是干什么的屏幕引脚功能必须连接MCU吗GND电源地是VCC电源 (3.3V)是SCLSPI时钟线 (SCK)是SDASPI数据线 (MOSI主出从入)是RES复位低电平有效可省可接MCU复位引脚DC数据/命令选择线是CSSPI片选线低电平有效是BLK背光控制可省可接3.3V或悬空SCL和SDA这是SPI通信的核心必须连接。DC这个引脚很关键。当DC为低电平时MCU发送的是命令如设置屏幕模式为高电平时发送的是要显示的数据。CS片选低电平选中屏幕开始通信。RES如果MCU引脚不够可以把它接到MCU的复位引脚上。这样MCU复位时屏幕也跟着复位省了一个GPIO。但这样就无法在程序运行中单独复位屏幕了。BLK背光控制。如果不需要调节亮度可以直接接3.3V让它常亮或者悬空有些模块内部已上拉。2.2 实际接线方案我手头的GD32VW553开发板资源还算充足所以我把所有引脚都接上了方便独立控制。接线如下屏幕引脚连接到GD32VW553引脚GNDGNDVCC3V3SCLPA11 (SPI时钟)SDAPA9 (SPI MOSI)RESPA7 (普通GPIO)DCPA6 (普通GPIO)CSPB11 (普通GPIO)BLKPB12 (普通GPIO)这里我选择了PA11和PA9作为SPI引脚是因为它们复用了GD32VW553的SPI功能。RES、DC、CS、BLK则用普通的GPIO输出模式来控制。3. 软件移植修改驱动代码硬件接好了接下来就是重头戏——修改代码让它在GD32VW553上跑起来。3.1 将源码加入工程首先把从厂家资料里拿到的【LCD】文件夹整个复制到你自己的GD32VW553工程目录下。然后在你的IDE比如Keil或IAR里把这个文件夹添加到工程中。提示如果添加后IDE里没显示试试在项目浏览器里右键点击选择“Refresh”刷新一下。3.2 修改头文件包含和类型定义厂家代码可能用了不同的硬件抽象层。我们需要做两处基础修改修改头文件找到所有#include sys.h的语句把它们改成#include systick.h因为GD32的标准库通常用systick.h来管理延时。添加类型定义在lcd_init.h等头文件的开头添加以下定义确保u8、u16、u32这些类型能被识别。#ifndef u8 #define u8 uint8_t #endif #ifndef u16 #define u16 uint16_t #endif #ifndef u32 #define u32 uint32_t #endif3.3 配置引脚与硬件SPI这是移植的核心我们需要根据之前的接线表重新定义引脚并配置GD32VW553的硬件SPI。打开lcd_init.h文件找到端口定义的部分修改成下面这样//-----------------LCD端口定义---------------- // 使能GPIO和SPI的时钟 #define LCD_RCU_ENABLE() rcu_periph_clock_enable(RCU_GPIOA); \ rcu_periph_clock_enable(RCU_GPIOB); \ rcu_periph_clock_enable(RCU_SPI); // SPI引脚 (复用功能) #define LCD_SCL_PORT GPIOA #define LCD_SCL_PIN GPIO_PIN_11 #define LCD_SCL_AF GPIO_AF_0 // 复用功能0对应SPI #define LCD_SDA_PORT GPIOA #define LCD_SDA_PIN GPIO_PIN_9 #define LCD_SDA_AF GPIO_AF_0 // 控制引脚 (普通GPIO输出) #define LCD_RES_PORT GPIOA #define LCD_RES_PIN GPIO_PIN_7 #define LCD_DC_PORT GPIOA #define LCD_DC_PIN GPIO_PIN_6 #define LCD_CS_PORT GPIOB #define LCD_CS_PIN GPIO_PIN_11 #define LCD_BLK_PORT GPIOB #define LCD_BLK_PIN GPIO_PIN_12 /* LCD信号控制宏定义 */ #define LCD_RES_Clr() gpio_bit_write(LCD_RES_PORT, LCD_RES_PIN, 0) //RES拉低 #define LCD_RES_Set() gpio_bit_write(LCD_RES_PORT, LCD_RES_PIN, 1) //RES拉高 #define LCD_DC_Clr() gpio_bit_write(LCD_DC_PORT, LCD_DC_PIN, 0) //DC拉低命令 #define LCD_DC_Set() gpio_bit_write(LCD_DC_PORT, LCD_DC_PIN, 1) //DC拉高数据 #define LCD_CS_Clr() gpio_bit_write(LCD_CS_PORT, LCD_CS_PIN, 0) //CS拉低选中 #define LCD_CS_Set() gpio_bit_write(LCD_CS_PORT, LCD_CS_PIN, 1) //CS拉高取消 #define LCD_BLK_Clr() gpio_bit_write(LCD_BLK_PORT, LCD_BLK_PIN, 0) //背光关 #define LCD_BLK_Set() gpio_bit_write(LCD_BLK_PORT, LCD_BLK_PIN, 1) //背光开接下来在lcd_init.c中编写引脚初始化和SPI配置函数LCD_GPIO_Initvoid LCD_GPIO_Init(void) { // 1. 使能时钟 LCD_RCU_ENABLE(); // 2. 配置SPI引脚为复用功能 gpio_af_set(LCD_SCL_PORT, LCD_SCL_AF, LCD_SCL_PIN); gpio_af_set(LCD_SDA_PORT, LCD_SDA_AF, LCD_SDA_PIN); // 3. 设置所有引脚的模式 // SPI引脚复用功能无上下拉 gpio_mode_set(LCD_SCL_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, LCD_SCL_PIN); gpio_mode_set(LCD_SDA_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, LCD_SDA_PIN); // 控制引脚推挽输出上拉 gpio_mode_set(LCD_RES_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, LCD_RES_PIN); gpio_mode_set(LCD_DC_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, LCD_DC_PIN); gpio_mode_set(LCD_CS_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, LCD_CS_PIN); gpio_mode_set(LCD_BLK_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, LCD_BLK_PIN); // 4. 设置输出选项推挽输出最高速度 gpio_output_options_set(LCD_SCL_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, LCD_SCL_PIN); gpio_output_options_set(LCD_SDA_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, LCD_SDA_PIN); gpio_output_options_set(LCD_RES_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, LCD_RES_PIN); gpio_output_options_set(LCD_DC_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, LCD_DC_PIN); gpio_output_options_set(LCD_CS_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, LCD_CS_PIN); gpio_output_options_set(LCD_BLK_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, LCD_BLK_PIN); // 5. 初始状态片选高不选中数据/命令高默认数据状态 LCD_CS_Set(); LCD_DC_Set(); // 6. 配置硬件SPI参数 spi_parameter_struct spi_init_struct; spi_struct_para_init(spi_init_struct); // 先初始化结构体 spi_init_struct.trans_mode SPI_TRANSMODE_FULLDUPLEX; // 全双工模式 spi_init_struct.device_mode SPI_MASTER; // 主机模式 spi_init_struct.frame_size SPI_FRAMESIZE_8BIT; // 8位数据帧 spi_init_struct.clock_polarity_phase SPI_CK_PL_HIGH_PH_2EDGE; // 时钟极性相位根据屏幕手册 spi_init_struct.nss SPI_NSS_SOFT; // 软件控制NSS(CS) spi_init_struct.prescale SPI_PSC_4; // 4分频决定SPI速度 spi_init_struct.endian SPI_ENDIAN_MSB; // 高位在前 // 7. 初始化并使能SPI spi_init(spi_init_struct); spi_enable(); }3.4 重写底层数据发送函数厂家例程里可能用的是模拟SPI我们要改成硬件SPI。找到lcd_init.c里的LCD_Writ_Bus函数它负责发送一个字节数据将其替换为以下硬件SPI版本void LCD_Writ_Bus(u8 dat) { uint8_t recv_data 0; LCD_CS_Clr(); // 拉低CS开始传输 // 等待发送缓冲区为空可以发送数据了 while(RESET spi_flag_get(SPI_FLAG_TBE)); // 通过SPI发送一个字节 spi_data_transmit(dat); // 等待接收缓冲区非空虽然屏幕不返回有用数据但读取以完成传输 while(RESET spi_flag_get(SPI_FLAG_RBNE)); recv_data spi_data_receive(); // 读取数据清空缓冲区 LCD_CS_Set(); // 拉高CS结束本次传输 }这个函数是屏幕驱动的“发动机”所有命令和数据都通过它发送出去。硬件SPI的效率远高于模拟SPI。3.5 修正汉字显示问题关键步骤这是一个很容易踩的坑。厂家提供的字库代码可能是针对其他编译器编写的在GD32上直接使用会导致汉字显示乱码。你需要修改两个地方修改lcd.c文件 找到LCD_ShowChinese函数里面应该有一行s2;将其改为s3;。这是因为中文字符在数组中的索引步长可能不同。修改lcdfont.c文件 这个文件里定义了各种点阵字库。找到typFNT_GB12、typFNT_GB16、typFNT_GB24、typFNT_GB32这几个结构体。在每个结构体内部将char Index[2];这一行改为char Index[3];。 例如修改typFNT_GB16后应该是这样的typedef struct { char Index[3]; // 由[2]改为[3] char Msk[32]; } typFNT_GB16;注意这一步非常关键如果不改汉字显示会完全错乱。我当初就在这里调试了好久最后发现是字库索引数组长度不匹配导致的。4. 编写测试程序让屏幕动起来代码移植好了我们来写个主函数测试一下。在main.c中包含必要的头文件然后初始化屏幕并显示内容。#include gd32vw55x.h #include systick.h #include lcd_init.h #include lcd.h // 如果你有图片数据还需要包含 #include pic.h int main(void) { // 系统时钟、延时初始化 systick_config(); // LCD初始化 LCD_Init(); // 清屏测试依次显示白、红、绿、蓝、白色背景 LCD_Fill(0, 0, LCD_W, LCD_H, WHITE); delay_1ms(1000); LCD_Fill(0, 0, LCD_W, LCD_H, RED); delay_1ms(1000); LCD_Fill(0, 0, LCD_W, LCD_H, GREEN); delay_1ms(1000); LCD_Fill(0, 0, LCD_W, LCD_H, BLUE); delay_1ms(1000); LCD_Fill(0, 0, LCD_W, LCD_H, WHITE); // 最后回到白色背景 delay_1ms(1000); float t 0.0; while(1) { // 1. 显示汉字串 LCD_ShowChinese(40, 0, (const char *)中景园电子, RED, WHITE, 32, 0); // 2. 显示字符串和整数变量 LCD_ShowString(10, 33, LCD_W:, RED, WHITE, 32, 0); LCD_ShowIntNum(106, 33, LCD_W, 3, RED, WHITE, 32); // 显示屏幕宽度 LCD_ShowString(10, 66, LCD_H:, RED, WHITE, 32, 0); LCD_ShowIntNum(106, 66, LCD_H, 3, RED, WHITE, 32); // 显示屏幕高度 // 3. 显示浮点数变量会自动递增 LCD_ShowFloatNum1(10, 99, t, 4, RED, WHITE, 32); // 显示两位小数 t 0.11; // 4. 显示图片需要先准备好图片数组gImage_1 // LCD_ShowPicture(160, 95, 40, 40, gImage_1); delay_1ms(100); // 延时控制刷新速度 } }5. 常见问题与调试心得屏幕白屏或花屏首先检查电源和地线确保电压是稳定的3.3V。检查SPI时钟极性和相位。代码中配置的是SPI_CK_PL_HIGH_PH_2EDGE如果屏幕没反应可以尝试其他模式如SPI_CK_PL_LOW_PH_1EDGE具体要看ST7789V3的数据手册。检查复位时序。在LCD_Init()函数里复位信号RES拉低后需要延时几十毫秒再拉高。汉字显示乱码90%的原因是3.5节提到的字库索引数组长度没改。请务必确认lcd.c和lcdfont.c两处修改都已到位。检查字库数据本身是否正确。可以用一个简单的汉字如“中”进行测试。SPI通信失败用逻辑分析仪或示波器抓一下SCL、SDA、CS、DC的波形。看CS是否在发送数据前拉低结束后拉高看DC在发送命令时是否为低发送数据时是否为高。确认SPI分频设置SPI_PSC_4是否合适。如果主频太高可以尝试更大的分频如SPI_PSC_8、SPI_PSC_16降低SPI速度。横屏/竖屏设置 在lcd_init.h文件中通过USE_HORIZONTAL宏定义来设置显示方向#define USE_HORIZONTAL 2 // 0或1为竖屏2或3为横屏修改后需要根据方向调整LCD_W和LCD_H的定义代码中已经通过条件编译做好了。按照上面的步骤操作下来你的GD32VW553应该就能成功点亮这块1.47寸彩屏并且流畅地显示文字和图形了。这套驱动代码结构清晰后续要画点、画线、画矩形或者显示更复杂的UI都可以在lcd.c和lcd.h的基础上轻松扩展。在实际项目中我把这块屏用在了一个便携式数据显示设备上效果非常不错。如果你也遇到了类似的需求希望这篇教程能帮到你。

相关新闻

AI净界RMBG-1.4快速部署使用:Web界面操作,真正零技术门槛

AI净界RMBG-1.4快速部署使用:Web界面操作,真正零技术门槛

AI净界RMBG-1.4快速部署使用:Web界面操作,真正零技术门槛 1. 引言:从“技术恐惧”到“一键搞定” 如果你一听到“部署AI模型”、“运行代码”、“配置环境”这些词就头疼,觉得那是程序员才懂的黑话,那么这篇文章就是…

2026/7/7 15:54:15 阅读更多 →
基于Phi-3-mini-4k-instruct的Python安装包依赖分析

基于Phi-3-mini-4k-instruct的Python安装包依赖分析

基于Phi-3-mini-4k-instruct的Python安装包依赖分析 Python项目开发中,依赖管理是个让人头疼的问题。版本冲突、兼容性错误、循环依赖...这些问题经常让开发者耗费大量时间在调试环境上。传统的依赖分析工具虽然有用,但往往只能给出冷冰冰的版本信息&am…

2026/7/7 15:54:04 阅读更多 →
TranslateGemma企业级应用:本地部署神经机器翻译全流程

TranslateGemma企业级应用:本地部署神经机器翻译全流程

TranslateGemma企业级应用:本地部署神经机器翻译全流程 1. 为什么企业需要本地化神经机器翻译 想象一下这个场景:你的法务团队收到一份急需审阅的德文合同,市场部需要将最新的产品白皮书同步翻译成八种语言,研发部门则希望将日文…

2026/7/3 16:58:36 阅读更多 →

最新新闻

OpenCV 4.x 双边滤波实战:3个核心参数调优与卡通化效果量化分析

OpenCV 4.x 双边滤波实战:3个核心参数调优与卡通化效果量化分析

OpenCV 4.x 双边滤波实战:3个核心参数调优与卡通化效果量化分析当我们需要在保留图像边缘的同时去除噪声时,传统的高斯滤波往往会让整个图像变得模糊不清。这正是双边滤波(Bilateral Filter)大显身手的地方——它像一位精明的画家…

2026/7/7 15:59:41 阅读更多 →
STM32F745VG与13DOF传感器融合的嵌入式导航方案

STM32F745VG与13DOF传感器融合的嵌入式导航方案

1. 项目背景与核心价值在嵌入式系统开发领域,精确的定位与导航能力一直是工业级应用的核心需求。传统方案往往面临两个关键痛点:单一定位源(如GPS)在复杂环境下的可靠性不足,以及高精度多传感器融合方案的高成本门槛。…

2026/7/7 15:57:31 阅读更多 →
IIM-42652与dsPIC30F4013实现6DoF运动跟踪系统

IIM-42652与dsPIC30F4013实现6DoF运动跟踪系统

1. IIM-42652与dsPIC30F4013的6DoF运动跟踪系统概述 在现代嵌入式系统开发中,6自由度(6DoF)运动跟踪技术已经成为VR设备、无人机飞控和工业机器人等领域的核心技术。与传统的3D运动感知不同,6DoF系统通过整合3轴加速度计和3轴陀螺…

2026/7/7 15:55:31 阅读更多 →
IIM-42652与PIC18F26K42实现6DoF姿态检测方案

IIM-42652与PIC18F26K42实现6DoF姿态检测方案

1. 从3D到6DoF:IMU传感器的进阶应用 在运动追踪和姿态检测领域,3D空间感知已经不能满足日益增长的需求。6DoF(六自由度)技术通过增加三个旋转维度的测量,实现了对物体运动的完整描述。IIM-42652这款6轴IMU(…

2026/7/7 15:55:31 阅读更多 →
综合面试问你在海外实习的最大收获?留学生用工程闭环逻辑汇报「蒸汽求职分享」

综合面试问你在海外实习的最大收获?留学生用工程闭环逻辑汇报「蒸汽求职分享」

只要海归同学的简历里写了海外本地的实习、兼职或导师实验室项目,综合面试时面试官几乎一定会抛出这个经典问题:“在这段经历里,你觉得自己最大的收获和成长是什么?”很多同学由于缺乏对国内工业界话语体系的对齐,往往…

2026/7/7 15:53:30 阅读更多 →
5个痛点解决!MAA游戏助手如何让《明日方舟》玩家告别重复劳动

5个痛点解决!MAA游戏助手如何让《明日方舟》玩家告别重复劳动

5个痛点解决!MAA游戏助手如何让《明日方舟》玩家告别重复劳动 【免费下载链接】MaaAssistantArknights 《明日方舟》小助手,全日常一键长草!| A one-click tool for the daily tasks of Arknights, supporting all clients. 项目地址: http…

2026/7/7 15:51:29 阅读更多 →

日新闻

鸿蒙新特性:图片画廊与轮播导航——构建沉浸式图片浏览体验

鸿蒙新特性:图片画廊与轮播导航——构建沉浸式图片浏览体验

图片浏览是移动应用中最高频的场景之一。从社交应用的照片流到电商平台的商品图集,从旅游应用的景点相册到摄影作品展示——用户对图片浏览的体验要求不断提高:流畅的切换动画、直观的缩略图导航、便捷的收藏操作、自动播放模式。HarmonyOS NEXT ArkUI 虽…

2026/7/7 0:05:16 阅读更多 →
24V DC-DC降压芯片PW2312B/PW2815,SOT23-6到SOP8-EP方案对比

24V DC-DC降压芯片PW2312B/PW2815,SOT23-6到SOP8-EP方案对比

24V稳压芯片完整选型指南 PW8600 PW75XX PW2815 PW2312B LDODC/DC全方案 一、24V稳压方案概述 24V直流电源在工业自动化、门禁系统、电梯控制、汽车电子、LED驱动、监控设备等场景中应用极广,是最常见的中压直流母线电压。要将24V母线稳定降压至下游MCU、传感器…

2026/7/7 0:05:16 阅读更多 →
RAG+知识图谱混合检索与Graph RAG核心对比

RAG+知识图谱混合检索与Graph RAG核心对比

做企业RAG落地的团队,往往容易卡在一容易踩坑的选型难题: 当需求单纯靠向量RAG搞不定、单纯靠知识图谱也搞不定,必须同时依赖「文本语义理解 实体关系推理」时,到底是做「向量图谱混合检索」就够了,还是必须上「Grap…

2026/7/7 0:07:19 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/7 14:24:45 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/7 12:34:47 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/7 15:59:06 阅读更多 →

月新闻