恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
C51单片机驱动LCD1602入门:从点亮到显示温度时间
首页
资讯中心
/
C51单片机驱动LCD1602入门:从点亮到显示温度时间
C51单片机驱动LCD1602入门:从点亮到显示温度时间
发布时间:2026/10/21 2:42:56
简介这份资源是面向C51单片机初学者与嵌入式爱好者的LCD1602显示例程合集围绕字符型液晶屏与8051内核单片机的交互展开覆盖矩阵按键键值、DS18B20温度、DS1302实时时钟以及ADC0832模数转换电压四类典型应用场景帮助读者理解数据线、地址线及RS、RW、E控制信号的驱动逻辑。压缩包共86个文件约4.13MB包含c源码、h头文件、uvproj与uvopt工程配置、hex烧录文件、dsn与pdsprj仿真工程以及mp4操作录屏和lst、m51编译列表等兼顾代码实现与仿真验证。目前已有1076人学习下载。四个独立工程分别对应按键扫描、单总线测温、串行时钟读取和模拟量采集读者可对照录屏观察仿真现象再结合源码梳理显示格式化与接口时序适合作为课程设计或电子制作的参考素材。1. 从一块“只会亮灯”的板子说起LCD1602 到底是什么你手里可能有一块单片机开发板上面焊着一块绿色或蓝色的屏幕能显示两行字每行十六个字符。你把它通上电屏幕亮了但要么一片空白要么只有一排方块。你想让它显示“Hello”却不知道从哪下手。这块屏幕就是 LCD1602而让它听话的过程就是这篇文章要带你走完的路。LCD1602 是一种字符型液晶显示模块它不能显示图片也不能显示中文只能显示数字、英文字母和少量符号一共两行每行最多十六个字符。它便宜、稳定、接线简单几乎是每个学单片机的人第一个真正“输出信息”的外设。你学它不是为了做产品而是为了跨过一道坎让程序的结果不再只是闪烁的 LED而是变成你能读懂的文字。C51 单片机是它的经典搭档两者配合是嵌入式入门最经典的组合之一。适合谁适合刚学完点亮 LED、会写最简单的延时函数、但还没让单片机“说话”的你。2. 为什么值得先学它从“看不见”到“看得见”的跨越2.1 它是调试的眼睛也是信心的来源学单片机最难受的阶段是程序跑没跑通你根本不知道。LED 只能告诉你“有电”或“没电”按键只能告诉你“按了”或“没按”。但当你接上 LCD1602你可以让程序把变量值、传感器读数、状态标志直接打印在屏幕上。比如你后面要学 DS18B20 温度传感器温度到底读出来没有、读出来是多少看一眼屏幕就知道。没有它你只能靠猜或者把数据传回电脑那又是另一套麻烦事。我第一次学的时候卡在 DS1302 时钟芯片上很久读出来的时间全是乱码。后来把读到的原始字节直接显示在 LCD1602 上才发现是时序里少了一个延时。屏幕不会骗你它显示什么程序就是什么。这种“看得见”的反馈是新手坚持下去最重要的动力。2.2 它逼你搞懂“时序”这个玄学LCD1602 的驱动不复杂但它有一套严格的读写时序。什么时候送命令、什么时候送数据、什么时候读忙标志都有时间要求。你如果只是抄一段代码烧进去可能也能显示但一旦换一块屏幕、换一个晶振频率就不亮了。真正自己写一遍驱动你会被迫理解“使能脉冲”“建立时间”“保持时间”这些词到底在说什么。这些概念在后面学 DS1302、DS18B20 时全都会用到它们都是靠一根线按特定节奏传数据的。提示新手不要一上来就追求“无延时驱动”或“高速刷新”先把标准时序跑通哪怕延时给得保守一点。2.3 它连接了按键、传感器和时钟你拿到的这份例程标题里除了 LCD1602 和 C51还带了按键、DS18B20、DS1302。这不是随便凑的。按键用来切换显示页面DS18B20 提供温度数据DS1302 提供日期和时间。LCD1602 是最终的展示窗口。学完这个例程你就有了一个最小的“环境监测站”雏形按一下键屏幕从时间跳到温度再按一下跳回来。这个过程中你会把之前单独学的按键扫描、单总线通信、SPI 通信全部串起来。这才是它真正的价值——不是一块屏幕而是一个完整的入门项目骨架。3. 动手之前接线、供电和第一个能亮起来的画面3.1 先认清引脚别急着插线LCD1602 通常有 16 个引脚编号从 1 到 16。你不需要记住全部先记住这几组引脚名称作用新手接法1VSS地接单片机 GND2VDD电源正接 5V3V0对比度调节接电位器中间脚4RS数据/命令选择接单片机某个 IO5RW读/写选择一般直接接地只写不读6E使能信号接单片机某个 IO7-14D0-D7数据线接单片机一组 IO15A背光正串电阻接 5V16K背光负接 GNDV0 的对比度调节很关键。你如果发现屏幕亮了但看不到字或者只有一排黑方块八成是 V0 电压不对。拿一个 10K 电位器一端接 5V一端接 GND中间脚接 V0慢慢拧直到字清晰出现。这个坑几乎每个人都会踩一次。3.2 第一个例程让屏幕显示一行字假设你把 RS 接 P2.0RW 接 GNDE 接 P2.1数据线 D0-D7 接 P0 口。下面是最小化的显示代码只做一件事在第一行显示“Hello LCD”。#include reg52.h #define LCD_DATA P0 sbit RS P2^0; sbit E P2^1; // 短延时让时序满足 LCD1602 的要求 void delay(unsigned int t) { while (t--); } // 写命令RS0E 给一个高脉冲 void lcd_write_cmd(unsigned char cmd) { RS 0; LCD_DATA cmd; delay(100); E 1; delay(100); E 0; } // 写数据RS1E 给一个高脉冲 void lcd_write_data(unsigned char dat) { RS 1; LCD_DATA dat; delay(100); E 1; delay(100); E 0; } // 初始化按手册要求的顺序送命令 void lcd_init() { lcd_write_cmd(0x38); // 8 位数据两行显示5x7 点阵 lcd_write_cmd(0x0C); // 开显示关光标不闪烁 lcd_write_cmd(0x06); // 写一个字符后地址自动加一 lcd_write_cmd(0x01); // 清屏 delay(1000); } void main() { unsigned char i; unsigned char *str Hello LCD; lcd_init(); lcd_write_cmd(0x80); // 设置显示地址为第一行第一个位置 for (i 0; str[i] ! \0; i) { lcd_write_data(str[i]); } while (1); }这段代码里0x38、0x0C、0x06、0x01是 LCD1602 的初始化命令顺序不能乱。0x80是设置 DDRAM 地址的命令第一行第一个位置对应地址 0x00所以命令是 0x80 | 0x00。如果你想在第二行第一个位置显示就写0x80 | 0x40也就是0xC0。delay(100)里的 100 不是精确的微秒数它只是让 E 脉冲足够宽新手先不用纠结具体时间能显示就行。注意如果你用的是 4 位数据线接法初始化命令和写数据的方式会不一样但原理相同。建议第一遍先用 8 位接法线多但逻辑直白。3.3 显示变量让屏幕说出温度值只会显示固定字符串还不够你真正需要的是把变量显示出来。比如 DS18B20 读到一个温度值temp它是整数你要把它变成字符显示。下面这个函数把 0 到 99 的整数显示在屏幕上。// 在指定位置显示一个两位整数 void lcd_show_num(unsigned char row, unsigned char col, unsigned char num) { unsigned char addr; if (row 0) addr 0x80 col; else addr 0xC0 col; lcd_write_cmd(addr); lcd_write_data(num / 10 0); // 十位 lcd_write_data(num % 10 0); // 个位 }num / 10 0是把数字转成对应字符的常用写法。比如 num 是 2525/10 得 2加 0 的 ASCII 码就变成字符 2。个位同理。你后面读 DS18B20 得到的温度、读 DS1302 得到的小时和分钟都可以用这个函数显示出来。先让屏幕显示一个你手动改的变量再把它换成传感器读到的值这一步跨过去例程就活了一半。4. 把按键、DS18B20、DS1302 串起来一个能切换的显示界面4.1 按键扫描别用延时死等按键接法通常是一个引脚接按键按键另一端接地引脚配置成输入并开启上拉。最简单的扫描方式是轮询在主循环里不断读引脚如果是低电平就认为按下。但机械按键有抖动你需要在检测到低电平后延时 10 到 20 毫秒再读一次如果还是低电平才确认按下。sbit KEY P3^2; bit key_pressed() { if (KEY 0) { delay(1000); // 约 10ms消抖 if (KEY 0) { while (KEY 0); // 等待松手 return 1; } } return 0; }这个函数返回 1 表示有一次有效按下。你在主循环里调用它按一次就切换一个显示模式。注意while (KEY 0)会卡住程序如果你后面要同时刷新时间和温度就不能用这种死等松手的方式而要改成状态机。但作为入门先让按键能切换页面再优化。4.2 DS18B20一根线读出温度DS18B20 是单总线器件一根数据线完成所有通信。它的时序要求比 LCD1602 更严格延时必须准确。例程里通常包含复位、写字节、读字节、启动转换、读温度这几个步骤。你不需要从头写但要知道读回来的温度是 16 位高 5 位是符号位低 4 位是小数部分。如果只显示整数把读到的 16 位值右移 4 位再乘 0.0625 取整就行。// 简化示意读取温度并返回整数部分 int ds18b20_read_temp() { unsigned char low, high; int temp; ds18b20_start(); // 启动一次温度转换 delay_ms(750); // 等待转换完成12 位精度约 750ms ds18b20_reset(); ds18b20_write_byte(0xCC); // 跳过 ROM ds18b20_write_byte(0xBE); // 读暂存器 low ds18b20_read_byte(); high ds18b20_read_byte(); temp (high 8) | low; return temp 4; // 取整数部分 }0xCC是跳过 ROM 命令总线上只有一个 DS18B20 时用它最省事。0xBE是读暂存器命令读回的第一个字节是温度低 8 位第二个是高 8 位。temp 4把小数部分丢掉只留整数。你把这个返回值交给lcd_show_num屏幕上就能看到温度了。4.3 DS1302让屏幕显示日期和时间DS1302 是实时时钟芯片它自己走时掉电后靠纽扣电池维持。它用三根线通信复位、时钟、数据。例程里会提供读写寄存器的函数。你需要做的是初始化时写入一个起始时间然后每隔一秒读一次当前时间显示在屏幕上。// 读取 DS1302 的小时和分钟并显示 void show_time() { unsigned char hour, min; hour ds1302_read(0x85); // 读小时寄存器 min ds1302_read(0x83); // 读分钟寄存器 lcd_show_num(0, 0, hour); // 第一行显示小时 lcd_write_data(:); lcd_show_num(0, 3, min); // 第一行显示分钟 }DS1302 的寄存器数据是 BCD 码也就是说0x23表示 23 点而不是十进制的 35。你如果直接当十进制显示会看到乱码。例程里通常有 BCD 转十进制和十进制转 BCD 的函数读出来先转换再显示。这个坑很隐蔽现象是时间跳得不对原因就是没做 BCD 转换。4.4 主循环把三个功能拼在一起主循环里做三件事扫描按键、根据当前模式决定显示什么、每隔一段时间刷新数据。下面是一个简化的框架。unsigned char mode 0; // 0 显示时间1 显示温度 void main() { lcd_init(); ds1302_init(); while (1) { if (key_pressed()) { mode !mode; // 按键切换模式 lcd_write_cmd(0x01); // 清屏准备重画 } if (mode 0) { show_time(); } else { show_temp(); } delay(30000); // 简单延时控制刷新速度 } }这个框架很粗糙但能跑。你按一下键屏幕从时间切到温度再按一下切回来。delay(30000)是为了让屏幕不要刷新太快导致闪烁实际项目中会用定时器中断来做但入门阶段先用延时把逻辑跑通。5. 新手最容易翻车的几个地方避坑与排查5.1 屏幕亮但没字或者只有黑方块现象背光亮了但看不到任何字符或者第一行全是黑色方块。原因V0 对比度电压不对或者初始化命令没发成功。解决先调电位器从一端慢慢拧到另一端看字是否出现。如果怎么调都不行检查 RS、E、数据线是否接错尤其是数据线顺序有没有反。用万用表测一下单片机 IO 在写数据时有没有变化。5.2 显示乱码或只显示第一个字符现象屏幕上出现奇怪的符号或者只显示“H”后面就没了。原因时序太快LCD1602 还没处理完上一个字节你就发了下一个。解决在lcd_write_cmd和lcd_write_data里把延时加大比如delay(500)。如果用的是 4 位模式检查是不是先发高四位再发低四位顺序不能错。5.3 DS18B20 读出来永远是 85 或 0现象温度值不变一直是 85 或者 0。原因85 是 DS18B20 上电默认值说明转换命令没发出去或者等待时间不够。0 通常是读时序不对读回来的全是 0。解决检查启动转换后有没有等够 750 毫秒。用示波器看数据线有没有正确的复位脉冲和读写脉冲。如果没有示波器就把读到的原始字节显示在 LCD 上看看到底读回了什么。5.4 DS1302 时间不走或跳变现象秒数不动或者分钟突然跳好几分钟。原因晶振没起振或者 BCD 转换写错了。解决DS1302 需要 32.768kHz 晶振检查晶振是否焊好负载电容是否匹配。读出来的时间先不做任何转换直接显示十六进制看看是不是 BCD 码。如果是就加转换函数。5.5 按键按一次跳好几下现象按一下键模式切换了好几次。原因按键抖动没消干净或者松手检测没做。解决把消抖延时加长到 20 毫秒并且在确认按下后等待松手再返回。如果主循环里还有其他耗时操作考虑用定时器中断扫描按键避免死等。6. 下一步学什么从能显示到能控制你现在已经能让屏幕显示固定字、显示变量、显示传感器数据也能用按键切换页面。这个例程跑通之后下一步不是去学更复杂的屏幕而是把现有的东西用得更稳。第一把延时换成定时器。你现在用的delay是空循环它会阻塞程序导致按键反应迟钝、时间显示不准。用定时器 0 或定时器 1 产生 1 毫秒中断在中断里做按键扫描和时间刷新主循环只负责显示。这是从“能跑”到“好用”的关键一步。第二把显示内容做成菜单。现在只有两个模式你可以扩展成三级菜单主菜单显示时间按一下进入温度再按一下进入设置设置里可以调时间。菜单结构用数组和状态机实现不要用一堆 if-else 堆在一起。第三把数据存起来。DS1302 有电池掉电时间不丢。但你的温度数据掉电就没了。可以学 24C02 这类 EEPROM把最高最低温度记录下来上电后显示。这样你的小系统就有了“记忆”。第四把通信协议整理成独立的文件。现在所有代码可能都在一个 .c 文件里你可以把 LCD1602、DS18B20、DS1302 的驱动分别写成 .c 和 .h主文件只调用接口。这是工程化的第一步也是后面做更大项目的基础。我自己的习惯是每学一个新外设就把它单独写成一个最小工程只做一件事让它工作并显示在 LCD 上。等所有外设都能单独跑了再拼在一起。这样出问题的时候你能快速定位是哪个模块的事。从那以后我每次调新模块都强制先写一个只显示原始数据的测试程序确认通信没问题再去做业务逻辑。希望这个路径能帮到你别急着一次写完先让屏幕亮出第一个字。本文还有配套的精品资源点击获取