尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

ST7735 1.44寸TFT液晶屏驱动实战:从原理图到三平台移植与排障

ST7735 1.44寸TFT液晶屏驱动实战:从原理图到三平台移植与排障 简介1.44寸LCD串口模块ST7735的软硬件全套资料覆盖C51、STM32、Arduino三大嵌入式平台适合正在调试同型号屏幕或准备做小尺寸显示项目的开发者。压缩包为RAR格式约18.05MB内含模块原理图与尺寸图、Altium封装库、芯片PDF以及多平台SPI驱动源码和图片/文字取模软件硬件设计、代码移植、界面制作所需内容基本齐全。目前已有219人学习/下载属于同类资源中较为实用的参考包。尤其值得关注的是其中STM32硬件SPI中英文显示测试源码可以直接借鉴接线说明和测试代码能帮读者快速跑通基础显示功能对于从零开始接触ST7735驱动的朋友也能借助这些资料少走弯路较快完成项目验证。1. 1.44寸ST7735串口屏从原理图到三平台驱动的完整落地方案1.44寸、128x160、ST7735驱动的TFT-LCD串口屏几乎是嵌入式开发板资料里出现频率最高的一块小屏。它的控制引脚极简SPI就够、自带GRAM、颜色还原尚可所以从C51到STM32到Arduino谁的开发套件都要配一块。但在实际项目中很多人是拿到厂家资料包就开始烧例程真正遇到换主控、改引脚、调亮度、加中文时才开始对着原理图和驱动源码逐行抠。这篇博文把这块屏作为一组硬件加固件的组合来回看原理图哪些器件不能省SPI速率和指令时序怎么配C51/STM32/Arduino三套主流驱动各自的最小可行代码长什么样以及卡屏、花屏、闪屏时从哪里下手。2. ST7735的硬件底子接口协议、原理图关键位与封装库选型2.1 为什么是ST7735同尺寸LCD控制器的选型对比ST7735是一颗单芯片TFT LCD控制器最大支持132x162像素内部带有GRAM和电源电路只需要一颗3.3V电源、四线SPI和几个控制引脚就能驱动。它和常见的SSD1306、ILI9341、ILI9488定位不同SSD1306是OLED单色/双色屏分辨率通常是128x64胜在自发光和超低功耗但颜色信息完全没有ILI9341是2.4寸以上真彩屏的常客分辨率240x320适合做仪表或简单的GUIILI9488则是480x320真彩屏色彩深度高但需要更多的GRAM和更快的总线。ST7735卡在两者之间128x160、16位色刚好能显示一块带点信息的彩色画面但数据量又不会大到让8位单片机太吃力。从选型逻辑上看ST7735适合的是「以彩色显示为目标但不追求复杂UI」的项目。如果你的面板只显示几行传感器数据、一个简单曲线或者状态图标用ST7735是最省事的一旦要跑滑屏动画、多级菜单甚至显示图片就要评估帧率能不能接受。一个很容易被忽略的参数是接口速度ST7735支持SPI mode 0和mode 3最大串行时钟因厂家批次而异常见模块标注为15MHz~20MHz实际跑8MHz以上就能有不错的效果。选择模块时优先看厂家是否标出RAM型号和玻璃批次同一颗芯片在不同玻璃上会有色差和响应速度差异。2.1.1 接口协议SPI还是并口标题里说「串口模块」但串口这个词在ST7735语境下容易产生歧义。这里指的并不是UART串口而是SPI串行接口——模块上的数据线是SCLK、MOSI模块上常标为SDA、CS、DC模块上常标A0或RS、RST、BLK。完整的驱动只需要5根信号线加电源地算上背光控制也不超过8根线。有些1.44寸模块的「40pin LCD接口」是玻璃端子的FPC引出主板上通过一个转接小板把FPC转换成8pin或10pin排针收到货先确认排针定义因为不同批次模块的引脚顺序并不完全一致。从性能上讲ST7735内部数据总线是并行的但外部接口支持串行使用SPI时每次写GRAM都要经过移位寄存器所以同一颗屏在并口下的刷新速度会比SPI下快很多。模块厂之所以普遍做成SPI是因为布线简单、引脚少适合DIY和原型验证。如果你的产品最终方案确定用STM32也可以反过来看模块是否支持并口模式——ST7735有IM0~IM3引脚决定接口模式但1.44寸模块通常已经把模式固定为SPI想改并口需要飞线甚至放弃模块成品。2.2 模块原理图里的三个关键区域电源、背光、SPI信号拿到原理图先看电源部分。ST7735的电源分为模拟电源VCI、逻辑电源IOVCC和LCD驱动电源由内部charge pump产生。在1.44寸模块上厂家通常已经把VCI和IOVCC合并成一颗3.3V LDO供电你只需要从主控板上引3.3V过来。但有一个坑很多模块上的VCC引脚对电压纹波很敏感特别是背光突然点亮时如果电容容量不足就会出现水波纹或红绿横纹。原理图里VCC附近那两个10uF100nF电容不能省都贴上去再实测。背光控制是第二个关键位。模块上BLK引脚接入背光LED回路常见设计是通过一个三极管或MOS管开关控制串联电阻决定背光电流。直接接3.3V时背光最亮但电流可能达到20~40mA如果主控板的LDO余量不够会影响ST7735的模拟电压。更常见的做法是把BLK接到主控的一个PWM脚用一个10k电阻做下拉通过调节PWM占空比控制亮度。注意有些模块的BLK引脚内部已经带了限流电阻TFT_eSPI库用户可以在初始化后直接调digitalWrite看屏的亮度变化来确定模块属于哪种背光电路。SPI信号线上需要关注的不是上拉而是电平匹配和信号完整性。C51/STM32的GPIO都是3.3V逻辑Arduino Uno的5V输出建议串一个几百欧的电阻分压或者直接接电平转换后再进模块。SPI走线超过10cm时时钟和数据线之间的相位偏移会让画面出现整屏错位或第一行显示异常解决办法是把SPI时钟降到4MHz以下或者把CS和DC也纳入等长布线考虑。2.3 封装库与PCB布局从模块到自己的板子如果你不是直接把模块飞线到开发板上而是想在自有PCB上贴装1.44寸屏封装库的选取就变得重要。模块常见两种封装一种是大板排针焊盘间距2.54mm适合原型另一种是邮票孔或Wi-Fi模块式焊盘适合SMT量产。很多模块厂家在资料包中附带Altium/AD的封装库但导出后经常会遇到原点不一致、丝印超出板框的问题。我一般会新建一个原理图器件把引脚名按模块实际排针顺序命名再配一个独立的PCB封装这样画板时不易被厂家库的怪异原点带偏。布局方面的经验值这个屏的FPC排线区域不要走其他大电流线ST7735的电源去耦电容应尽量靠近模块电源引脚如果板上同时有Wi-Fi模块或电机驱动LCD的GND要单独一条线回到电源地避免电机启停的电流噪声窜进SPI信号回路。屏幕背面的金属框如果接地良好还能起到屏蔽作用减少触摸或无线信号的干扰。3. C51驱动ST7735的软件SPI实现最小寄存器级代码C51单片机的处理能力和存储空间都有限尤其经典STC89C52只有8KB程序Flash跑不了Arduino那种重量级图形库。所以C51驱动的正确姿势是自己写寄存器级SPI只实现画点、画矩形和显示ASCII字符。这一章给出可以完整编译的一套最小驱动芯片以STC89C52RC为例晶振12MHz。3.1 引脚分配与软件SPI的实现思路STC89C52本身不带硬件SPISTC12和STC15系列才有所以用普通GPIO模拟。建议把SCLK、MOSI、CS、DC、RST分到同一组端口方便赋值和宏替换。下面这张引脚表是常用接法你也可以按自己的板子调整只要在驱动头文件里对应修改即可。引脚功能51单片机引脚说明SCLKP1.0SPI时钟空闲低电平MOSI(SDA)P1.1主出从进数据在上升沿有效CSP1.2片选低电平时选中ST7735DC(A0)P1.3低电平写命令高电平写数据RSTP1.4复位低电平有效BLKP1.5背光控制直接输出高电平点亮软件SPI的核心是字节发送函数。ST7735支持SPI mode 0和mode 3C51软件模拟时建议固定在mode 0空闲时SCLK为低数据在SCLK上升沿被采样。// spi_delay() 由空循环实现视晶振频率微调 void SPI_WriteByte(unsigned char dat) { unsigned char i; for (i 0; i 8; i) { if (dat 0x80) MOSI 1; // 先送最高位 else MOSI 0; SCLK 0; // 空闲电平为低 dat 1; // 移位准备下一位 SCLK 1; // 上升沿锁存数据 } }这段代码的要点是每次把数据最高位移出在SCLK上升沿时让ST7735采样。注意循环里先写MOSI再拉高SCLK是为了满足建立时间要求如果你的单片机速度太快SPI_WriteByte里没延时也会工作但信号线长或模块负载重时容易出现偶发错位这时在SCLK1后面加两个空操作即可。3.2 初始化序列ST7735的寄存器配置与其中含义ST7735上电后必须发送一串初始化命令否则屏不会正常显示。不同厂家封装的ST7735S序列大同小异下面是一段经过多块屏验证的常用初始化代码包含软件复位、退出睡眠、颜色格式和显存窗口设置。void LCD_Init(void) { RST 0; DelayMs(50); // 复位保持时间至少10us实际放宽 RST 1; DelayMs(120); // 退出复位需要等待内部PLL稳定 WriteCmd(0x01); // SWRESET 软件复位 DelayMs(150); WriteCmd(0x11); // SLPOUT 退出睡眠模式 DelayMs(120); WriteCmd(0x36); // MADCTL 设置扫描方向 WriteData(0xA0); // RGB顺序正常扫描根据面板丝印调整 WriteCmd(0x3A); // COLMOD 颜色格式 WriteData(0x05); // 16位/pixel5-6-5格式 WriteCmd(0x20); // INVOFF 关闭反色显示 WriteCmd(0x2A); // CASET 设置列地址窗口 WriteData(0x00); WriteData(0x00); WriteData(0x00); WriteData(0x7F); WriteCmd(0x2B); // RASET 设置行地址窗口 WriteData(0x00); WriteData(0x00); WriteData(0x00); WriteData(0x9F); WriteCmd(0x29); // DISPON 打开显示 DelayMs(20); }这里WriteCmd和WriteData的区别在于DC引脚的电平状态写命令时DC0写数据时DC1。0x36的MADCTL参数A0表示RGB色彩顺序加上从左到右、从上到下的扫描方向但不同批次的1.44寸屏可能在玻璃装配时旋转了180度画面上下颠倒时把这个值改为0xA0或0x70做对比即可。0x3A设成0x05是16位色这是代码里最统一的一个寄存器设置不要改成0x06否则后续颜色数据的字节序全部会错。3.3 画点、矩形与字符显示在8KB Flash里塞进可用UI初始化完成后最基础的原语是画点函数。ST7735的GRAM寻址方式是先设列地址窗口CASET再设行地址窗口RASET最后连续写入像素数据。每发送一个像素就是两个字节低字节在前高字节在后具体取决于MADCTL的RGB/BGR设置。void LCD_DrawPoint(unsigned int x, unsigned int y, unsigned int color) { WriteCmd(0x2A); // 列地址 WriteData(x 8); WriteData(x 0xFF); WriteData(x 8); WriteData(x 0xFF); WriteCmd(0x2B); // 行地址 WriteData(y 8); WriteData(y 0xFF); WriteData(y 8); WriteData(y 0xFF); WriteCmd(0x2C); // RAMWR 写显存 WriteData(color 8); WriteData(color 0xFF); }如果在循环里逐个像素调用LCD_DrawPoint刷一整屏耗时非常长128x160个像素每个像素要发两次SPI字节12MHz晶振下软件SPI刷一帧在秒级。所以实际项目都会在字符和图片显示时采用整块填充的方式先用CASET和RASET框住一个区域然后连续发送该区域全部像素最后再拉高DC并写命令结束。常见做法是做一个LCD_FillRect函数调用点画区域设置后用for循环直接把颜色数据发完中间不切换DC这样ST7735会自动把GRAM地址1直到填满窗口。ASCII字符显示基于一张8x16或8x8的点阵表在C51上更常用的是8x8小字库。把所有ASCII字符的8字节模板放在code区显示时按字符编码索引到起始偏移逐列取出数据每个bit作为像素的上色开关。中文字体在C51上比较吃力一则字模数据大二则GB2312编码处理复杂如果一定要显示中文建议只放需要的那十几个字的16x16字模用编码查表而不是整个字库全塞进去。4. STM32硬件SPI与Arduino库移植性能提升和快速出效果C51这种8位平台只能解决「点亮」问题到了STM32或Arduino平台上驱动方式就从寄存器模拟转向硬件SPI和现成库。STM32的硬件SPI可以跑16MHz或更高DMA又能把CPU从枯燥的像素搬运中解放出来Arduino则用Adafruit_ST7735或TFT_eSPI把底层细节封装掉几分钟就能看到画面。这一章把两条路都走一遍。4.1 STM32硬件SPI配置SPI_CR1和DMA搬运显存数据在STM32上驱动ST7735首选硬件SPI。以STM32F103C8T6为例SPI1的SCLK和MOSI复用映射到PA5/PA7CS、DC、RST用普通GPIO控制。初始化代码的特点是SPI模式选Master、时钟空闲低电平、第一个跳变沿采样对应CPOL0、CPHA08位数据长度MSB先发。void SPI1_Init(void) { GPIO_InitTypeDef gpio; SPI_InitTypeDef spi; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE); gpio.GPIO_Pin GPIO_Pin_5 | GPIO_Pin_7; // SCK与MOSIMISO不用 gpio.GPIO_Mode GPIO_Mode_AF_PP; gpio.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, gpio); gpio.GPIO_Pin GPIO_Pin_3; // DC复用为GPIO输出 gpio.GPIO_Mode GPIO_Mode_Out_PP; GPIO_Init(GPIOA, gpio); SPI_InitStructure.SPI_Direction SPI_Direction_1Line_Tx; SPI_InitStructure.SPI_Mode SPI_Mode_Master; SPI_InitStructure.SPI_DataSize SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL SPI_CPOL_Low; SPI_InitStructure.SPI_CPHA SPI_CPHA_1Edge; SPI_InitStructure.SPI_NSS SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler SPI_BaudRatePrescaler_2; SPI_InitStructure.SPI_FirstBit SPI_FirstBit_MSB; SPI_Init(SPI1, spi); SPI_Cmd(SPI1, ENABLE); }把APB1/APB2时钟算出实际SPI时钟后你会发现预分频2得到的是18MHz或36MHz这个值已经超过不少1.44寸模块标称的15MHz上限。所以实际项目里SPI_BaudRatePrescaler_4更稳妥得到9MHz左右。这里要特别提醒不要一上来就追求最大速度先用低速调通显示再逐步提升分频值验证画面是否出现白噪点。DMA搬运显存是STM32平台相对C51的最大优势。定义一块128x160像素的缓冲区用DMA把缓冲区数据发送到SPI1的DR寄存器整个刷屏过程CPU基本不参与。DMA通道的配置要点是外设地址固定为SPI1-DR存储器地址指向显存缓冲区传输结束触发中断在中断里拉高片选或通知上层刷新完成。4.2 Arduino推荐库与参数表TFT_eSPI和Adafruit_ST7735的选择Arduino平台上常见两种驱动思路。Adafruit_ST7735封装程度高适合第一次接触ST7735的玩家初始化只用两行TFT_eSPI性能更强支持SPI频率设置、DMA视平台而定、更丰富的绘图接口且配置文件是显式地放在User_Setup.h中方便照抄。两者选谁取决于对底层控制的需求如果只是跑通一个demoAdafruit库就够了如果要持续动态刷新或者做小游戏建议直接用TFT_eSPI。TFT_eSPI要做的关键配置都在User_Setup.h里。以1.44寸屏为例常见参数如下表配置项推荐值说明ST7735_DRIVER定义启用ST7735驱动也可用ST7735_GREENTAB标记不同面板偏移TFT_WIDTH / TFT_HEIGHT128 / 160分辨率直接决定坐标范围ST7735_GREENTAB定义绿标签屏常用偏移量为0红标签屏可能需要别的值TFT_MOSI / TFT_SCLK按接线硬件SPI时通常固定为板载引脚不需要改TFT_CS / TFT_DC / TFT_RST按接线可任意指定TFT_eSPI会把这些引脚设置为GPIO输出SPI_FREQUENCY27000000过高会出噪点降到15000000更稳定在User_Setup.h里还需要注意屏幕旋转TFT_eSPI的setRotation(0~3)可以切换四个方向其中0和2对应面板安装方向变化。如果文字方向反了不用改硬件直接换一个旋转参数就能解决。4.3 中文字库方案在Arduino上显示UTF-8编码文字Arduino Uno的内存只有2KB SRAM直接放中文字库不现实但很多ST7735项目是搭配ESP32或STM32用的内存相对宽裕可以加载常用字模。中文显示的难点不在ST7735驱动层面而在字体编码转换上Arduino的String对象存放的是UTF-8编码而16x16点阵字库通常按GB2312或GBK编码索引所以先要把UTF-8的3字节编码解析成GB码。具体做法是写一个UTF8转GB2312的函数逐个字符判断首字节范围把3字节的中文字符编码转换成两个字节的区位码再按区位码在字模数组中查找偏移。字模数据可以用PC上的取模软件生成按宋体或黑体16x16格式逐行取模每两个字节代表一行的左半和右半。把取模结果放到PROGMEM中显示时逐行把bit映射到ST7735的像素即可。一个16x16的中文字模占32字节显示二十个汉字就是640字节无论是Flash还是RAM都完全可接受。5. 显示性能调优与故障排查白屏、花屏与颜色错乱的定位思路最后一章不再铺开讲基础驱动而是聚焦两类实战问题画面刷新不够快的性能瓶颈以及显示异常的排错技巧。5.1 帧率瓶颈从SPI速率到FPS提升的三条路径ST7735在128x160分辨率下一帧像素数据的总量是128乘160乘2字节换算下来约40KB。以8MHz SPI计算纯数据发送时间约40ms理论上帧率上限是25FPS左右加上命令开销实际只有15~20FPS。如果你的项目需要显示动态波形或滚动文字可以按三条路径优化第一把SPI时钟从8MHz提到16MHz甚至更高但要先验证模块在高压摆率下是否出现花屏第二只做局部刷新——ST7735支持任意矩形窗口的RAMWR只更新变化区域能省掉大量冗余传输第三在ESP32或STM32H7这类芯片上启用DMA双缓冲让显示输出与CPU绘制流水并行帧率可以再提升一截。局部刷新的代码要点是调用setWindow设定矩形范围然后连续写入该矩形像素。TFT_eSPI里可以先用fillRect的xywh参数减少API调用开销C51平台则要自己维护脏矩形列表把多个待更新区域合并成一个大矩形避免频繁发送地址命令。5.2 异常现象与故障点对照实际调试时白屏、花屏、颜色偏移的成因往往各有不同。下面这张表是我排查时常用的对照列表现象优先检查点背后的原因上电完全无显示VCC是否3.3V、RST复位时序、BLK是否点亮电源或复位时序不满足ST7735要求白屏但有背光初始化序列是否完整发送、CS电平是否翻转ST7735未进入正常工作模式常因命令序列遗漏SLPOUT或DISPON花屏且画面呈雪花状SPI时钟是否过高、MOSI线上是否有干扰串行数据采样失败降低SPI速度或加长SCLK上升沿前的延时画面左右或上下颠倒MADCTL寄存器参数面板玻璃和模块装配方向不同颜色整体偏转且像是补色0x3A颜色格式、MADCTL的BGR位RGB与BGR顺序不匹配屏上出现横向水波纹电源纹波大、去耦电容缺失背光电流波动影响到内部电荷泵排查时一个有用的技巧是先运行一屏纯色填充比如全红、全绿、全蓝看颜色是否正确这样可以把像素写入和RGB顺序问题隔离出来。纯色正确之后再显示渐变色如果渐变色出现带状条纹说明每两个字节的颜色数据发生了位偏移——通常是把写数据时的DC状态拉错了。5.3 一个具体技巧用渐变色帧验证通信完整性与时隙直接写一段能产生全屏水平渐变的代码可以快速验证SPI吞吐是否稳定也适合用来做产线出货检测。下面以Arduino TFT_eSPI的fillRect循环为例uint16_t col 0; for (int x 0; x 128; x 8) { tft.fillRect(x, 0, 8, 160, tft.color565(x * 2, 0, 255 - x * 2)); delay(2); } delay(500); tft.fillScreen(TFT_BLACK);这段代码从左到右按8像素宽分块填充颜色值从红色渐变到蓝色同时带有TFT_BLACK的整屏清空过程。观察重点有两个一是每个8像素条带的颜色是否平滑过渡如果某个条带明显偏暗或偏亮说明该处的SPI传输或时钟极性有问题二是清屏时是否残留上一帧的残影如果残留明显需要检查GRAM窗口设置是否正确——很多残影问题都来自CASET或RASET窗口没有覆盖全屏。把这段测试函数固定为设备上电后的自检项再把判定结果通过指示灯或串口输出一套最简易的LCD产测程序就完成了。本文还有配套的精品资源点击获取
返回列表