十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

STM32驱动ST7565 LCD完整指南:从时序到图形界面

STM32驱动ST7565 LCD完整指南:从时序到图形界面 简介面向STM32嵌入式开发者的ST7565控制器12864液晶屏驱动资源适合需要快速实现图形界面或自定义字符显示的软硬件工程师、电子爱好者及学生无论入门学习还是项目二次开发均能从中受益。资源围绕硬件SPI接口展开涵盖屏幕初始化、命令发送、显存数据写入等核心环节可系统解决此类无字符库液晶屏的底层驱动难题。压缩包共111个文件整体仅1.55MB以C语言源文件.c/.h为主并包含Keil工程文件、编译生成的hex固件及调试辅助文件结构清晰便于从源码阅读、工程编译到直接烧录验证的完整流程。目前已有671人学习下载。资源中提供关键驱动代码与标准外设库文件可直接移植到自身项目配合详实的注释和文件组织方便理解SPI通信时序与ST7565控制逻辑减少排查初始化、背光、锁存器等问题的弯路是嵌入式显示应用的高效参考。1. 项目概述与硬件方案选型1.1 为什么是ST7565方案ST7565这颗驱动芯片做嵌入式显示的老朋友应该都不陌生。它是一颗单芯片LCD控制器专门驱动COG封装的128×64点阵液晶屏内部集成了64路行驱动和128路列驱动。相比ST7920那种自带中文字库的屏ST7565不带字库所有显示内容都要靠MCU逐像素去画但这恰恰是它的优势128×64全点阵可控想显示什么图案、曲线、波形都可以自由绘制不像ST7920那样受字库格式限制。STM32搭配ST7565是国产工控、消费电子项目里非常经典的一套组合。我这次做的是一个带图形化菜单的便携仪表项目用STM32F103C8T6这颗小芯片驱动一块1.3寸的ST7565屏幕主控只负责逻辑运算和菜单切换屏幕则承担全部人机交互界面。为什么选这颗屏而不选SSD1306的OLED主要考虑是户外强光下的可读性LCD反射式的可视角和阳光下表现比OLED更稳而且ST7565的屏功耗在带背光时也能做到很低。适合参考这篇博文的读者一种是手里正好拿到一块ST7565的裸屏但不会初始化另一种是准备在STM32上做廉价图形界面但被并行接口的线序和时序搞得头疼。这篇内容会把从接线、时序、底层驱动到图形绘制和坑点排查的完整过程写清楚照着做就能跑起来。1.2 屏幕硬件细节与接口模式ST7565屏对外通常引出的引脚有引脚名功能说明VDD/VSS电源正/地一般是3.3V供电SCL/SCLKSPI时钟线SDA/SI/DINSPI数据输入A0/RS/DC数据/命令选择高电平写数据低电平写命令CS/CE片选信号低有效RST/RES复位信号低电平复位BL/BL-、LEDA/LEDK背光正极/负极PSB/BS0串行/并行模式选择接低电平选SPI串行模式这里要特别提醒第一次接触ST7565的朋友别一上来就按并行模式接线。ST7565本身支持6800并行、8080并行和SPI串行三种接口由PSB引脚的电平决定。并行模式需要接8根数据线加6根控制线总共十几根线接线复杂不说还特别容易虚焊。而4线SPI只需要CS、SCL、SDA、A0再加RST和电源总共6根线对STM32来说直接复用硬件SPI外设速度还能跑到几MHz显示刷新的流畅度完全够用。我这次选的是3.3V供电版本如果你拿到5V供电的屏需要确认STM32引脚是否能耐受5V。F103的IO口默认不是5V tolerant的即使标注了FT的引脚能承受5V也建议串一个1kΩ电阻或者加电平转换稳妥起见直接用3.3V供电的屏最省事。初始化之前还有一件关键事确认屏的偏压电路和负压发生器是否内建。ST7565内部有DC-DC升压电路只需要在VOUT引脚外接一个电容典型值0.1uF到1uF再在VR引脚接一个可调电阻到VSS来调节对比度。有些模块会把VR固定成分压电阻板上已经帮你调好对比度了这种屏锂电池供电时最容易遇到的问题是电压从4.2V降到3.3V显示对比度会跟着漂板载固定电阻的屏尤其明显。如果遇到这种情况可以在初始化代码里动态调整对比度寄存器0x81指令后面的参数值后面会详细讲参数计算。2. 驱动原理与底层时序拆解2.1 ST7565的显存结构与寻址方式搞清楚ST7565的显存映射方式写驱动才不会晕。ST7565内部有64路共极COM输出和128路段SEG输出对应屏幕上的64行和128列。它不像SSD1306那样给每一行都分配独立地址而是按页Page来组织的。整块屏幕被分为8页每页由8行像素构成。第0页对应行0到行7第1页对应行8到行15依此类推第7页对应行56到行63。每一页有128个字节每个字节的8个bit低位LSB对应页内的上一行高位MSB对应页内的下一行。整个显存就是8页×128列1024字节写入某个字节时等于同时修改了该页内8行像素的垂直方向8个点。这里有个新手最容易绕进去的地方屏幕的物理行方向和显存的列方向不一定一一对应取决于你初始化的扫描方向设置。ST7565支持ADC选择指令0xA0/0xA1控制SEG输出的扫描方向支持SHL选择指令0xC0/0xC8控制COM输出的扫描方向。如果这两条指令设置反了最常见的问题就是屏幕显示镜像或者上下颠倒。等你把字符和图形代码都写好之后发现字是反的再回头改初始化序列会比较郁闷。建议画点函数里把坐标映射逻辑抽象出来做成软件坐标系遇到镜像问题只改初始化参数不做大改。2.2 SPI时序与读写流程4线SPI模式下ST7565的时序并不复杂可以用硬件SPI也可以用GPIO模拟。硬件SPI的优点是主循环不用一直盯着IO翻转MCU可以有时间去跑业务逻辑缺点是某些屏对时钟极性和相位要求比较死板需要核对数据手册上的时序图。ST7565的SPI时序比较简单CPOL0CPHA0模式0通常就能正常工作也有的屏要求模式3也就是CPOL1、CPHA1。实在不行就先用GPIO模拟SPI验证屏能点亮之后再切到硬件SPI优化速度这样可以减少排错时的变量。写命令和写数据两个字节的处理有一个细节值得注意。A0引脚必须在字节传输的整个过程中保持稳定电平不能在时钟沿附近跳变。使用硬件SPI时如果A0控制用的是普通的GPIO翻转可能因为SPI外设的数据移位和数据输出之间有时序差导致第一个SCL时钟沿来临时A0还没稳定。解决方法是如果是硬件SPI可以试试把A0也换成手动控制的引脚在SPI使能CS拉低之前先设好A0电平再调用SPI发送函数。或者直接用GPIO模拟SPI这样时序完全由你控制稳定性最高代价是刷屏速度大概几百kHz对菜单切换这类应用完全够用。我实测用STM32F103的硬件SPI1时钟分频到4.5MHzST7565能稳定工作帧率足够流畅显示一个128×64的动态曲线区域。如果你要刷全屏动画4.5MHz下全屏更新1024字节再加上命令开销大约2到3ms一帧肉眼看上去非常顺滑。2.3 初始化序列的关键指令ST7565的初始化序列网上能搜到各种版本但不要盲抄很多人的初始化代码是从不相干的屏抄过来改的参数不匹配会导致显示异常。核心指令包括以下几项指令参数作用说明0xE2无软复位等效于上电后执行一次内部复位0x2C无升压电路倍率设为4倍有的屏是0x2E表示5倍0x2E无打开内部升压DC-DC必须在显示开启前使能0xA2无偏压比1/9有的屏用0xA3表示1/7按数据手册选0xA0 / 0xA1无列扫描方向0xA0为正向0xA1为反向0xC0 / 0xC8无行扫描方向0xC0正向0xC8反向0x811字节对比度设置寄存器范围0~63默认0x200xAF无显示开启没有这条屏永远不亮有一个容易被忽略的关键点升压电路打开之后需要等待一段时间让电荷泵稳定再写对比度、显示开关。这段时间通常在10ms到50ms之间不同批次屏幕差异很大。我一般在打开DC-DC之后加一个50ms的死等延时再继续初始化这个小延时可以避免很多莫名其妙的显示异常。对比度参数的计算逻辑是ST7565内部用一组电阻分压网络产生LCD驱动电压0x81指令后面的值0~63控制分压比。电压偏低时屏上的字看起来发灰、水印感很强电压偏高时整个屏会偏黑、甚至显示全黑。如果你发现某个温度下屏幕显示不清检查一下是不是对比度参数没针对当前温度做调整。实际项目中建议把对比度写成可配置项在菜单里加一档“显示调节”让用户可以自己调别把这个参数写死。3. 核心代码编写与图形绘制3.1 底层函数设计写驱动先把底层四件套搞定写命令、写数据、复位、延时。这四件套是所有上层功能的地基。写命令和写数据的函数用GPIO模拟SPI的实现逻辑很直白先拉低CS再根据是命令还是数据设置A0电平然后循环8次每发送一个bit就翻转一次SCL。每次操作结束后拉高CS。唯一要注意的是bit发送顺序ST7565在串行模式下是高位在前MSB first因此每次取数据的第7位作为当前bit然后左移一位。硬件SPI版本更简洁但有一个问题值得注意STM32的SPI外设发送数据时是整字节送出的如果A0的电平切换和SPI发送之间需要同步可以考虑用查询方式SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE)在TXE标志位置位后、发送下一个字节前切换A0这样能确保A0电平的建立时间充足。实测用这种“先切换A0再查TXE再送字节”的顺序各种SPI时钟配置下都能稳定工作。复位函数上电时调用一次即可拉低RES引脚保持10ms以上再释放为高。如果你用的是STM32的硬件复位搭配RC延时电路也可以省略软件复位但保留软件复位会更保险因为单片机可能先于屏幕完成上电初始化。3.2 画点、清屏与字符显示画点函数是图形驱动的地基。ST7565按页寻址画点需要两步计算点所在的页号page y / 8列号col x把对应页的显存缓存数组中对应字节读出来把点所在的bit置1或清零再写回屏这里有个性能优化的关键点不建议直接操作屏幕寄存器画点因为“先读屏-改bit-写回屏”的流程太慢了。正确的做法是在RAM里维护一份1024字节的显存缓冲所有画点、画线、画字符操作都只改缓冲需要显示的时候用一次批量刷新把整块缓冲全部送到屏幕。显存缓冲的更新是内存操作比SPI传输快几个数量级而且还能批量填图、实现界面切换的全屏刷新。清屏函数分两级一级清RAM缓冲一级清屏幕。清RAM缓冲用memset清零即可然后调用刷新函数把整个缓冲推到屏幕。字符显示需要先准备字模。可以先用PC端的取模软件生成8×8 ASCII字母数字字模再把汉字用16×16点阵存成数组。显示ASCII字符时按列方向扫描一个字符占8字节对应屏幕上一列的垂直8个点。显示汉字时是16字节一组对应两页。这里有个经验字模取模方向最好设置成“列行式低位在前”这样和ST7565的页布局天然契合显示代码就不需要额外做bit反转处理。3.3 图形绘制与UI布局有了画点函数和显存缓冲画直线、画矩形、画圆都可以自己封装。画直线用Bresenham算法代码量不大效果却很扎实。画矩形的思路很简单四条边分别画直线如果是填充矩形则逐行扫描填充每页的相应bit区间。我这次做的菜单界面用到了几个常用的UI元素边框、选中高亮块、进度条、小图标。这些都能用基础图元组合出来。进度条的实现很直观按百分比计算填充宽度然后把填充区域逐列写入对应bit。菜单的高亮块倒是有一个小心得如果直接整块填充会盖上文字所以高亮块要在画文字之前画或者高亮块只做反色处理。反色显示是ST7565用得比较多的一个特性。普通反色的思路是把目标区域的字节按位取反这样原来黑色的像素变白、白色变黑。但直接对整个缓存区做取反会连边框和别的文字一起反了。所以在菜单实现里更推荐的做法是先记录高亮块的矩形坐标刷新时只对那个矩形区域内的缓存字节做异或0xFF操作刷新完成后恢复原值。这样既能实现选中态的高亮效果又不会影响界面其他部分。4. STM32工程搭建与调试实录4.1 CubeMX工程配置要点用STM32CubeMX配置工程比较方便。我这次用F103C8T6作为示例核心配置步骤写在下面。时钟部分外部晶振8MHzPLL倍频到72MHzAPB2总线时钟72MHzAPB1总线36MHz。如果不用外部晶振直接用内部HSI也行但SPI时钟配置要注意分频系数的上限HSI 8MHz下SPI最高能到4MHz左右刷新速度足够但余量不大。SPI配置模式设置为主模式数据帧格式8bit时钟极性CPOLLow时钟相位CPHA1EdgeNSS引脚软件控制预分频16SPI时钟72/164.5MHz。注意F103的SPI1挂载在APB2上最高可以到36MHz所以4.5MHz是很保守的配置。GPIO配置CS和A0配置为推挽输出、最大速度50MHzRST配置为推挽输出。如果有背光控制引脚用一个PWM通道去接LEDA这样亮度调节和界面背光休眠都能用PWM直接实现。工程师惯用的一个习惯所有引脚宏定义和SPI接口都在一个lcd_conf.h头文件里做映射这样换平台或改引脚只改头文件一处不用动驱动源码。4.2 编译烧录常见错误排查调试过程中最让人头疼的错误信息就是打开调试器之后弹出的error: no stm32 target found! if your product embeds debug authentication。这个问题大多不是代码本身引起的而是调试器连接或固件配置的问题我遇到过的几种情况和排查方法如下现象常见原因解决方法找不到目标芯片提示No target foundST-Link/J-Link的SWDIO和SWCLK没接好或虚焊重新焊接排针用万用表量到MCU引脚通断能枚举到ST-Link但连接失败目标板供电不稳定或MCU被锁死给目标板单独供3.3V按住复位键点Connect后松开执行全擦除Flash下载成功但程序不跑BOOT0电平不对或复位电容异常检查BOOT0跳线帽是否接GND下载报错RDDI-DAP ErrorKeil的Debug Settings选了错误的接口在Utilities设置中选择ST-Link Debugger并确认SW模式还有一个跟屏本身相关、但表现成“下载失败”的坑如果屏和MCU共用一个3.3V LDO屏上电瞬间的浪涌电流可能导致MCU供电被拉低进而导致调试器连接失败。解决办法是把屏的电源和MCU电源之间加一个磁珠或电感和10uF电容做隔离或者在调试阶段先把屏的电源断开等程序烧录成功再接上。实测过很多次屏幕模块的电容充电瞬间会拉低VDD几十毫秒这期间SWD握手必然失败。4.3 白屏、花屏、对比度异常实战修复初始化代码写完烧录后第一次上电视觉问题通常集中在三类白屏、花屏、对比度异常。每个问题的排查路径不太一样但最终都能归到初始化顺序或寄存器参数上。白屏是最常见的。屏完全没反应检查顺序应该是先量VDD引脚是不是3.3V再查背光引脚是否点亮然后量SCL和SDA的电平变化确认MCU在跑。如果这些都没问题大概率是初始化序列里没有打开升压电路。刚才提到过ST7565必须先把内部DC-DC使能0x2E等待几十毫秒然后才能显示。如果你只写了一大堆指令但漏了0xAF这最后一步屏也会一直保持睡眠状态。花屏通常是初始化序列里扫描方向设置与实际走线不匹配或者对比度设置太低导致相邻像素之间串扰。显示内容是乱的先降低对比度值试一下如果降到0之后还是花的重点查0xA0/0xA1和0xC0/0xC8这两个方向的组合。另外有一种花屏很隐蔽复位时序不对MCU已经写完初始化指令屏的复位引脚才被拉高导致屏根本没执行初始化。解决方法是把复位引脚接到MCU的GPIO上手动控制复位时序而不是靠RC上电复位这样最可靠。对比度异常的表现是整体发灰像没睡醒或者全部黑块。调节0x81寄存器后面的参数就能解决数值范围0到63。我实测在不同温度下的表现差异很明显夏天室外30度时0x18已经是舒服的浓度冬天室内10几度可能得加到0x2A。所以如果你做的是户外设备建议把对比度做成可动态调节并且把VR引脚的硬件可调电阻也留出来双保险。5. 显示缓存策略与刷新性能优化5.1 局部刷新与全屏刷新的取舍显存缓冲方案最大的问题是刷新整屏1024字节需要时间。虽然4.5MHz SPI下听起来只需要几毫秒但如果在刷新中途被高优先级中断打断显示会出现撕裂。解决撕裂的方法有两种。第一种是每次只刷新变化区域做法是维护一个脏矩形dirty rectangle标记只有覆盖到脏矩形的部分才提交给屏幕。菜单切换、进度条变化、图标点亮这类局部变化脏矩形只占屏幕十分之一不到刷新时间能缩短一个数量级同时还能避免全屏刷新导致的闪烁感。第二种是用DMA配合SPI传输。STM32F103的SPI1可以触发DMA1通道3请求把显存缓冲直接交给DMA搬运CPU全程不用管SCL翻转。我第一次用DMA刷新ST7565的时候效果非常明显原来主循环在显示函数里等了2ms多现在只需要设置一次DMA使能CPU立刻回到业务逻辑画面刷新完全无感。要注意的是DMA传输期间不能修改显存缓冲否则数据被破坏。工程上的做法是双缓冲一个缓冲区给DMA读一个给UI写入刷新前把新数据拷贝到DMA缓冲。5.2 SPI时钟与布线的经验值STM32F103驱动ST7565SPI时钟能跑多快不能只看芯片数据手册。ST7565的手册上写的SPI最大时钟是几MHz但那是在理想走线条件下的值。实际模块屏的SCL/SDA走线如果比较细长或者屏的FPC排线绕了弯时钟过高就会出错。我实测过几块不同厂商的1.3寸ST7565屏模块给出了大致的经验值SPI时钟表现建议≤2MHz各种屏都稳定调试阶段首选排错最稳4~6MHz多数屏稳定个别屏偶尔花屏可以使用但要做压力测试≥8MHz长线连接下容易丢bit尽量避免除非确认屏模块质量好如果你的屏模块的A0/CS控制也是用GPIO翻转高速SPI下容易出现命令数据错位因为GPIO翻转速度跟不上SPI发送速度。解决办法是初始化时把一个字节的命令写到SPI数据寄存器然后用一个延时等待TXE标志再翻转下一个操作的A0。这样A0跳变的建立时间大约有几百纳秒远大于GPIO翻转时间能有效解决错位问题。5.3 输出缓冲与背光PWM联动功耗优化是便携设备逃不开的话题。ST7565的全屏刷新电流大概在1到2mA不算大但背光LED驱动的电流通常有10到20mA。手头项目电池容量有限所以休眠策略是低功耗设计里很重要的部分。背光通过PWM控制后亮度等级可以做成平滑渐变的呼吸效果平时空闲5分钟之后自动降低到10%亮度或直接关闭。ST7565本身也支持休眠指令0xAE关闭显示进入休眠前先关背光、再关显示、再关SPI外设时钟让F103进入Stop模式。实测这一整套下来待机电流能压到10uA以下。唤醒流程要注意顺序先开SPI时钟、等待时钟稳定再开显示0xAF最后开背光PWM。如果先开背光再开显示用户会看到屏先亮一下再迅速进入正常内容体验很差。调整顺序之后唤醒和休眠都表现得很干净。6. 常见问题速查表与排错心得6.1 问题速查表实操过的项目积累了不少坑整理成速查表方便大家直接检索问题现象根因分析解决方法屏全白怎么发指令都没反应电源引脚虚焊或升压未使能检查VDD电压确认初始化序列含0x2E并延时50ms显示内容左右镜像0xA0/0xA1方向设置与实际屏不符把0xA0改为0xA1或反过来显示内容上下颠倒0xC0/0xC8方向设置不对把0xC0改为0xC8或反过来首行或首列有杂点显存缓冲未清零或坐标越界检查画点函数是否对x/y坐标做过边界裁剪显示正常但很淡对比度太低或偏压比错误调大0x81参数检查0xA2/0xA3偏压比显示大块黑斑对比度过高或升压电容选大了调小0x81参数检查VOUT电容容值刷新时闪烁整屏刷新太频繁改为脏矩形局部刷新或用DMA双缓冲下电后恢复杂质没有执行0xAE休眠指令休眠前发0xAE并关闭背光PWMSPI数据偶尔错位A0翻转和SPI发送时序不匹配改为TXE标志同步切换A0降低SPI时钟6.2 排错的核心方法论液晶驱动出问题最忌讳的就是瞎改参数。我的习惯是先把串口或调试器里的共存信息拉出来用逻辑分析仪看SCL/SDA/A0/CS的实际波形对照数据手册的时序图一帧一帧比对。没有逻辑分析仪的话也可以用GPIO翻转加示波器在写命令的前后拉高拉低某个测试引脚能看到命令发送的节奏是否正常。另外拿到一块新屏幕模块别急着直接怼代码先用万用表量一下板上各个引脚和VDD、GND之间的阻值判断是否有短路。有些网上买的散新屏模块上的PSB电阻焊错了位置默认是并行模式你按SPI怎么调都不亮。这时把PSB引脚强制接GND再试SPI往往秒解决。这个坑我踩过不止一次也见过很多同行的帖子里问同样的问题。如果你也遇到“SPI时序完全正确、屏就是不亮”的情况第一反应就应该去检查PSB有没有被拉低。7. 个人经验与后续扩展方向写驱动这事最核心的收获是把“数据手册”和“实际硬件”对应起来。ST7565的数据手册并不复杂但真正动手焊板、调时序、看到屏幕亮起来和只看手册的体会完全不同。我也建议大家在完成基础驱动之后花点时间做一个简单的性能测试程序先全屏刷白色然后刷黑色交替几次看看有没有残影、闪烁、拖尾。这个测试能很快找出初始化参数里偏压和对比度的组合是否合适也能验证SPI时钟的上限。后续如果要在这个项目上继续扩展可以考虑的方向有两个。一是把UI框架升级成带事件触发的图标菜单用图标加文字作为菜单项滚动时只刷新脏矩形区域这套交互在很多便携仪器上都很实用。二是把ST7565驱动做成RTOS下的独立显示服务显示任务用信号量保护这样其他任务可以异步调用绘制接口不会互相阻塞。最后分享一个小技巧ST7565的对比度寄存器在工作温度变化时表现非常灵敏做产品时最好把对比度参数放到Flash里出厂后根据环境温度做一次自校准把最优值保存下来。这个功能看起来小但实际交付给用户以后屏幕在不同环境下都能保持清晰可读口碑提升不少。本文还有配套的精品资源点击获取
返回列表