尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
STM32F103RCT6驱动1.44寸TFT屏:从点灯到UI底板实战
简介这份资源面向嵌入式初学者与需要快速验证显示方案的开发者围绕STM32F103RCT6驱动1.44英寸128×128彩色TFT屏展开解决从引脚定义、SPI初始化到屏幕刷新这一完整链路的落地问题。压缩包共86个文件、约289KB以38个h头文件与32个c源文件为主体涵盖LCD驱动、GUI绘制、字库与图片数据、延时与LED等模块另含4个s启动文件、Keil工程文件、hex固件及readme说明工程结构完整可直接编译参考。目前已有4053人学习下载说明该方案在同类屏幕调试中具有较高参考价值。读者可从中获得SPI通信配置、DC/RST/BL控制线处理、初始化序列与显存缓冲刷新等关键实现思路并借助现成工程对照排查花屏、无显示等常见问题适合作为小型仪表盘、迷你显示屏等图形界面项目的起步模板。1. 一块 1.44 寸屏点亮之后我才敢说这颗 MCU 入门了很多人第一次碰 STM32F103RCT6都是从点灯开始的灯亮那一刻挺爽但真正让人心里有底的是把一块 1.44 寸 TFT 屏点亮、刷出第一行字。这个项目干的就是这件事用 STM32F103RCT6 驱动 1.44 寸 TFT 液晶屏完成初始化、清屏、画点画线、显示字符和简单图形。它不花哨却是嵌入式入门最扎实的一块试金石——SPI 时序、GPIO 配置、显存管理、字模取模全在这一块小屏上过一遍。适合刚上手 STM32、想搞懂屏幕驱动链路的人也适合拿它当 UI 底板做二次开发的老手。下面我按自己拆项目的顺序把这块屏从硬件接线到代码改造讲透。2. 硬件与工程结构先看清这块屏和这颗 MCU 怎么搭2.1 为什么选 STM32F103RCT6 配 1.44 寸 TFTSTM32F103RCT6 是 Cortex-M3 内核主频 72MHz256KB Flash、48KB SRAMLQFP64 封装GPIO 数量对驱动一块小屏绰绰有余。1.44 寸 TFT 常见分辨率是 128×128驱动芯片多为 ST7735 系列走 SPI 接口只需要 SCK、MOSI、CS、DC、RESET 几根线接线简单、占用引脚少非常适合入门和中小型项目。选这套组合的现实原因是SPI 刷 128×128 的屏72MHz 主频下全屏刷新在几十毫秒量级做菜单、仪表盘、简单动画都够用而 F103RCT6 的 SRAM 有 48KB开一块 128×128×2 字节的显存缓冲约 32KB也放得下这点很关键——有显存缓冲画图才不会闪。常见做法是把屏幕挂在 SPI1 上用软件控制 CS 和 DC复位脚单独接一个 GPIO。下面这张表是我一般会先确认的接线关系屏幕引脚接到 MCU作用VCC / GND3.3V / GND供电注意别接 5VSCL(SCK)PA5SPI 时钟SDA(MOSI)PA7SPI 数据CSPA4片选低有效DCPA3数据/命令选择RESPA2硬件复位BLK3.3V 或 GPIO背光控制提示不同厂家的 1.44 寸模块引脚命名不统一有的把 DC 写成 A0有的把 MOSI 写成 SDA接线前一定对照模块丝印别照抄网上图。2.2 工程目录怎么分层这类项目我一般不会把所有代码堆在 main.c 里而是按「硬件抽象—驱动—应用」三层拆开后面换屏、换 MCU 都好改。典型目录结构如下Project/ ├── Core/ │ ├── Inc/ │ │ ├── main.h │ │ ├── stm32f1xx_hal_conf.h │ │ └── lcd_st7735.h // 屏幕驱动对外接口 │ └── Src/ │ ├── main.c // 应用入口 │ ├── stm32f1xx_it.c │ ├── lcd_st7735.c // 屏幕底层驱动 │ ├── lcd_font.c // 字模数据 │ └── spi.c / gpio.c // 外设初始化 ├── Drivers/ │ └── STM32F1xx_HAL_Driver/ // HAL 库 └── MDK-ARM/ 或 STM32CubeIDE/ // 工程文件分层的好处很直接lcd_st7735.c只关心「怎么把命令和数据发出去」main.c只关心「显示什么」。哪天把 ST7735 换成 ST7789只动驱动层应用层几乎不用改。这也是我后面讲二次开发时反复强调的一点。2.3 时钟与 SPI 初始化SPI 的速率直接决定刷屏快慢。F103 的 SPI1 挂在 APB2 上72MHz分频系数选 2 就是 36MHz但 ST7735 手册一般标称写周期最快 66ns 左右实际跑 18MHz 更稳。我一般先用 4 分频18MHz跑通再往上试。// spi.c 片段SPI1 初始化主机模式8 位数据 void MX_SPI1_Init(void) { hspi1.Instance SPI1; hspi1.Init.Mode SPI_MODE_MASTER; // 主机模式 hspi1.Init.Direction SPI_DIRECTION_2LINES;// 全双工 hspi1.Init.DataSize SPI_DATASIZE_8BIT; // 8 位 hspi1.Init.CLKPolarity SPI_POLARITY_LOW; // 空闲低电平 hspi1.Init.CLKPhase SPI_PHASE_1EDGE; // 第一个边沿采样 hspi1.Init.NSS SPI_NSS_SOFT; // 软件片选 hspi1.Init.BaudRatePrescaler SPI_BAUDRATEPRESCALER_4; // 18MHz hspi1.Init.FirstBit SPI_FIRSTBIT_MSB; // 高位先发 HAL_SPI_Init(hspi1); }参数说明CLKPolarity和CLKPhase合起来决定 SPI 模式ST7735 通常用模式 0CPOL0、CPHA0也就是空闲低、第一个边沿采样NSS设成软件是因为片选要由驱动代码在发命令和发数据之间手动拉低拉高FirstBit必须是 MSB屏幕驱动芯片按高位在前解析。这几项配错屏幕要么全白要么花屏是新手最常见的翻车点。3. 驱动核心拆解一条命令从 MCU 到屏幕像素3.1 命令与数据的分流DC 引脚才是关键SPI 本身只负责搬字节屏幕怎么知道这一字节是命令还是数据靠 DC 引脚。DC 拉低表示接下来发的是命令寄存器地址拉高表示发的是数据参数或像素。所以驱动层最核心的就是两个函数写命令、写数据。// lcd_st7735.c底层写命令/写数据 static void LCD_WriteCmd(uint8_t cmd) { LCD_DC_LOW(); // DC0命令模式 LCD_CS_LOW(); // 片选拉低 HAL_SPI_Transmit(hspi1, cmd, 1, 100); LCD_CS_HIGH(); } static void LCD_WriteData(uint8_t data) { LCD_DC_HIGH(); // DC1数据模式 LCD_CS_LOW(); HAL_SPI_Transmit(hspi1, data, 1, 100); LCD_CS_HIGH(); }逻辑说明每次传输前先设好 DC再拉低 CS发完立刻拉高 CS。有人图省事把 CS 一直拉低单设备时确实能跑但一旦总线上还有别的 SPI 器件就会互相干扰。HAL_SPI_Transmit的超时参数给 100ms 足够实际单字节传输微秒级。批量发像素时不要一个字节调一次要拼成缓冲一次发否则刷屏慢得肉眼可见。3.2 初始化序列照着手册一条条喂ST7735 上电后必须按手册的初始化序列配置顺序错了屏幕不亮或颜色异常。核心几条是软件复位、退出睡眠、设置像素格式为 16 位 RGB565、设置显示窗口、打开显示。void LCD_Init(void) { LCD_RES_LOW(); HAL_Delay(20); LCD_RES_HIGH(); HAL_Delay(120); // 硬件复位等内部稳定 LCD_WriteCmd(0x01); HAL_Delay(120); // SWRESET 软件复位 LCD_WriteCmd(0x11); HAL_Delay(120); // SLPOUT 退出睡眠 LCD_WriteCmd(0x3A); // COLMOD 像素格式 LCD_WriteData(0x05); // 16 位/像素 RGB565 LCD_WriteCmd(0x36); // MADCTL 扫描方向 LCD_WriteData(0x00); // 根据屏幕朝向调整 LCD_WriteCmd(0x21); // INVON 反显部分屏需要 LCD_WriteCmd(0x29); // DISPON 开显示 LCD_Fill(0x0000); // 清屏为黑 }参数说明0x3A的参数据0x05表示 16 位色这是 RGB565 的标准配置0x36控制行列扫描方向和 RGB/BGR 顺序屏幕显示镜像、颜色红蓝颠倒基本都是这一条参数不对改0x00/0x60/0xA0/0xC0几个值试0x21反显命令不是所有批次都需要如果发现颜色整体反了加或去掉它。初始化里每个延时都不能省尤其是复位后那 120ms省了就是玄学不亮。3.3 设置显示窗口与刷像素要在指定区域画图先发0x2A列地址和0x2B行地址设定窗口再发0x2C开始写显存之后连续发的数据就按窗口顺序填进去。void LCD_SetWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) { LCD_WriteCmd(0x2A); // 列地址设置 LCD_WriteData(x0 8); LCD_WriteData(x0 0xFF); LCD_WriteData(x1 8); LCD_WriteData(x1 0xFF); LCD_WriteCmd(0x2B); // 行地址设置 LCD_WriteData(y0 8); LCD_WriteData(y0 0xFF); LCD_WriteData(y1 8); LCD_WriteData(y1 0xFF); LCD_WriteCmd(0x2C); // 开始写显存 } void LCD_Fill(uint16_t color) { LCD_SetWindow(0, 0, 127, 127); LCD_DC_HIGH(); LCD_CS_LOW(); for (uint32_t i 0; i 128 * 128; i) { uint8_t buf[2] { color 8, color 0xFF }; // RGB565 高字节在前 HAL_SPI_Transmit(hspi1, buf, 2, 100); } LCD_CS_HIGH(); }逻辑说明地址是 16 位拆成高低字节发颜色是 RGB565两个字节高字节在前。上面这个LCD_Fill是能跑但不够快的写法逐像素调HAL_SPI_Transmit开销大。优化思路是开一块行缓冲一次发一整行或者直接用 DMA。128×128 全屏 16384 个像素优化后刷新能压到十几毫秒。3.4 字符显示字模从哪来显示字符本质是把字模点阵按位展开成像素。常用 8×16 或 16×16 字模用取模软件生成 C 数组。显示时逐行判断每一位为 1 画前景色为 0 画背景色。// 显示一个 8x16 ASCII 字符 void LCD_ShowChar(uint16_t x, uint16_t y, char ch, uint16_t fc, uint16_t bc) { const uint8_t *p font8x16[(ch - ) * 16]; // 每个字符 16 字节 LCD_SetWindow(x, y, x 7, y 15); LCD_DC_HIGH(); LCD_CS_LOW(); for (uint8_t row 0; row 16; row) { uint8_t bits p[row]; for (uint8_t col 0; col 8; col) { uint16_t c (bits (0x80 col)) ? fc : bc; uint8_t buf[2] { c 8, c 0xFF }; HAL_SPI_Transmit(hspi1, buf, 2, 100); } } LCD_CS_HIGH(); }参数说明font8x16是字模数组按 ASCII 从空格开始排列每个字符 16 字节、每字节一行 8 位0x80 col是从左到右取位取模软件设置成「阴码、逐行、高位在前」才能对上。字模方向搞反显示出来就是镜像或乱码这是取模配置和代码不匹配的典型问题。4. 跑起来与避坑从编译到点亮的那几道坎4.1 编译下载与首次点亮流程工程用 Keil MDK 或 STM32CubeIDE 都能开HAL 库版本要和工程里stm32f1xx_hal_conf.h对得上。流程是确认时钟树配到 72MHz、SPI1 和 GPIO 初始化被调用、LCD_Init()在main里while(1)之前执行、下载后按复位。第一次点亮建议先只做「清屏为红」能整屏变红说明 SPI 通路、初始化序列、DC/CS 控制全对再往上加字符和图形逐层验证比一上来全功能好排查得多。4.2 常见问题排查白屏、花屏、颜色反现象一上电全白什么都不显示。原因通常是初始化没跑完或背光/复位没处理好。先量 RES 脚有没有复位脉冲再看LCD_Init是否真的被调用有的模块 BLK 不接就不亮把背光脚接 3.3V 试。还有一种情况是 SPI 模式配错CPOL/CPHA 不对命令根本没被识别。现象二花屏、雪花点。多半是 SPI 速率太高或接线过长。把分频从 2 改到 4 甚至 8 试杜邦线尽量短另外检查LCD_SetWindow的行列范围有没有越界越界写显存会串到别的区域。现象三颜色红蓝颠倒。这是 RGB/BGR 顺序问题改0x36MADCTL参数里的 RGB 位或者初始化时加/去0x21反显命令。别急着改代码逻辑先在这两个寄存器上找。现象四显示镜像或旋转 90 度不对。还是0x36的扫描方向位四个方向对应不同参数值配合LCD_SetWindow的坐标映射一起调改完记得同步改画点函数的坐标换算。现象五刷屏慢、有撕裂感。逐字节HAL_SPI_Transmit是主因改成行缓冲批量发或 DMA如果开了显存缓冲注意先写缓冲再整块刷别边算边刷。注意屏幕供电一定确认是 3.3V部分模块标 5V 兼容但逻辑电平仍是 3.3V直接接 5V 数据线长期会伤 IO。5. 二次开发把这块屏改成你自己的 UI 底板5.1 加显存缓冲消灭闪烁直接写屏最大的问题是画图过程中屏幕可见地闪。改造思路是开一块uint16_t frame[128*128]32KBF103RCT6 的 48KB SRAM 放得下所有画点、画线、画字符先写进内存最后一次性LCD_Flush()推给屏幕。static uint16_t frame[128 * 128]; void LCD_DrawPixelBuf(uint16_t x, uint16_t y, uint16_t color) { if (x 128 y 128) frame[y * 128 x] color; // 先写缓冲 } void LCD_Flush(void) { LCD_SetWindow(0, 0, 127, 127); LCD_DC_HIGH(); LCD_CS_LOW(); HAL_SPI_Transmit(hspi1, (uint8_t *)frame, sizeof(frame), 1000); // 整块推 LCD_CS_HIGH(); }这样刷屏从「逐像素发」变成「一次 DMA 级传输」配合 DMA 还能在传输时继续算下一帧。注意frame是 16 位数组传给HAL_SPI_Transmit要强转成uint8_t*长度是字节数不是元素数这里写错就是只刷半屏。5.2 封装图形接口方便换屏换 MCU把画点、画线、画矩形、画圆、显示字符串统一成一组接口底层实现藏在驱动里。换 ST7789 时只改LCD_WriteCmd/Data和初始化序列上层 UI 代码一行不动。我一般会定义一个lcd_ops结构体放函数指针或者干脆用同名函数加条件编译小项目后者更省事。5.3 验证改造是否成功改完别只看「能显示」要验证三件事全屏填充耗时用定时器打点优化后应在 20ms 内、连续刷新 100 帧有没有撕裂、旋转方向切换后坐标是否仍然正确。我习惯在main里写一个自检函数依次刷红绿蓝白黑五色各 200ms再画一个边框和十字线肉眼一遍就能确认颜色、方向、边界都对。5.4 一个具体技巧字模按需裁剪全 ASCII 8×16 字模约 1.5KB不算大但如果只显示数字和少量字母可以只保留用到的字符把字模表压到几百字节给 SRAM 紧张的场合腾空间。做法是建一个字符到索引的映射表取模时只导出需要的字符代码里查表偏移。这个技巧在 F103 这种 SRAM 有限的片子上很实用。血泪经验是每次改完初始化序列或0x36参数我一定先跑一遍五色自检再往下写业务代码不然等 UI 堆上去再回头查颜色问题成本翻几倍。希望这块 1.44 寸屏也能成为你 STM32 路上第一块真正点亮的屏。本文还有配套的精品资源点击获取
RELATED

相关推荐

电调MK V0.41固件:BLDC六步换相与反电动势过零检测实战

电调MK V0.41固件:BLDC六步换相与反电动势过零检测实战

简介:电调MK V0.41代码面向无人机、遥控飞机等无刷电机控制的学习者与嵌入式开发者,聚焦无感无刷电调的设计与实现。资源围绕反电动势检测的无传感器控制、PWM调速、数字滤波与平滑、过流过热短路保护、PID驱动算法及PPM信号解码等关键环节展开&#xff…

📅 2026/10/26 2:49:11
高次方程求解与多项式表达式计算技巧

高次方程求解与多项式表达式计算技巧

1. 方程求解的基本思路面对"x⁵ x 1 0, x - x ?"这样的复合数学问题,我们需要分步骤解决。首先需要理解题目结构:这是一个由两个方程组成的复合问题,第一个方程是五次方程,第二个是三次方程的表达式求值问题。1.1 …

📅 2026/10/26 2:49:11
Oracle数据库版本演进与核心技术解析

Oracle数据库版本演进与核心技术解析

1. Oracle数据库发展历程全景图Oracle数据库作为关系型数据库的标杆产品,其40余年的版本迭代史堪称一部数据库技术进化史。1979年推出的Oracle V2首次实现了SQL语言支持,这个用汇编语言编写的版本已经展现出"数据一致性"的核心设计理念。真正奠…

📅 2026/10/26 2:49:11
MORE NEWS

更多资讯

📰

从完美主义到无可挑剔:一套可复制的高质量行动法

1. 从“完美主义”到“无可挑剔”:重新理解这个词我第一次认真琢磨“impeccable”这个词,不是因为词典,而是因为收到过一封邮件。那封邮件不长,但措辞、排版、附件命名、签名档甚至发送时间,都让人觉得发件人极其靠谱。…

📰

ADS8688+STM32F407+RT-Thread高精度模拟量采集系统实战

简介:本资源是一套基于STM32F407主控、ADS8688高精度ADC与RT-Thread实时操作系统的完整嵌入式驱动工程,面向嵌入式开发初学者及RTOS进阶实践者,解决高精度模拟信号采集在实时系统中稳定驱动与数据处理的典型难题,适用于工业传感、…

📰

代码质量量化落地:三层机制让“完美”不再只是口号

我一直觉得,软件团队里最容易被误解的一个词就是“完美”。很多人一听“完美代码”,第一反应是“这不可能”“这是洁癖”,或者“我们要的是能上线,不是搞艺术”。但几年前我在一个模拟项目里认真地追了一次“完美”,项…

📰

SXSSFWorkbook分页查询实现百万行Excel流式导出

一次导出请求把服务拖垮,事后排查下来,数据库不慢、网络不抖,问题出在几百兆的单元格对象全堆在堆内存里。SXSSFWorkbook 实现分页查询导出这个组合,就是专门解决这类场景的:流式写出把内存中的行数压到固定窗口&#…

📰

对话模型记忆增强实战:claude-mem架构解析

很多人在使用 Claude 这类对话模型时都遇到过同一个尴尬:上午刚聊完的方案细节,下午换个话题再切回来,它已经完全不记得了。如果只是临时问答倒也还好,可一旦你希望它持续跟进一个项目、记住你的写作偏好、或者跨多轮会话维护一份…

📰

AI编程中的规则约束:提升代码质量与工程效能

1. AI编程时代的规则约束革命当代码补全工具开始接管我们的IDE时,一个被忽视的真相正在浮现:真正决定AI编程质量的不是算法本身,而是我们为它设定的规则边界。最近三个月,我的团队在Vibe-Coding工作流中系统性地引入了Rules约束机…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬