除此之外, 这篇博客: LCD1602液晶显示屏在51单片机上的使用中的 LCD1602液晶显示屏在51单片机上的使用 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
以下是我在学习使用51单片机时的心得体会,在这里记录我的学习历程,本文使用的教程的代码,如果有侵权的可能,请告知。
LCD1602液晶屏是我购买的普中51单片机自带的外设之一,学习这一款液晶屏的使用不仅仅在于学习这块液晶屏,更是学习一种连接外设的方式。
这一款液 晶屏的屏幕有两行,每一行都有一定的格子去装写入的字符,这个格子的大小可以选择,有5X7和5X10两个选择。
以下是1602的引脚说明摘录:

在以后的程序中,BLA和BLK这两个东西没有接触到,VL这个东西是拿来调整1602的亮度的,VSS和VDD不用多说,是不需要用软件来操作的,剩下的部分就是变成要注意的地方。
首先介绍1602的几个关键性指令:
- 清屏

如图所示,开头两位都是0,这显示了,这是一个命令选择端,并且为写选择端。
即将 DDRAM 的内容全部填入"空白"的 ASCII码 01H; 并且光标归位,将地址计数器AC的值设为0.
- 进入模式设置指令

功能 : 设定每次定入 1 位数据后光标的移位方向 , 并且设定每次写入的一个字符是否移动。参数设定的情况如下所示:
位名 设置
I/D 0=写入新数据后光标左移 1=写入新数据后光标右移
S 0=写入新数据后显示屏不移动 1=写入新数据后显示屏整体右移 1 个字符
(至于显示屏右移,下文会详细说明)
- 显示开关控制指令

功能:控制显示器开/关、光标显示/关闭以及光标是否闪烁。参数设定的情况如下:
位名 设置
D 0=显示功能关 1=显示功能开
C 0=无光标 1=有光标
B 0=光标闪烁 1=光标不闪烁
- 功能设定指令

功能:设定数据总线位数、显示的行数及字型。参数设定的情况如下:
位名 设置
DL 0=数据总线为 4 位 1=数据总线为 8 位 (我用的普中51单片机是默认8位的)
N 0=显示 1 行 1=显示 2 行
F 0=5×7 点阵/每字符 1=5×10 点阵/每字符
在设置完成之后我们就要明白具体是在哪显示,在哪个位置显示?在对液晶模块的初始化中要先设置其显示模式, 在液晶模块显示字符时光标是自动右移的, 无需人工干预。 每次输入指令前都要判断液晶模块是否处于忙的状态。DDRAM 就是显示数据 RAM ,用来寄存待显示的字符代码。共 80 个字节,其地址和屏幕的对应关系如下表:

这里要注意一下,80个字节,不是每一个都可以出现在屏幕上的,一般来说,出现的只有8*2行,即16个字节,其余的字节是存在的,而且可以存储数据,让他们出来,需要用到显示屏移动的指令。
要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符,例如第二行第一个字符的地址是 40H, 那么是否直接写入 40H 就可以将光标定位
在第二行第一个字符的位置呢?这样不行,因为写入显示地址时要求最高位 D7
恒定为高电平 1 所以实际写入的数据应该是 01000000B(40H)
+10000000B(80H)=11000000B(C0H)。
(总之全部地址都加上80H就对了)
前面16个字节的地址如下:

以下是操作步骤:
1602的基本操作
①读状态:RS=0,RW=1,E=高脉冲。输出:D0~D7为状态字。
②读数据:RS=1,RW=1,E=高脉冲。输出:D0~D7为数据。
③写指令:RS=0,RW=0,E=高脉冲。输出:无
④写数据:RS=1,RW=0,E=高脉冲。输出:无。
初始化:根据硬件约定对1602进行启动设置。
写命令(RS=L)设置显示坐标
写数据(RS=H)
操作的具体步骤(代码怎么写):
首先用一个h文件写下所有的函数定义和变量如下:
#ifndef __LCD_H_
#define __LCD_H_
/**********************************
当使用的是4位数据传输的时候定义,
使用8位取消这个定义
**********************************/
//#define LCD1602_4PINS
/**********************************
包含头文件
**********************************/
#include<reg51.h>
//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
/**********************************
PIN口定义
**********************************/
#define LCD1602_DATAPINS P0
sbit LCD1602_E=P2^7;
sbit LCD1602_RW=P2^5;
sbit LCD1602_RS=P2^6;
//普中赠送的开发板原理图有关于使用管脚的说明。
/**********************************
函数声明
**********************************/
/*在51单片机12MHZ时钟下的延时函数*/
void Lcd1602_Delay1ms(uint c); //误差 0us
/*LCD1602写入8位命令子函数*/
void LcdWriteCom(uchar com);
/*LCD1602写入8位数据子函数*/
void LcdWriteData(uchar dat) ;
/*LCD1602初始化子程序*/
void LcdInit();
#endif
然后是c文件进行函数的各种定义,包括初始化等函数
#include "lcd.h"
/*******************************************************************************
* 函 数 名 : Lcd1602_Delay1ms
* 函数功能 : 延时函数,延时1ms
* 输 入 : c
* 输 出 : 无
* 说 名 : 该函数是在12MHZ晶振下,12分频单片机的延时。
*******************************************************************************/
void Lcd1602_Delay1ms(uint c) //误差 0us
{
uchar a,b;
for (; c>0; c--)
{
for (b=199;b>0;b--)
{
for(a=1;a>0;a--);
}
}
}
/*******************************************************************************
* 函 数 名 : LcdWriteCom
* 函数功能 : 向LCD写入一个字节的命令
* 输 入 : com
* 输 出 : 无
*******************************************************************************/
#ifndef LCD1602_4PINS //当没有定义这个LCD1602_4PINS时
void LcdWriteCom(uchar com) //写入命令
{
LCD1602_E = 0; //使能
LCD1602_RS = 0; //选择发送命令
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = com; //放入命令
Lcd1602_Delay1ms(1); //等待数据稳定
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5); //保持时间
LCD1602_E = 0;
}
#else //因为普中51单片机默认是8字节通道,所以上面的函数无效,直接跳入下方的函数
void LcdWriteCom(uchar com) //写入命令
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 0; //选择写入命令
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = com; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
LCD1602_DATAPINS = com << 4; //发送低四位
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 数 名 : LcdWriteData
* 函数功能 : 向LCD写入一个字节的数据
* 输 入 : dat
* 输 出 : 无
*******************************************************************************/
#ifndef LCD1602_4PINS
void LcdWriteData(uchar dat) //写入数据
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 1; //选择输入数据
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = dat; //写入数据
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5); //保持时间
LCD1602_E = 0;
}
#else
void LcdWriteData(uchar dat) //写入数据
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 1; //选择写入数据
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = dat; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
LCD1602_DATAPINS = dat << 4; //写入低四位
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 数 名 : LcdInit()
* 函数功能 : 初始化LCD屏
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
#ifndef LCD1602_4PINS
void LcdInit() //LCD初始化子程序
{
LcdWriteCom(0x38); //开显示
LcdWriteCom(0x0c); //开显示不显示光标
LcdWriteCom(0x06); //写一个指针加1
LcdWriteCom(0x01); //清屏
LcdWriteCom(0x80); //设置数据指针起点
}
#else
void LcdInit() //LCD初始化子程序
{
LcdWriteCom(0x32); //将8位总线转为4位总线
LcdWriteCom(0x28); //在四位线下的初始化
LcdWriteCom(0x0c); //开显示不显示光标
LcdWriteCom(0x06); //写一个指针加1
//这里说的指针加一其实有点模糊,不过应该指的是屏幕移动方向。
LcdWriteCom(0x01); //清屏
LcdWriteCom(0x80); //设置数据指针起点
}
#endif
剩下就是main.c文件的代码,引入之前的h和c文件,想显示什么,在Main文件中写入即可
/**************************************************************************************
* LCD1602液晶显示实验 *
实现现象:下载程序后插上LCD1602液晶在开发板上,即可显示
注意事项:如果不想让点阵模块显示,可以将74HC595模块上的JP595短接片拔掉。
***************************************************************************************/
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
#include "lcd.h"
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
u8 Disp[]=" Pechin Science ";
//如果要显示什么123456789,换一个数组就可以,不过要注意
//这个液晶屏显示的是字符类变量,如果使用的是int格式,要给它加上'0'.
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main(void)
{
u8 i;
LcdInit();
for(i=0;i<16;i++)
{
LcdWriteData(Disp[i]);
}
while(1);//这里的while是用来防止单片机关闭的,不然的话,几微妙的时间内单片机就运转完了。
}
最后是1602的原理图,看看就好,以后插外设的时候可以参考一下:
