
简介面向单片机与嵌入式初学者的《字符LCD液晶显示和接口.pptx》专业课件系统讲解字符型LCD以1602为例的显示原理、引脚定义及与51单片机的接口方法。内容从液晶的扭曲向列效应入手说明LCD低功耗、信息量大、寿命长等优势并围绕直接访问与间接控制两种方式详细分析AT89C51与LM016L连接时的数据线、ALE、RS、R/W、E等信号作用以及写命令、读状态、写数据、读数据四类基本操作。课件还给出读忙标志的查询程序段和完整接口电路图可帮助理解时序配合与初始化流程。资源包共1个文件为28页PPT演示文稿大小约451KB结构紧凑既适合教师课堂讲授也便于学生课后对照电路图自学。已有68人学习下载可作为单片机接口技术章节的配套课件。1. 一块 35 年前的屏凭什么是现在的教科书常客在嵌入式显示方案已经卷到 TFT 触摸的今天1602 字符液晶却依旧是单片机课程和工业仪表里的常客。它不发光靠电场驱动液晶分子扭转来控制光线通过它没有显存和字库加速器只有一颗与 HD44780 兼容的控制器在管理两行 16 列字符它只有 14 或 16 个引脚却能稳定输出字母、数字和自定义符号。这块屏真正值钱的地方在于把“被动显示原理—引脚接口定义—总线访问方式—控制时序—初始化命令字”这条技术链路完整串了起来。拆透 1602等于同时搞懂了字符型外设的通用控制模型。下面按照教学课件的主线从物理原理讲到驱动代码再落到实际排错。2. LCD 显示原理与字符模块的内部结构2.1 扭曲向列效应不加电时亮加了电反而暗LCD 的核心材料是介于固态和液态之间的液晶1602 模块里使用的是向列相液晶。液晶盒的两侧各有一层偏振方向相差 90° 的偏光片未加电场时液晶分子在基板间自发排列成 90° 扭曲结构。自然光穿过第一层偏光片变成线偏振光经过液晶分子层的扭转后偏振方向恰好旋转 90°刚好能穿过第二层偏光片所以人眼看到的是亮区域。当两片玻璃之间的电极加上电压液晶分子沿电场方向重新取向扭曲结构被破坏线偏振光不再能被第二层偏光片输出这个像素点变暗。也就是说LCD 的驱动电压控制的是“透光还是遮光”而不是“发光还是熄灭”。外部光照越强反射型液晶屏的对比度反而越高这也是许多户外工控设备至今坚持用 LCD 的原因。功耗方面1602 模块连同背光典型工作电流在 2 mA 量级对电池供电的便携仪表非常友好。字符显示的本质是把 ASCII 码交给模块内部的控制器控制器再到内置字库中检索对应的 5×7 点阵。用户可以自定义的字形放在 CGRAM字符发生器 RAM中CGRAM 最多容纳 8 个自定义字符。显示字符时单片机写入的是字符编号而不是点阵数据本身这就是字符型 LCD 比点阵图形屏省 MCU 资源的原因。2.2 笔段型、字符型、点阵图形型的选型边界LCD 按显示类型分三档选型逻辑不能只看价格。笔段型 LCD 的显示内容出厂时就固定了每个段位对应一段导电图形驱动方式就是控制段电极的电压。计算器、数字电表和电子钟是典型场景成本极低但没有灵活性。字符型 LCD 内部集成了控制器和字库单片机只需要写字符编码模块负责把编码翻译成点阵并在指定窗口渲染。1602 和 2004 是代表规格。点阵图形型 LCD 没有字库DDRAM 直接映射屏幕上的每个像素点能画曲线和汉字但需要外部提供字模数据对 RAM 和总线的压力大得多。类型典型规格内容灵活性驱动成本典型场景笔段型计算器屏固定笔段引脚直驱仪表、电子钟字符型1602、2004ASCII 自定义字模控制器寻址设备状态显示点阵图形型12864、320240逐像素绘点字模软件 大量 RAM曲线、汉字界面在需要显示一屏参数和状态的场景里字符型 LCD 的显示效率是最高的——MCU 不需要维护每个像素的状态写一个字节就是一个字符。点阵图形屏虽然灵活但在低速 51 单片机上频繁搬运显存反而拖累主循环。因此充电桩、医疗设备和工业仪表中最常见的依然是字符型。2.3 1602 模块的存储映射与坐标计算1602 模块内部维护了三块存储区。DDRAM显示数据 RAM存放当前屏幕显示的字符编码第一行地址从 0x00 到 0x0F第二行从 0x40 到 0x4FCGRAM 允许用户自定义 8 个 5×7 点阵字符地址 0x00 到 0x07CGROM 内置 ASCII 字库包括英文字母、数字和常用符号。这里最容易踩坑的是 DDRAM 地址与屏幕行列不是连续对应。第二行起始地址并非 0x10而是 0x40定位第二行第三列时需要发送0x80 0x40 0x02 0xC2。starter 写字符串前必须先用定位命令把地址计数器移动到位。/* 定位到指定行列row: 0 或 1col: 0~15 */ void lcd_gotoxy(unsigned char row, unsigned char col) { unsigned char addr; if (row 0) { addr 0x80 col; } else { addr 0xC0 col; } lcd_w_cmd(addr); }这段代码里0x80和0xC0是 DDRAM 地址设置命令的标志位。命令字的最高位 D7 为 1 时控制器把低 7 位解释为 DDRAM 地址。如果漏掉基准地址或者把第二行直接写成0x80 col字符会显示在第一行对应位置而不是期望的第二行。这种错误编译器不会报错只能靠观察屏幕现象来判断。3. 51 单片机与 1602 的硬件接口与访问方式3.1 十六引脚定义与最小系统连接1602 模块对外接口分两种无背光时用 14 Pin带 LED 背光时用 16 Pin。多出来的两个引脚是 A背光阳极和 K背光阴极。讲接口设计必须先把每个引脚的功能边界说清楚。引脚号符号方向功能说明1VSS电源地GND2VDD电源5V 电源输入3VO输入液晶驱动偏压决定对比度4RS输入寄存器选择0命令/状态1数据5R/W输入读写选择0写1读6E输入使能信号下降沿锁存数据7~14DB0~DB7双向8 位数据总线15A输入背光 LED 阳极16K输入背光 LED 阴极RS、R/W、E 三条控制线的电平组合决定数据总线上内容被如何解释。这套逻辑是整个驱动软件的基础初始化、读忙状态、写显示数据三个操作的本质区别就是这三根线的状态不同。VO 引脚的接法同样关键。通常在 VDD 与 VSS 之间串联一个 10k 电位器中间抽头接 VO。偏压太高屏幕全黑太低显示几乎看不见。拿到新屏后第一步应是旋转电位器确认可视范围而不是急着改代码。### 3.2 直接访问方式把 LCD 当成总线上的存储器 单片机与 LCD 的访问方式分两类。直接访问方式是把液晶模块当作存储器或 I/O 设备直接挂到单片机总线上。AT89C51 的 P0 口作为地址/数据复用总线经 74LS373 锁存低 8 位地址P2 口提供高 8 位地址RD 和 WR 信号直接连到 LCD 的 R/W 引脚RS 则通过地址线的最低一位来区分命令与数据。 采用直接访问方式时写命令和写数据在 C 语言里表现为对两个不同地址的赋值 c #define LCD_CMD_PORT XBYTE[0x8000] /* A00选中命令寄存器 */ #define LCD_DATA_PORT XBYTE[0x8001] /* A01选中数据寄存器 */ void lcd_write_cmd(unsigned char cmd) { LCD_CMD_PORT cmd; } void lcd_write_data(unsigned char dat) { LCD_DATA_PORT dat; }两个地址共享同一条数据总线差异仅在地址线 A0 上。访问0x8000时 A0 为低电平RS0控制器收到的是命令字访问0x8001时 A0 为高电平RS1数据被写入数据寄存器。直接访问的优势是写一条指令只需一次 MOVX 周期速度最快代价是占用外部总线需要地址译码逻辑电路复杂度明显上升。3.3 间接控制方式并行口模拟时序比直接访问更常用的是间接控制方式。LCD 作为终端设备连接到单片机的并行口上数据线接 P1 口RS、R/W、E 分别接 P3 口的三根线。这种方式不涉及总线仲裁也没有地址译码电路最简单代价是每次读写都要用软件模拟时序速度略慢。sbit LCD_RS P3^4; sbit LCD_RW P3^5; sbit LCD_E P3^6; #define LCD_DATA P1 void lcd_delay(void) { unsigned char i 20; while (i--); }sbit是 Keil C51 中定义位变量的关键字编译后映射到 SFR 的位地址引用LCD_RS时实际操作的是 P3 口的第 4 位。数据口用宏定义而不是sbit因为 8 位并行总线无法用单个 bit 表示。lcd_delay()的作用是保证控制线电平稳定后再切换下一根线。注意如果数据线接在 P0 口上必须外接 10k 上拉排阻。P0 口内部是开漏结构不加上拉电阻时高电平输出能力不足LCD 数据线上的高电平会飘读回来的状态字随机跳变最典型的表现就是卡在忙标志查询里出不来。P1、P2、P3 口内部有上拉可以直接接数据线。4. 忙标志查询与初始化命令字的完整拆解4.1 RS、R/W 真值表与四条基本操作单片机控制 1602 的本质是执行四类操作写命令、读状态、写数据、读数据。这几类操作的区别完全体现在 RS 和 R/W 的电平组合上E 引脚负责锁存时机。RSR/W操作类型数据线含义00写命令初始化、清屏、光标定位01读状态最高位 BF 忙标志低 7 位地址计数器10写数据要显示字符的编码11读数据DDRAM/CGRAM 中已存内容E 引脚的作用是时序同步。先设置 RS 和 R/W 的状态再在数据线上放数据最后拉高 E 产生脉冲数据在 E 的下降沿被控制器锁存。顺序反了或者 E 高电平持续时间不够都会导致数据丢失。4.2 读状态操作与忙标志查询LCD 上电后并不立即就绪控制器内部需要进行复位和初始化。为此 HD44780 兼容芯片设计了忙标志机制状态字最高位 BF 为 1 表示控制器正在处理内部事务为 0 表示可以接收下一条指令。标准驱动都会在每次写命令前先查询忙标志。/* 读状态字函数返回状态字D71 表示忙D70 表示空闲 */ unsigned char lcd_r_start(void) { unsigned char s; LCD_RW 1; /* 读方向 */ LCD_RS 0; /* 读状态寄存器 */ lcd_delay(); LCD_E 1; /* E 高电平期间数据有效 */ lcd_delay(); s LCD_DATA; /* 从 P1 口读取状态字 */ lcd_delay(); LCD_E 0; /* 下降沿结束本次操作 */ lcd_delay(); LCD_RW 0; return s; } /* 查询忙标志LCD 忙则一直等待 */ void lcd_wait_busy(void) { unsigned char stat; do { stat lcd_r_start(); stat 0x80; /* 屏蔽低 7 位只保留 BF */ } while (stat ! 0); }lcd_r_start()返回的完整状态字包含 BF 和地址计数器 AC 的值。stat 0x80这一步必不可少如果不做掩码读回来的低 7 位地址值会参与判断while循环可能因 AC 的随机值而提前退出或永远等待。另一个等价写法是while (stat 0x80)。读状态下 E 线上的脉冲宽度需要足够长。12 MHz 晶振的 51 单片机一条指令约 1 μslcd_delay()循环几十次完全满足 HD44780 对 E 高电平不低于 230 ns 的要求。但如果换成 1T 的 STC 单片机空循环的延时可能缩到几十纳秒就需要加大循环次数或插入_nop_()。4.3 写命令操作与命令字位拆解写命令的过程是查询忙标志确认空闲后拉低 R/W 置为写方向拉低 RS 选中命令寄存器放上命令字拉高 E 产生锁存脉冲。课件中的lcd_w_cmd实现就是一个标准模板。void lcd_w_cmd(unsigned char com) { lcd_wait_busy(); /* 先确认控制器空闲 */ LCD_RW 0; /* 写方向 */ LCD_RS 0; /* 命令寄存器 */ lcd_delay(); LCD_E 1; lcd_delay(); LCD_DATA com; /* 命令字放到数据总线 */ lcd_delay(); LCD_E 0; /* 下降沿锁存数据 */ lcd_delay(); LCD_RW 1; /* 恢复默认电平 */ }LCD_RW 1放在函数末尾不是多余代码。有些模块在读模式下数据线是输出驱动的RW 拉高后能防止总线悬空带来的不确定电平干扰后续操作。4.4 初始化命令序列为何是 0x3C、0x0E、0x01、0x06、0x80LCD 上电时必须按固定流程初始化设置接口数据位数、显示行数、字型、光标、输入方式等。课件给出的顺序是典型的五步初始化void lcd_init(void) { lcd_w_cmd(0x3C); /* 00111100B: 8位总线、2行显示、5×10字型 */ lcd_w_cmd(0x0E); /* 00001110B: 开显示、光标显示、字符不闪烁 */ lcd_w_cmd(0x01); /* 00000001B: 清屏、光标回归左上角 */ lcd_w_cmd(0x06); /* 00000110B: 增量方式右移显示不移动 */ lcd_w_cmd(0x80); /* 10000000B: DDRAM 地址设为第一行第一列 */ }逐条拆解命令字的每一位。0x3C高四位为0011表示工作方式设置指令DL1 选择 8 位数据总线N1 表示两行显示F1 选 5×10 点阵字型。如果改用0x38F 变为 0 对应 5×7 点阵这是 1602 上更常见也更省控制器的配置。0x0E是显示状态设置D1 开显示、C1 显示光标、B0 字符不闪烁。正式产品里通常会发0x0C把光标隐藏。0x01清屏会把 DDRAM 全部写空格地址计数器归零整个过程约 1.6 ms。0x06设置输入方式I/D1 表示每写一个字符光标自动右移S0 表示整体显示不滚动。0x80设置 DDRAM 地址到第一行第一列因命令字最高位为 1第二行首列对应0xC0。4.5 写数据操作与字符串输出初始化完成后写显示数据与写命令的差异只有 RS 电平。想把字符串显示在指定位置需要先定位再逐个写入字符编码。void lcd_putstr(unsigned char row, unsigned char col, unsigned char *str) { lcd_gotoxy(row, col); while (*str ! \0) { lcd_wait_busy(); /* 每个字符写入前都查忙 */ LCD_RW 0; LCD_RS 1; /* 与写命令唯一区别RS1 */ lcd_delay(); LCD_E 1; lcd_delay(); LCD_DATA *str; lcd_delay(); LCD_E 0; lcd_delay(); } }*str同时完成取值和指针后移等价于*str加str两条语句。每个字符写入前都查询忙标志是因为控制器需要把字符编码翻译成 5×7 点阵并搬运到 DDRAM这一过程约几十微秒不等待就连续写入后面的字符会被丢弃。显示汉字时写入的不是汉字编码而是 CGRAM 中的自定义字符编号 0x00 到 0x07。5. 屏不亮、乱码、定位错乱三级排查路径5.1 供电与偏压检查新板子拿到手不要急着烧程序。先用万用表确认 VDD 对 VSS 电压在 4.55.5V 之间。然后把电位器从一端旋到另一端正常时屏幕上能看到一行或两行的底色变化。全黑说明偏压过高降低 VO 电压完全无反应先查背光 A-K 是否点亮。这一步能把“电气问题”和“驱动问题”分开。5.2 时序波形与忙标志死循环用示波器探头夹在 E 引脚上跑初始化代码正常能看到一串脉冲。如果只出现第一个脉冲就停了几乎可以断定程序卡在lcd_wait_busy()的while循环里。常见原因是数据线某一位接触不良读回来的状态字不是 0x10 就是 0xFF。此时用万用表逐个量 DB0-DB7 到单片机引脚的连通性重点检查排针虚焊。还有一种隐蔽情况LCD 数据线长时间处于输入模式时P1 口被其他外设复用读状态字会混入外部信号。因此在lcd_wait_busy()前后不应进行其他端口操作必要的话用临时变量保存状态字后再释放数据线。5.3 初始化参数与字型选择的验证把0x3C换成0x38重新烧录如果显示正常说明问题出在 5×10 与 5×7 字型选择上。部分兼容控制器对 5×10 字型的支持不完整会表现为第二行无法显示或光标错位。另外0x01清屏后最好加 2 ms 延时再继续虽然前面有lcd_wait_busy()查询但部分控制器在清屏完成后 AC 更新有延迟直接发下一条定位命令可能被忽略。验证整体功能的测试序列void lcd_selftest(void) { lcd_init(); lcd_putstr(0, 0, 0123456789ABCDEF); lcd_putstr(1, 0, LCD-1602 I/F OK); while (1); }如果第一行完整显示 16 个字符、第二行正常显示说明数据线、控制线和初始化参数全部正确。若第二行出现乱码优先检查lcd_gotoxy中第二行地址是否加了0x40若两行内容都偏右检查lcd_w_cmd(0x80 col)中的基准地址是否被覆盖。定位命令中最高位 D7 必须是 1写入低 7 位地址时不能把0x80丢掉这是字符型 LCD 驱动中最容易踩的一个坑。本文还有配套的精品资源点击获取