前言
趁机把LCD 1602的实验完成了,那个电路图有几个地方没弄懂,但是去掉也没有报错,就没管了。
LCD1602_百度百科 (baidu.com)https://baike.baidu.com/item/LCD1602/6014393?fr=ge_ala
LCD1602液晶显示屏通过电压来改变填充在两块平行板之间的液晶材料内部分子的排列状况,以达到遮光和透光的目的来显示深浅不一,错落有致的图像。而且只要在两块平板间再加上三元色的滤光层,就可实现显示。
液晶是具有流动特性的物质,所以只需外加很微小的力量即可使液晶分子运动。以最常见普遍的向列型液晶为例,液晶分子可轻易的借着电场作用使得液晶分子转向,由于液晶的光轴与其分子轴相当一致,故可借此产生光学效果。当加于液晶的电场移除消失时,液晶将借着其本身的弹性及黏性,液晶分子将十分迅速的回撤销来未加电场前的状态。
“16”表示液晶显示模块每行可显示16个字符,“02”表示显示2行。
基础操作参考下面的这篇文章:
LED数码管的静态显示与动态显示(Keil+Proteus)-CSDN博客https://blog.csdn.net/weixin_64066303/article/details/134101256?spm=1001.2014.3001.5501
Keil
要注意的是Sbit RS=P2^2;
符号"^"前面是特殊功能寄存器的名字,“^”后面的数字定义的可寻址位在特殊功能寄存器中的位置。
LCD 1602的命令字
命令 | RS | R/~W | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
清屏 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
光标返回 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | X |
显示模式设置 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | I/D | S |
显示开/关及光标设置 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | D | C | B |
光标或字符移位 | 0 | 0 | 0 | 0 | 0 | 1 | S/C | R/L | X | X |
功能设置 | 0 | 0 | 0 | 0 | 1 | DL | N | F | X | X |
CGROM地址设置 | 0 | 0 | 0 | 1 | 字符库ROM地址 | |||||
DDRAM地址设置 | 0 | 0 | 1 | 显示数据RAM地址 | ||||||
读忙标志或地址 | 0 | 1 | BF | 计数器地址 | ||||||
写数据 | 1 | 0 | 要写的数据 | |||||||
读数据 | 1 | 1 | 读出的数据 |
LCD 1602的读写操作规定如下
单片机发给LCD 1602 的控制信号 | LCD 1602 的输出 | |
读状态 | RS=0,R/~W=1,E=1 | D0~D7=状态字 |
写命令 | RS=0,R/~W=0,D0~D7=命令,E=正脉冲 | 无 |
读数据 | RS=1,R/~W=1,E=1 | D0~D7=数据 |
写数据 | RS=1,R/~W=0,D0~D7=数据,E=正脉冲 | 无 |
我这里取消了光标右移,是直接打印出来的.
第一行字符的地址为80H~8FH.
第二行字符的地址为C0H~CFH.
#include<reg51.h>
#include<intrins.h> //包含_nop_()空函数指令的头文件
#define uchar unsigned char
#define uint unsigned int
#define out P0
sbit RS=P2^0;//位变量
sbit RW=P2^1;//位变量
sbit E=P2^2;//位变量
//函数声明部分
void lcd_initial(void);//LCD初始化函数
void check_busy(void);//检查忙标志位函数
void write_command(uchar com);//写命令函数
void write_data(uchar dat);//写数据函数
void string(uchar ad,uchar *s);//显示字符串
void delay(uint);//延时
void main(void){
lcd_initial();//对LCD初始化
while(1){
string(0x83,"I LOVE YOU");//显示第一行的字符
string(0xC4,"FOREVER");//显示第二行的字符
delay(100);//延时
write_command(0x01);//清屏
delay(100);//延时
}
}
//延时
void delay(uint j){
uchar i=250;
for(;j>0;j--){
while(--i);
i=249;
while(--i);
i=250;
}
}
//检查忙标志
void check_busy(void){
uchar dt;
do{
dt=0xff;//dt为变量单元,初值为0xff
//RS=0,E=1时才可以读忙标志位
E=0;
RS=0;
RW=1;
E=1;
dt=out;//out为P0口,P0口的状态送入dt中
}while(dt&0x80);//如果忙标志位BF=1,继续循环检测,等待BF=0
E=0;//BF=0,LCD 1602不忙,结束检测
}
//写命令
void write_command(uchar com){
check_busy();
//按规定RS和E同时为0时,才可以写命令
E=0;
RS=0;
RW=0;
out=com;//将命令com写入P0口
E=1;//写命令时,E应为正脉冲,即正跳变,所以前面先置E=0
_nop_();//空操作1个机器周期,等待硬件反应
E=0;//E由高电平变为低电平,LCD 1602开始执行命令
delay(1);//延时,等待硬件反应
}
//写数据
void write_data(uchar dat){
check_busy();//检测忙标志位BF=1则等待,若BF=0,则可对LCD 1602写入命令
E=0;//按规定写数据时,E应为正脉冲,所以先置E=0
//按规定RS=1和RW=0时,才可以写入数据
RS=1;
RW=0;
out=dat;//将数据”dat“从P0口输出,即写入LCD 1602
E=1;//E产生正跳变
_nop_();//空操作1个机器周期,等待硬件反应
E=0;//E由高电平变为低电平,写数据操作结束
delay(1);
}
//液晶显示器初始化函数
void lcd_initial(void){
write_command(0x38);//8位两行显示,5*7点阵字符
_nop_();//空操作1个机器周期,等待硬件反应
write_command(0x0C);//开整体显示,光标关,无闪烁
_nop_();//空操作1个机器周期,等待硬件反应
//write_command(0x05);//光标右移
_nop_();//空操作1个机器周期,等待硬件反应
write_command(0x01);//清屏
delay(1);
}
//输出显示字符串
void string(uchar ad,uchar *s){
write_command(ad);
while(*s>0){
write_data(*s++);//输出字符串,且指针增1
delay(100);
}
}
Proteus
所需器件
元件名称 | Proteus关键字 |
51单片机 | AT89C51 |
复位按钮 | BUTTON |
电容 | CAP |
电解电容 | CAP-ELEC |
晶体振荡器 | CRYSTAL |
字符型LCD 1602显示器 | LM016L |
滑动变阻器 | POT-HG |
电阻 | RES |
排阻 | RESPACK-8 |
运行结果
参考链接
Proteus-51单片机-LCD1602液晶显示DS1302实时时钟_51单片机lcd1602显示时间_爱上电路设计的博客-CSDN博客https://blog.csdn.net/liht_1634/article/details/131524016一、51单片机 使用Proteus掌握LCD1602显示屏的使用(仿真及代码)_51单片机1602显示汉字-CSDN博客https://blog.csdn.net/m0_47235364/article/details/128294254STC89C51基础及项目第10天:LCD显示字符(非标协议外设)-CSDN博客https://blog.csdn.net/Jaci133/article/details/133429036[89C51单片机]LCD1602静态显示-CSDN博客https://blog.csdn.net/zitech/article/details/9200203【精选】【常用传感器】LCD1602液晶工作原理详解及例程代码_lcd1602工作原理-CSDN博客https://blog.csdn.net/as480133937/article/details/113148712
总结
基本上就是按照书上来了,也没有什么技巧,简单记录一下吧。