news 2026/10/15 17:31:07

基于12864液晶屏的时钟温湿度显示终端设计与实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于12864液晶屏的时钟温湿度显示终端设计与实现

1. 项目缘起与整体设计思路

12864这个型号,玩过单片机的朋友应该都不陌生。它本质上是一块128x64像素的点阵液晶屏,驱动芯片通常是ST7920或者KS0108这类,支持并行和串行两种通信方式,内置中文字库的版本还能直接显示汉字,省去了取模的麻烦。我这次要聊的项目,就是拿它来做一块同时显示时钟和温湿度信息的小终端。听起来简单,但实际做下来,从选型到布局再到刷新逻辑,每一步都有值得说道的地方。

先说清楚这个项目能干什么。最终成品是一块巴掌大的显示终端,屏幕上同时呈现四类信息:当前时间(时、分、秒)、日期(年、月、日、星期)、环境温度、环境湿度。时间走时准确,温湿度实时更新,整个界面清爽不闪烁。它解决的核心问题是:把多个独立的信息源整合到一块屏幕上,用一个低成本的MCU统一调度,适合放在桌面、工作台或者作为嵌入式学习的综合练手项目。适合谁来参考?有一定单片机基础、玩过1602或者OLED、想进一步折腾图形化布局和定时调度的朋友。纯小白也能看,但建议先把GPIO和定时器中断的基本概念过一遍。

为什么选12864而不是更常见的1602或者0.96寸OLED?这是第一个要解释清楚的选型逻辑。1602只能显示两行字符,要同时塞下时间、日期、温湿度,信息密度不够,得来回翻页,体验很差。0.96寸OLED虽然小巧、对比度高,但尺寸太小,远看费劲,而且很多OLED模块长时间显示静态内容会有烧屏风险。12864的128x64分辨率,刚好能划分出几个区域:顶部一行显示日期和星期,中间用大号字体显示时间,底部两行分别放温度和湿度。空间不浪费,也不局促。另外,带中文字库的12864在显示“温度”“湿度”“星期”这些汉字时非常方便,不需要额外做字模。

整体方案上,我采用的是STC89C52或者STM32F103这类常见MCU作为主控,前者适合纯51入门,后者适合想用硬件I2C和更多定时器资源的场景。温湿度传感器选的是DHT11或者SHT30,前者便宜、单总线协议、精度够用,后者走I2C、精度更高、响应更快。时钟部分,如果对精度要求一般,可以用MCU的定时器配合软件计数;如果要求走时准,建议加一颗DS1302或者DS3231这类专用RTC芯片,带纽扣电池,掉电不丢时间。我两个版本都做过,后面会分别讲。

显示刷新策略是这个项目的核心难点之一。12864的刷新速度有限,尤其是并行模式下,如果你每次更新都全屏重绘,屏幕会明显闪烁。我的做法是分区刷新:时间区域每秒只更新变化的数字,温湿度区域每两秒更新一次,日期区域基本不变,只在跨天时刷新。这样既保证了实时性,又避免了频繁全屏写入带来的闪烁。这个思路在后面会展开讲具体实现。

2. 核心器件选型与关键参数解析

2.1 12864液晶屏的两种驱动方案对比

12864模块市面上主要有两种驱动芯片方案,一种是ST7920,支持串行和并行,内置8192个中文汉字字库;另一种是KS0108,只有并行接口,不带字库。这个区别直接决定了你的代码复杂度和IO占用。

ST7920的串行模式只需要三根线:CS、SCLK、SID,对于IO紧张的MCU非常友好。但串行模式下刷新速度慢,全屏刷新大概需要几十毫秒,如果你频繁全屏刷新,肉眼能感觉到轻微闪烁。并行模式需要8位数据线加3位控制线,占用11个IO,但速度快很多。我最终选择的是ST7920的并行模式,因为我要做分区刷新,并行模式下每次只写一小块区域,速度快到肉眼无感。

KS0108的方案我不推荐新手用,因为它没有字库,显示任何汉字都要自己取模,工作量翻倍。而且KS0108的时序要求更严格,稍不注意就花屏。如果你手头只有KS0108的屏,也不是不能用,但建议先跑通全屏清屏和画点,再往上叠功能。

对比项ST7920(带字库)KS0108(无字库)
接口方式串行/并行可选仅并行
中文字库内置无,需自取模
IO占用(并行)11根11根以上
刷新速度较快中等
上手难度低中高
推荐场景综合显示项目图形化定制项目

2.2 温湿度传感器的精度与响应速度权衡

DHT11和SHT30是我实际用过的两款。DHT11便宜,单总线协议,只需要一根数据线,但它的精度是温度±2℃、湿度±5%RH,而且采样周期不能低于1秒,响应偏慢。SHT30走I2C,精度温度±0.3℃、湿度±3%RH,采样速率可编程,最快能达到每秒多次。如果你只是做个桌面小摆件,DHT11完全够用;如果你要做数据记录或者对精度有要求,直接上SHT30,省得后面换传感器重写驱动。

这里有个细节:DHT11的单总线协议对时序非常敏感,如果你用51单片机跑,建议关掉中断再读,否则中断会打乱时序导致读数失败。SHT30就省心很多,I2C硬件外设直接读寄存器,稳定性好很多。我在早期版本用DHT11时,偶尔会遇到读数为0的情况,后来加了重试机制才稳定下来。

2.3 RTC时钟芯片的必要性与选型

很多人一开始想省掉RTC芯片,直接用MCU定时器计数。这么做短期没问题,但一旦断电,时间就归零了。而且MCU的晶振精度有限,一天下来可能差几秒到几十秒。DS1302是经典的低成本RTC,走三线SPI协议,带31字节RAM,价格便宜,但精度一般,需要外接32.768kHz晶振和纽扣电池。DS3231是升级版,走I2C,内置温补晶振,精度能达到±2ppm,一年误差也就一两分钟,价格贵一些但省心。

我的建议是:如果你只是练手,用MCU定时器就够了;如果你想做个能长期用的桌面时钟,直接上DS3231,别在DS1302上纠结。DS1302的时序模拟比较麻烦,而且对晶振匹配电容有要求,调不好走时不准。DS3231即插即用,代码也简单。

3. 显示布局设计与刷新逻辑实现

3.1 屏幕分区规划与坐标计算

12864的坐标系是X轴0到127,Y轴0到63,按页划分的话,每8个Y像素为一页,共8页。ST7920的并行模式支持直接写指令和写数据,设置好地址后连续写入即可。我的布局是这样的:

  • 顶部区域(Y=0到15,即第0、1页):左侧显示日期“2025-01-15”,右侧显示星期“周三”
  • 中部区域(Y=16到39,即第2、3、4页):大号数字显示时间“14:30:25”,用16x32的自定义字模
  • 底部区域(Y=40到63,即第5、6、7页):第一行显示“温度:25.3℃”,第二行显示“湿度:58%RH”

这个布局的关键在于时间数字要用大号字模,否则和温湿度字体一样大,视觉上没有主次。16x32的字模需要自己取模,每个数字占用4个字节的宽度(16像素=2字节,32像素高度=4页),0到9十个数字加上冒号,一共11个字符,取模工作量可控。

坐标计算上,ST7920的地址设置指令是:先写页地址(0到7),再写列地址(0到15,每列对应2个像素?不对,这里要澄清一下)。ST7920的列地址是以“字”为单位,每个字是16位,对应屏幕上的16个像素。所以列地址0到7对应X=0到127。实际写数据时,先写高8位,再写低8位,分别对应左半和右半。这个细节如果搞错,显示会错位。

3.2 分区刷新与防闪烁策略

全屏刷新闪烁的根本原因是:你清屏和写新内容之间有时间差,屏幕会短暂变白。解决办法有两个:一是用双缓冲,先在内存里画好再一次性写入,但12864的显存只有1KB,双缓冲对51单片机来说太奢侈;二是分区刷新,只更新变化的部分。

我的做法是:时间区域每秒只更新秒数变化的两位数字,分钟和小时不变时不重写。温湿度区域每两秒更新一次,而且只更新数值部分,标签“温度:”“湿度:”只写一次。日期区域只在跨天时刷新。这样大部分时间屏幕是静止的,只有秒数在跳,视觉上非常稳定。

具体实现上,我维护了一个“当前显示值”的缓存数组,每次新数据来的时候,和缓存对比,只有不同的字符才触发写入。这个逻辑虽然简单,但效果立竿见影。实测下来,秒数跳动时完全感觉不到闪烁。

注意:ST7920在写数据前必须先设置地址,如果你连续写多个字符但不重设地址,它会自动递增列地址,但跨页时不会自动换行,需要手动设置下一页的地址。这个坑我踩过,导致字符显示到屏幕边缘后消失。

3.3 大号字模的取模与显示技巧

16x32的大号数字取模,我用的是PC端取模软件,设置成“纵向取模、字节倒序”或者“横向取模”要看你的写入方式。ST7920的并行写入是按字节写,每个字节对应8个垂直像素。所以16x32的字模,每个数字需要16列x4页=64字节。取模时选择“阴码”还是“阳码”取决于你的背景色和前景色。

显示的时候,先设置起始页和列地址,然后连续写入64个字节。注意每写16个字节(即一页的宽度),要重新设置下一页的地址。这个循环逻辑要写对,否则数字会显示成乱码。

我建议先用一个小程序测试单个数字的显示,确认取模方向和字节顺序正确后,再批量处理所有数字。这个步骤花点时间,但一劳永逸。

4. 完整实操流程与核心代码解析

4.1 硬件连接与供电注意事项

先列一下我最终版本的硬件清单:STC89C52RC最小系统板、12864液晶屏(ST7920并行版)、DS3231模块、SHT30模块、5V电源。连接上,12864的数据线接P0口,控制线CS、RS、RW、EN分别接P2.0到P2.3。DS3231的SCL、SDA接P2.4、P2.5,SHT30也挂在这两个脚上,因为I2C支持多设备。注意DS3231和SHT30的I2C地址不能冲突,DS3231默认0x68,SHT30默认0x44,没问题。

供电方面,12864的背光电流大概20mA,加上MCU和传感器,整体不超过100mA,USB供电足够。但要注意,12864的背光如果直接接5V,最好串一个限流电阻,否则长期用会缩短背光寿命。我串了一个100欧姆的电阻,亮度稍微降一点,但发热明显减小。

提示:如果你用的是3.3V的MCU,比如STM32,12864的5V逻辑电平可能需要电平转换,否则长期工作可能损坏屏幕。最简单的办法是用74HC245做电平匹配,或者选支持3.3V供电的12864模块。

4.2 初始化流程与关键指令序列

12864的初始化顺序很重要,顺序错了可能不显示。我的初始化序列是这样的:

// 12864并行模式初始化(ST7920) void LCD12864_Init(void) { Delay_ms(50); // 上电等待稳定 LCD_WriteCmd(0x30); // 基本指令集 Delay_ms(1); LCD_WriteCmd(0x0C); // 开显示,关光标,关反白 Delay_ms(1); LCD_WriteCmd(0x01); // 清屏 Delay_ms(10); // 清屏需要较长时间 LCD_WriteCmd(0x06); // 光标右移,画面不移动 Delay_ms(1); }

这里的关键是清屏指令后必须延时10ms以上,否则后续写入会丢失。我一开始只延时1ms,结果屏幕偶尔花屏,后来改成10ms就稳定了。

DS3231的初始化主要是检查时钟是否在运行,如果掉电过,需要重新设置时间。SHT30的初始化是发送测量命令,等待转换完成后再读数据。

4.3 定时器调度与多任务处理

整个系统有三个周期性任务:时间读取(每秒一次)、温湿度读取(每两秒一次)、显示刷新(每秒一次,但只刷新变化部分)。我用了一个定时器产生1ms基准中断,在中断里维护三个计数器,分别计数到1000、2000、1000时置标志位。主循环里检查标志位,执行对应任务。

这种前后台架构在51上很常见,优点是简单可靠,不需要RTOS。但要注意,中断服务函数里不要做耗时操作,只置标志位。温湿度读取和显示刷新都在主循环里做,避免中断阻塞。

如果你用STM32,可以直接上FreeRTOS,开三个任务分别处理,优先级从高到低是显示刷新、时间读取、温湿度读取。但说实话,这个项目用RTOS有点杀鸡用牛刀,前后台足够了。

4.4 温湿度数据读取与格式化显示

SHT30的读取流程是:发送0x2C06命令启动测量,延时20ms,然后读6个字节,前两个是温度,中间两个是湿度,最后两个是CRC校验。温度换算公式是:-45 + 175 * (raw / 65535),湿度是:100 * (raw / 65535)。算出来的浮点数要格式化成字符串,比如“25.3℃”,注意小数点后保留一位。

DHT11的读取更简单,但时序要求高。起始信号拉低18ms,然后释放,等待传感器响应。读取40位数据,前16位湿度、中间16位温度、最后8位校验和。校验和等于前四个字节之和的低8位。如果校验失败,直接丢弃这次数据,用上一次的值。

显示的时候,我把温度和湿度格式化成固定长度的字符串,比如“25.3”和“58.0”,不足两位的补空格。这样刷新时字符位置不会跳动。

5. 常见问题排查与避坑经验实录

5.1 屏幕花屏与乱码的排查思路

花屏是12864最常见的问题,原因通常有三个:初始化时序不对、地址设置错误、电源不稳。我的排查顺序是:先用万用表量VCC和GND之间的电压,确保在4.8V到5.2V之间;然后检查初始化代码,确认清屏延时足够;最后检查地址设置,特别是跨页写入时有没有重设页地址。

有一次我遇到屏幕上半部分正常、下半部分花屏,查了半天发现是页地址设置时,我写的是0到7,但实际屏幕只有8页,写第8页(地址7)时越界了。后来改成0到7循环,问题解决。

5.2 温湿度读数异常的处理方法

DHT11读数失败最常见的原因是时序被打断。我的解决办法是在读取前关总中断,读完再开。另外,DHT11上电后需要1秒的稳定时间,如果你上电就立刻读,第一次大概率失败。我在初始化后加了2秒延时,之后再开始读取。

SHT30如果读数一直是0或者固定值,先检查I2C地址对不对,然后用逻辑分析仪抓一下波形,看ACK有没有正常返回。很多时候是上拉电阻没接,I2C总线需要4.7k到10k的上拉电阻,模块上一般自带了,但如果你是自己画的板子,别忘了加。

5.3 走时不准的校准与补偿

用DS3231的话,走时基本不用校准,出厂精度就够。但如果你用的是DS1302,走时偏快或偏慢是常态。校准的方法是:先让它跑24小时,记录误差秒数,然后调整晶振的匹配电容。如果走快了,增大电容;走慢了,减小电容。每次调整后重新跑24小时观察。这个过程比较磨人,但调好后能稳定在每天误差几秒以内。

用MCU定时器计时的方案,误差主要来自晶振本身。你可以通过软件补偿:比如每天固定加或减几秒。但这种方法治标不治本,温度变化后误差又会变。所以我还是推荐用专用RTC芯片。

5.4 常见问题速查表

现象可能原因排查方法解决措施
屏幕全白背光正常但无显示检查初始化序列确认清屏延时≥10ms
屏幕花屏地址设置错误检查页地址和列地址跨页时重设页地址
显示错位取模方向不对对比取模设置和写入顺序调整取模软件的字节序
温湿度读数为0时序被打断关中断再读读取前关总中断
走时偏快晶振负载电容偏小测量24小时误差增大匹配电容
走时偏慢晶振负载电容偏大测量24小时误差减小匹配电容
I2C通信失败上拉电阻缺失用示波器看波形加4.7k上拉电阻

提示:如果你在调试时遇到屏幕偶尔闪一下然后恢复正常,大概率是电源纹波太大。在VCC和GND之间并一个100uF电解电容和一个0.1uF陶瓷电容,能明显改善。

6. 项目扩展与个人实操体会

这个项目做完之后,我陆续加了一些扩展功能,比如用按键切换显示华氏度、增加整点报时蜂鸣器、通过串口把温湿度数据上传到电脑记录。这些扩展都不难,核心的显示和调度框架不用动,只需要在任务列表里加新任务就行。

我个人在实际操作中的体会是:12864的并行模式虽然占IO多,但刷新速度和稳定性确实比串行好,如果你IO够用,优先选并行。温湿度传感器别贪便宜,DHT11玩玩可以,真要做长期运行的项目,SHT30省心太多。RTC芯片同理,DS3231贵一点但省下的调试时间绝对值回差价。

最后再分享一个小技巧:如果你觉得16x32的大号数字取模太麻烦,可以用8x16的字体放大两倍显示,虽然边缘会有锯齿,但远看效果可以接受,而且取模工作量减半。具体做法是每个像素点横向和纵向各复制一次,代码里用一个循环就能实现。这个技巧在我早期版本里用过,应急完全没问题。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 17:31:07

Inkscape便携版完全指南:从RAR解压到SVG批量导出与配置迁移

简介:这是开源矢量绘图软件Inkscape 0.92.4稳定版Windows安装包合集,面向平面设计师、插画师和入门学习者,满足专业矢量图形绘制、多格式素材处理与教学实践等需求。软件内置完善的工具栏与形状工具,支持SVG、AI、PDF等格式导入&a…

作者头像 李华
网站建设 2026/10/15 17:30:54

操作系统磁盘管理与IO设备复习笔记:从物理结构到调度算法完整梳理

1. 磁盘管理与IO设备的知识框架拆解 1.1 为什么这块内容总让人“学了就忘” 操作系统里的磁盘管理和IO设备这两块,很多人第一遍学的时候觉得概念不多,不就是磁盘调度算法加个中断处理吗?但真到做题或者面试的时候,发现完全串不起…

作者头像 李华
网站建设 2026/10/15 17:29:41

Kerberos 认证报错排查实战:从错误码到根因的完整指南

1. 从一次票据请求失败说起:Kerberos 报错为什么总让人一头雾水如果你在运维或后端开发岗位上待过一段时间,大概率遇到过这样的场景:服务突然大面积不可用,日志里刷出一片KRB_AP_ERR_SKEW、KRB_AP_ERR_MODIFIED或者Server not fou…

作者头像 李华