STM32软件SPI驱动ST7735:引脚分配、初始化与刷屏优化
简介这份资源面向使用STM32F103C8T6进行嵌入式显示开发的初学者与进阶开发者提供基于HAL库、以软件SPI方式驱动1.8寸ST7735 TFT LCD彩屏的完整工程。它解决了硬件SPI资源紧张或引脚受限时如何点亮彩屏的问题涵盖GPIO模拟时钟、MISO、MOSI与NSS信号以及ST7735初始化序列、像素数据与控制命令收发等关键环节。压缩包共86个文件约4.14MB包含c与h源码、MDK-ARM工程文件、ioc配置、启动汇编、map与hex产物及说明文档目录按Src、Inc、MDK-ARM等模块组织便于直接编译与二次移植。目前已有5731人学习下载。读者可借此掌握HAL库SPI配置、软件SPI时序模拟、LCD驱动分层写法与显示刷新思路是理解SPI通信与嵌入式显示技术的实用参考。1. 当硬件 SPI 引脚被占满软件 SPI 怎么把 ST7735 点亮手上这块 STM32F103C8T6 最小系统板SPI1 的 PA5/PA6/PA7 已经被 Flash 和另一路传感器占死偏偏项目又要求加一块 1.8 寸 ST7735 TFT 彩屏做状态显示。硬件 SPI 没得用只能拿普通 GPIO 模拟时序也就是常说的软件 SPI。很多人一听软件 SPI 就摇头觉得刷屏肯定卡成幻灯片。实际测下来72MHz 主频下用软件 SPI 驱动 128×160 的 ST7735全屏刷新能压到 30ms 出头做 UI 状态面板完全够用。这篇笔记就把 HAL 库 软件 SPI ST7735 这条链路从引脚分配到驱动分层、从初始化序列到刷屏优化按我自己踩过的顺序讲一遍适合手里有 F103C8T6、屏幕是 ST7735、又不想动硬件 SPI 的嵌入式开发者照着复现。2. 软件 SPI 驱动 ST7735 的引脚分配与分层设计2.1 为什么选软件 SPI 而不是硬挤硬件 SPI先把这个决策说清楚不然后面全是白干。STM32F103C8T6 只有 SPI1 和 SPI2 两路硬件 SPISPI2 在 PB13/PB14/PB15如果你板子上这几个脚已经接了别的外设或者 PCB 已经打样改不了那硬件 SPI 就是死路。软件 SPI 的本质是用 GPIO 翻转模拟 SCK 和 MOSI牺牲 CPU 时间换引脚自由度。ST7735 的写时序对时钟极性不敏感只要求数据在 SCK 上升沿被锁存所以软件 SPI 实现起来比驱动那些对时序苛刻的 ADC 简单得多。代价也要讲明白软件 SPI 刷屏时 CPU 全程参与没法用 DMA 卸载。但 ST7735 单次写像素是 16 位128×160 全屏 20480 个像素按每次翻转加判断算 8 个指令周期72MHz 下理论极限约 18ms实际加上循环开销 30ms 左右。这个数字对状态面板、参数显示、简单波形足够但你要拿它播视频那确实不行。2.2 引脚分配表与硬件连接我一般这样分配兼顾布线和后续扩展信号ST7735 引脚STM32 引脚说明SCKSCLPA0软件 SPI 时钟推挽输出MOSISDAPA1软件 SPI 数据推挽输出CSCSPA2片选低有效DCDCPA3数据/命令选择0 命令 1 数据RESRESETPA4复位低有效BLKBLKPB0背光高电平点亮注意 RES 和 BLK 不是 SPI 信号但必须接。BLK 如果直接接 3.3V 常亮也行但接 GPIO 能省电、能做呼吸灯效果。CS 在单屏场景下可以常拉低省一个脚但保留它方便以后挂第二块屏。2.3 驱动分层把时序和业务拆开软件 SPI 最容易写成一坨所有东西塞在 main 里。我习惯分三层底层 GPIO 翻转、中间 ST7735 命令封装、上层绘图 API。这样换引脚只改底层换屏幕型号只改中间层。底层就是两个函数一个写字节一个写 16 位// 软件 SPI 写一个字节MSB 先行 static void soft_spi_write_byte(uint8_t data) { for (uint8_t i 0; i 8; i) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); // SCK 拉低 if (data 0x80) HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET); // MOSI 高 else HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET); // MOSI 低 data 1; HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET); // SCK 拉高上升沿锁存 } }逻辑说明ST7735 在 SCK 上升沿采样 MOSI所以先摆好数据再拉高 SCK。参数上唯一能调的是循环展开把 8 次循环手动展开能再快 15% 左右但代码可读性下降我一般先不展开等真卡了再优化。中间层封装命令和数据写// 写命令DC0CS 拉低 static void st7735_write_cmd(uint8_t cmd) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET); // DC0 命令 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET); // CS 拉低 soft_spi_write_byte(cmd); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET); // CS 拉高 } // 写数据DC1 static void st7735_write_data(uint8_t data) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET); // DC1 数据 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET); soft_spi_write_byte(data); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET); }这里 CS 每次写完拉高是保守做法。如果你只挂一块屏可以把 CS 常拉低省掉两次 GPIO 操作刷屏能快几个百分点。DC 的切换必须在 CS 有效之前或同时顺序反了屏幕会花。3. ST7735 初始化序列与最小刷屏验证3.1 上电复位时序不能省ST7735 对上电顺序有要求省了复位大概率白屏。我一般这样走先给 RES 拉低至少 10ms再拉高等 120ms 让内部电荷泵稳定然后才能发初始化命令。这个 120ms 是数据手册里的典型值实际我遇到过某批屏 80ms 也能起来但别赌老老实实等。static void st7735_reset(void) { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // RES 低 HAL_Delay(20); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // RES 高 HAL_Delay(120); // 等电荷泵稳定 }3.2 关键初始化命令逐条说明初始化序列网上一搜一大把但很多人直接复制粘贴不知道哪条能改哪条不能动。我挑几条必须理解的讲st7735_write_cmd(0x11); // Sleep Out退出睡眠 HAL_Delay(120); // 必须等否则后续命令不生效 st7735_write_cmd(0x3A); // 像素格式 st7735_write_data(0x05); // 0x05 16位 RGB565 st7735_write_cmd(0x36); // 内存访问控制 st7735_write_data(0xC8); // 行列交换 RGB顺序方向不对就改这里 st7735_write_cmd(0x29); // Display On0x36 这条是方向玄学重灾区。0xC8 对应横屏还是竖屏、颜色红蓝是否颠倒全看这一字节。如果你发现红色显示成蓝色把 0xC8 改成 0xC0 或 0x08 试。这个没有统一答案跟屏幕排线方向有关血泪经验是拿一个纯红矩形去试比看手册快。3.3 最小验证刷一个纯色块初始化完别急着写复杂 UI先刷个纯色确认链路通static void st7735_fill_color(uint16_t color) { st7735_set_window(0, 0, 127, 159); // 设置全屏窗口 st7735_write_cmd(0x2C); // Memory Write for (uint32_t i 0; i 128 * 160; i) { st7735_write_data(color 8); // 高字节 st7735_write_data(color 0xFF); // 低字节 } }逻辑说明0x2C 是写显存命令发完之后连续写数据就会自动填充窗口区域。参数上 color 是 RGB565比如红色 0xF800。这里每次写两个字节如果嫌慢可以合并成一个 16 位写函数少一半函数调用开销。如果刷出来是花屏先查 0x3A 是不是 0x05再查 0x36 方向字节。如果全白或全黑查背光 BLK 和复位时序。如果颜色对但位置偏查 set_window 的坐标范围ST7735 有些批次有 2 像素偏移需要加 offset。4. 刷屏速度优化与常见翻车排查4.1 把 GPIO 翻转从 HAL 换成寄存器直写HAL_GPIO_WritePin 内部有参数检查一次调用几十个周期。刷屏是高频操作换成 BSRR 寄存器直写能快一倍以上// 用 BSRR 直写PA0SCK, PA1MOSI #define SCK_H() (GPIOA-BSRR GPIO_PIN_0) #define SCK_L() (GPIOA-BRR GPIO_PIN_0) #define MOSI_H() (GPIOA-BSRR GPIO_PIN_1) #define MOSI_L() (GPIOA-BRR GPIO_PIN_1)BSRR 写 1 置位BRR 写 1 复位都是单周期指令。改完之后全屏刷新从 30ms 降到 18ms 左右。注意 BSRR 和 BRR 是 32 位寄存器写的时候别把其他位带进去用宏隔离最安全。4.2 避坑软件 SPI 驱动 ST7735 的 5 个常见问题现象一屏幕全白背光亮但无内容。原因九成是复位时序没等够或者 0x11 Sleep Out 后没等 120ms 就发后续命令。解决把复位后的延时加到 150msSleep Out 后也加 120ms宁可多等。现象二花屏有内容但像素错乱。原因通常是 0x3A 像素格式没设成 0x05或者软件 SPI 时序里 SCK 上升沿和 MOSI 建立时间冲突。解决确认 0x3A0x05然后在 MOSI 摆好数据后加一个 __NOP() 再拉高 SCK给足建立时间。现象三颜色红蓝颠倒。原因就是 0x36 的 RGB/BGR 位设反了。解决0xC8 和 0xC0 互换试或者 0x08 和 0x00 互换拿纯红纯蓝各刷一次就能定位。现象四刷屏时程序卡死或看门狗复位。原因是大循环里没喂狗或者软件 SPI 占用 CPU 太久导致其他中断堆积。解决刷屏循环里每行喂一次狗或者把刷屏拆成多次小批量中间让出 CPU。现象五显示偏移右边或下边有黑边。原因是 ST7735 不同批次显存有 offset常见是列偏移 2、行偏移 1。解决在 set_window 里加 offset 补偿比如 x 从 2 开始、y 从 1 开始具体值拿全屏填充试出来。4.3 用局部刷新代替全屏刷新状态面板通常只有几个数字在变全屏刷是浪费。我一般把屏幕分成若干矩形区域只刷变化的那块// 只刷新一个 32x16 的数字区域 void refresh_number_area(uint16_t x, uint16_t y, uint16_t color) { st7735_set_window(x, y, x 31, y 15); st7735_write_cmd(0x2C); for (uint32_t i 0; i 32 * 16; i) { st7735_write_data(color 8); st7735_write_data(color 0xFF); } }这样每次只写 512 个像素耗时不到 1msCPU 占用可以忽略。参数上区域大小按你 UI 元素定但别小于 8×8否则 set_window 的开销占比太高反而不划算。5. 把驱动封装成可复用模块的几个技巧写到能亮屏只是第一步真正省时间的是把驱动封成换块屏、换个引脚都不用重写业务代码的模块。我自己的习惯是定义一个 st7735_t 结构体把引脚端口、引脚号、屏幕宽高、偏移量全塞进去底层函数全部接收这个结构体指针。这样同一份代码改一个初始化结构体就能驱动第二块屏甚至换成 ST7789 也只需要改初始化序列和偏移参数。具体做法是底层 soft_spi_write_byte 不再写死 GPIOA而是从结构体里取端口和引脚号。代价是每次翻转多一次指针解引用实测全屏刷新会慢 2ms 左右。这个取舍看你项目如果只有一块屏写死更快如果产品线有多块屏封装带来的维护收益远大于 2ms。另一个技巧是把初始化序列做成表驱动。把命令、数据长度、数据内容、延时打包成数组初始化时遍历执行。这样换屏幕型号只改一张表不用动逻辑。表驱动唯一的坑是延时字段要留够我一般把 Sleep Out 后的延时单独拎出来硬编码不放进表里避免表里数值被误改。验证模块是否封装干净有个简单办法把引脚定义全部注释掉看编译报错是不是只集中在底层一个文件。如果是说明分层到位如果业务代码里还有 GPIOA 字样那就是漏了。这个自检习惯帮我省过很多次返工。最后说个我自己的教训早期我图快把初始化序列和刷屏逻辑全写在 main.c 里结果换块屏要改十几个地方还漏了一处导致调了一下午。后来强制自己先分层再写功能虽然开头多花二十分钟但后面每次改动都是几分钟的事。软件 SPI 驱动 ST7735 本身不难难的是别让它变成一坨改不动的代码。希望帮到你。本文还有配套的精品资源点击获取

相关新闻

Kestrel_VLLM_CUDA - 07 · 8B 阶段:模型转换与 q4 性能

Kestrel_VLLM_CUDA - 07 · 8B 阶段:模型转换与 q4 性能

07 8B 阶段:模型转换与 q4 性能 一句话:把阶段一在 2B 上打通的骨架放大到 8B 稠密模型,检验可扩展性——结论是骨架不失效,但「模型产物版本管理」第一次成了硬约束(VQF 布局标志不匹配直接拒绝加载)。 前…

2026/10/13 11:55:44 阅读更多 →
动态规划入门必刷:怪盗基德滑翔翼题解与状态设计精髓

动态规划入门必刷:怪盗基德滑翔翼题解与状态设计精髓

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 11:55:44 阅读更多 →
论文AI助手实战:RAG结合代码执行实现科研数据分析

论文AI助手实战:RAG结合代码执行实现科研数据分析

论文阅读正在成为一项越来越“重”的体力活。过去我们读一篇论文,需要自己翻图表、找数据、核对实验设置;现在虽然有大模型可以做问答,但多数助手只停留在“聊天”层面——你问它“这篇论文的核心方法是什么”,它能答;…

2026/10/13 11:55:44 阅读更多 →

最新新闻

鲲鹏云ARM架构Hadoop集群部署实验全流程拆解

鲲鹏云ARM架构Hadoop集群部署实验全流程拆解

简介:《鲲鹏云大数据实验docx》是一份面向云计算与大数据初学者的实验报告,完整记录了在华为云鲲鹏环境下从零搭建Hadoop集群的全过程。报告从购买弹性云服务器与对象存储服务开始,介绍如何获取AK/SK认证密钥,并逐步完成OpenJDK安…

2026/10/13 12:40:44 阅读更多 →
大数据实验第一课:Linux与Hadoop操作避坑指南

大数据实验第一课:Linux与Hadoop操作避坑指南

简介:本资源是大数据系列实验的第一份配套材料,面向刚接触大数据技术的高校学生与自学者,帮助其搭建后续实验所需的基础环境。内容围绕Linux虚拟机安装、常用Linux命令以及Hadoop伪分布式安装三大模块展开,覆盖cd、ls、mkdir、cp、…

2026/10/13 12:40:44 阅读更多 →
STM32双机CAN通信实战:TJA1050硬件设计到软件调试全解析

STM32双机CAN通信实战:TJA1050硬件设计到软件调试全解析

1. 为什么双机通信我选了CAN而不是UART——场景选择与总体方案先说一个最常见的场景:你在做一个小项目,A板和B板之间要互通数据,距离可能有个十来米,现场还有电机、变频器这类干扰源。多数人第一反应是UART,一对TX/RX接…

2026/10/13 12:40:44 阅读更多 →
数据库技术选型决策记录(ADR)实战:关系型、文档型与事件型数据库的完整评估与决策

数据库技术选型决策记录(ADR)实战:关系型、文档型与事件型数据库的完整评估与决策

【免费下载链接】architecture-decision-record Architecture decision record (ADR) examples for software planning, IT leadership, and template documentation 项目地址: https://gitcode.com/gh_mirrors/ar/architecture-decision-record 点击查看 免费下载 …

2026/10/13 12:40:44 阅读更多 →
8款硬核MCP服务器实战:让AI告别复制粘贴

8款硬核MCP服务器实战:让AI告别复制粘贴

我先从一个特别没面子但特别真实的场景说起。 上周我要做一份跨项目的数据汇总报告,具体流程是这样的:先从A系统的后台导出两个月的订单记录,再从B系统拉出成本表,打开电子表格软件把两边的格式统一,然后把关键数字一…

2026/10/13 12:40:44 阅读更多 →
Natron 中 G‘MIC Layers to Tiles 节点完全指南:多图层图像拆分为网格瓦片

Natron 中 G‘MIC Layers to Tiles 节点完全指南:多图层图像拆分为网格瓦片

音视频视频处理图形学桌面应用 【免费下载链接】Natron Open-source video compositing software. Node-graph based. Similar in functionalities to Adobe After Effects and Nuke by The Foundry. 项目地址: https://gitcode.com/gh_mirrors/na/Natron 点击查看 …

2026/10/13 12:39:44 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 21:05:09 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 14:48:49 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →