单片机C语言实例:18、LCD1602液晶显示

 LCD1602的显示原理

学单片机的小朋友应该都见过这个显示器--LCD1602,这是最古老最简单的显示屏,上世纪80年代的产物。

它显示的图案如下所示

显示部分放大就是下面这样 ,像素就是一个个小方块,相当于描点法绘图了。

如果把所有像素全部显示出来就是下面这样,全部是小黑点

 全部点亮的像素点如下所示,16列,2行,这就是1602名字的来历

每个显示区域又可以细分为35个像素,7行5列

 整个屏幕就是35*16*2 = 1120个像素

要想搞清楚这1120个像素的控制,就得先明白一个像素是这么控制的。显示屏的最下面是一层LED背光板,

只要通上电就会发光

在背光板上铺上一层液晶,每一小块的液晶就可以控制一个像素点

当不给液晶施加电压,液晶就是透明的,给某一块液晶施加电压后,就不透光了,看到的就是一个小黑点,常见的LCD背光有白光、蓝光、绿光,所以大家一般看到的要么是黑点,要么是背光。控制像素点就是控制他所对应的液晶的电压高低。

数码管只有8段,8个IO口就够了,可以用单片机直接控制,但是LCD1602有1120个像素点,1120个引脚的单片机我还没遇到,怎么办?这时候显示芯片HD44780U可以出场了。44780有80个引脚

单片机把想要显示的东西发给HD44780U,HD44780U再来控制显示屏就可以

所以这个HD44780U就有点像电脑的显卡了。

LCD1602液晶屏的背面长这个样子,首先映入眼帘的就是那两个大黑点,大黑点里面封装的就是芯片,大的那个是HD44780U,小一点的那个黑点是HD44100H,他的作用后面会讲到。关于芯片的封装,大家可能都觉得芯片 就应该是哪种方形的,有引脚的哪种,其实还有一种COB的封装,就像狗皮膏药一样黏在PCB上,这种封装便宜啊。

LCD1602一共有16个引脚,其中数据引脚又8个,控制这8个引脚的数据,就能控制液晶屏的显示内容。因为每个显示区域就35个像素,描点法也只能描出简单的图案,比如数字,字面,符号等。

比如大些字母A,ASCII码表是0100 0001,对应的数据引脚电平就是:

0         1         0         0         0        0        0        1

低       高       低        低      低       低      低        高

但是这个A在哪个区域显示呢?HD44780U里面给每个显示区域都规定的地址,这个地址就存在芯片内部的DRAM里面,

 

  这个DRAM就相当于显卡的显存了,只是大小只有80个字节,可以同时控制80个字符

 

LCD1602最多也就能显示32个字符,HD44780U为什么能控制80个字符,因为他是通用的芯片,不是为LCD1602定制的,多的部分可以空着不用。

 后面的红色部分就是多余的地址,控制不用

 先发送显存的地址,再发送需要显示的内容,这样数据就会被保存在相应的显存里面

比如让液晶屏的第一块显示区域显示大些字母A,就先发送第一块显示区域的地址0x00,再发送A的ASCII码0100 0001,怎么显示那就是显示芯片HD44780U的事情了。

HD44780U的芯片管脚分布如下那些SEG和COM引脚就是控制引脚,是不是似曾相识,数码管的SEG引脚和COM引脚,原理可以说是差不多的。

 COM引脚控制行,SEG引脚控制列,如果要显示A,那就是在相应的交叉点输出不同的电压就行了

因为不能同时控制所有行列的电压,只能用扫描的方式,一行一行的控制,是不是也似曾相识,多为数码管的动态显示也是这样的。

扫描第一行,并输出对应的电压 

扫描第二行并输出对应的电压

扫描第三行并输出对应的电压

扫描第四行并输出对应的电压 

扫描第五行并输出对应的电压 

扫描第六行,并输出对应的电压

扫描第七行并输出对应的电压 

扫描快一点,根根人眼的视觉残留,就能看到完整的A了

 HD44780U的SEG引脚只有40个,5个SEG脚才能控制一列显示区,40个SEG脚一共也只能控制8列显示区啊,LCD1602可是有16列显示区的,那另外的8列的显示区怎么控制,而且前面也说了,HD44780U能控制80个字符,现在怎么才16个。对HD44780U的显存DRAM是可以控制80个字符,但是引脚不够啊,这个时候该HD44100H出场了。

HD44100H就是那个小一点的黑点

它正好也有40个SEG引脚

 将HD44780U和HD44100H拼在一起不就好了

 加4个HD44100H,换一个能显示80个字符的液晶显示屏,就能显示80个字符了,HD44780U里面的DRAM就只有80个地址,只能显示80个字符。

LCD1602相关的寄存器以及电路

 1、认识LCD

LCD == Liquid Crystal Display ==液晶显示器

LCD1602表示一种液晶屏,能同时显示2行16列,共32个字符,这个字符可以是字母,数字,符号等

LCD结构上主要由3部分组成:

液晶:液态晶体,液晶本身不发光,但他在通电的时候可以让光线透过去,不通电时光线透不过去;

光源:这个光源才是点亮LCD的关键;

偏光片:又上下两片,液晶就在上下偏光片之间,改变偏光片的角度就可以让光线在特定的地方透过

上下两片偏光片有点像两个石子交叉的百叶窗,自己去脑补一下。

2、LCD1602的管脚以及管脚功能

管脚序号

管脚符号

管脚说明

1

VSS

电源地,

2

VDD

电源正极,是LCD1602驱动系统的电源

3

VO

液晶显示对比度调整管脚,接正电源是对比度最低,接地时对比度最高,但是对比度太高,就容易看到一些不该看到的东西,俗称“鬼影”,一般在这个脚通过电阻再接地。

4

RS

Register Select的缩写,字面意思就是寄存器选择;当RS=1的时候,通讯的是数据;当RS=0的时候,通讯的是命令。

5

R/W

读,写选择,当R/W = 1的时候表示读LCD里面的数据,R/W = 0的时候表示往LCD里面写数据。

6

E

使能信号,当E=1的时候读取信息,当E由1变为0的时候,液晶模块开始执行命令;要配合控制时序来用。

7

D0

数据第0位,D0--D7是双向的数据线,对LCD模块进行读写。

8

D1

数据第1位

9

D2

数据第2位

10

D3

数据第3位

11

D4

数据第4位

12

D5

数据第5位

13

D6

数据第6位

14

D7

数据第7位

15

BLA

背光源正极,可以理解为那个背光LED的正极电源,可以直接接VDD

16

BLK

背光源负极,可以理解为那个背光LED的负极电源,可以直接接VSS

3、LCD1602 的RAM地址映射

LCD1602能同时显示2行16列,一共32个位置,每个位置都对应着一个地址,每个地址里面可以促一个字节的字符,需要在哪个位置显示某种字符,就在他对应的地址上写入某种字符。

下图就是这32个显示位置所对应的地址,这个地址也就是DDRAM地址;

其实LCD1602的DDRAM一共有80个地址,依然是两行,每行40个地址,但是LCD1602一行只能同时显示16个地址的数据,剩下的24个在后面隐藏着。怎么办,只能用光标移动的方法把隐藏的部分显示出来。

4、LCD1602的显示设置

比如你想在第1行,第3列的位置显示个字符A,该怎么处理?

首先确定位置,第1行第3列的地址是02,转换为2进制就是0000 0010,但是LCD1602有自己的规矩,就是写地址的时候,最高位必须是1,也就是说写进LCD的地址应该为1000 0010。

然后确定字符,LCD1602模块里面有个字符产生器,简称CGROM(Character Generator ROM)里面存着一些常用的字模,你只需要根据地址来查询就可以了,比如字符A的地址就是0x41。

5、LCD1602的命令列表

6、单片机控制LCD1602电路

 

LCD1602液晶静态显示

程序实例1:

#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include<intrins.h>

sbit RS = P2^4;   //定义端口 
sbit RW = P2^5;
sbit EN = P2^6;

#define RS_CLR RS=0 
#define RS_SET RS=1

#define RW_CLR RW=0 
#define RW_SET RW=1 

#define EN_CLR EN=0
#define EN_SET EN=1

#define DataPort P0

/*------------------------------------------------
 uS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
 长度如下 T=tx2+5 uS 
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{   
	while(--t);
}

/*------------------------------------------------
 mS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void DelayMs(unsigned char t)
{    
	while(t--)
	{
		//大致延时1mS
		DelayUs2x(245);
		DelayUs2x(245);
	}
}

/*------------------------------------------------
              判忙函数
------------------------------------------------*/
bit LCD_Check_Busy(void) 
{ 
	DataPort= 0xFF; 
	RS_CLR; 
	RW_SET; 
	EN_CLR; 
	_nop_(); 
	EN_SET;
	return (bit)(DataPort & 0x80);
}

/*------------------------------------------------
              写入命令函数
------------------------------------------------*/
void LCD_Write_Com(unsigned char com) 
{  
	while(LCD_Check_Busy()); //忙则等待
	RS_CLR; 
	RW_CLR; 
	EN_SET; 
	DataPort= com; 
	_nop_(); 
	EN_CLR;
}

/*------------------------------------------------
              写入数据函数
------------------------------------------------*/
void LCD_Write_Data(unsigned char Data) 
{ 
	while(LCD_Check_Busy()); //忙则等待
	RS_SET; 
	RW_CLR; 
	EN_SET; 
	DataPort= Data; 
	_nop_();
	EN_CLR;
}

/*------------------------------------------------
                清屏函数
------------------------------------------------*/
void LCD_Clear(void) 
{ 
	LCD_Write_Com(0x01); 
	DelayMs(5);
}

/*------------------------------------------------
              写入字符串函数
------------------------------------------------*/
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) 
{     
	if (y == 0) 
 	{     
		LCD_Write_Com(0x80 + x);     //表示第一行
 	}
	else 
 	{      
		LCD_Write_Com(0xC0 + x);      //表示第二行
 	}        
	while (*s) 
 	{     
		LCD_Write_Data( *s);     
		s ++;     
 	}
}

/*------------------------------------------------
              写入字符函数
------------------------------------------------*/
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) 
{     
	if (y == 0) 
 	{     
		LCD_Write_Com(0x80 + x);     
 	}    
	else 
 	{     
		LCD_Write_Com(0xC0 + x);     
 	}        
	LCD_Write_Data( Data);  
}

/*------------------------------------------------
              初始化函数
------------------------------------------------*/
void LCD_Init(void) 
{
	LCD_Write_Com(0x38);    /*显示模式设置*/ 
	DelayMs(5); 
	LCD_Write_Com(0x38); 
	DelayMs(5); 
	LCD_Write_Com(0x38); 
	DelayMs(5); 
	LCD_Write_Com(0x38);  
	LCD_Write_Com(0x08);    /*显示关闭*/ 
	LCD_Write_Com(0x01);    /*显示清屏*/ 
	LCD_Write_Com(0x06);    /*显示光标移动设置*/ 
	DelayMs(5); 
	LCD_Write_Com(0x0C);    /*显示开及光标设置*/
}
   
/*------------------------------------------------
                    主函数
------------------------------------------------*/ 
void main(void) 
{ 
	LCD_Init(); 
	LCD_Clear();//清屏
	while (1) 
	{  
		LCD_Write_Char(7,0,'o');
		LCD_Write_Char(8,0,'k');
		LCD_Write_String(1,1,"hello world!");
		while(1);
	}
}

LCD1602液晶动态显示

程序实例2:

#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include<intrins.h>

sbit RS = P2^4;   //定义端口 
sbit RW = P2^5;
sbit EN = P2^6;

#define RS_CLR RS=0 
#define RS_SET RS=1

#define RW_CLR RW=0 
#define RW_SET RW=1 

#define EN_CLR EN=0
#define EN_SET EN=1

#define DataPort P0
/*------------------------------------------------
 uS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
 长度如下 T=tx2+5 uS 
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{   
	while(--t);
}

/*------------------------------------------------
 mS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void DelayMs(unsigned char t)
{    
	while(t--)
	{
		//大致延时1mS
		DelayUs2x(245);
		DelayUs2x(245);
	}
}

/*------------------------------------------------
              判忙函数
------------------------------------------------*/
bit LCD_Check_Busy(void) 
{ 
	DataPort= 0xFF; 
	RS_CLR; 
	RW_SET; 
	EN_CLR; 
	_nop_(); 
	EN_SET;
	return (bit)(DataPort & 0x80);
}

/*------------------------------------------------
              写入命令函数
------------------------------------------------*/
void LCD_Write_Com(unsigned char com) 
{  
	while(LCD_Check_Busy()); //忙则等待
	RS_CLR; 
	RW_CLR; 
	EN_SET; 
	DataPort= com; 
	_nop_(); 
	EN_CLR;
}

/*------------------------------------------------
              写入数据函数
------------------------------------------------*/
void LCD_Write_Data(unsigned char Data) 
{ 
	while(LCD_Check_Busy()); //忙则等待
	RS_SET; 
	RW_CLR; 
	EN_SET; 
	DataPort= Data; 
	_nop_();
	EN_CLR;
}

/*------------------------------------------------
                清屏函数
------------------------------------------------*/
void LCD_Clear(void) 
{ 
	LCD_Write_Com(0x01); 
	DelayMs(5);
}

/*------------------------------------------------
              写入字符串函数
------------------------------------------------*/
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) 
{     
	if (y == 0) 
 	{     
		LCD_Write_Com(0x80 + x);     
 	}
	else 
 	{     
		LCD_Write_Com(0xC0 + x);     
 	}        
	while (*s) 
 	{     
		LCD_Write_Data( *s);     
		s ++;     
 	}
}

/*------------------------------------------------
              写入字符函数
------------------------------------------------*/
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) 
{     
	if (y == 0) 
 	{     
		LCD_Write_Com(0x80 + x);     
 	}    
	else 
 	{     
		LCD_Write_Com(0xC0 + x);     
 	}        
	LCD_Write_Data( Data);  
}

/*------------------------------------------------
              初始化函数
------------------------------------------------*/
void LCD_Init(void) 
{
	LCD_Write_Com(0x38);    /*显示模式设置*/ 
	DelayMs(5); 
	LCD_Write_Com(0x38); 
	DelayMs(5); 
	LCD_Write_Com(0x38); 
	DelayMs(5); 
	LCD_Write_Com(0x38);  
	LCD_Write_Com(0x08);    /*显示关闭*/ 
	LCD_Write_Com(0x01);    /*显示清屏*/ 
	LCD_Write_Com(0x06);    /*显示光标移动设置*/ 
	DelayMs(5); 
	LCD_Write_Com(0x0C);    /*显示开及光标设置*/
}
   
/*------------------------------------------------
                    主函数
------------------------------------------------*/ 
void main(void) 
{ 
	unsigned char i; 
	unsigned char *p; 

	LCD_Init(); 

	while (1) 
	{  
		i = 1;  
		p = "hello world!";  
		LCD_Clear();  
		LCD_Write_String(2,0,"Welcome to");  
		DelayMs(250);   
		while (*p) 
		{   
			LCD_Write_Char(i,1,*p);   
			i ++;   
			p ++;   
			DelayMs(250);   
		}  
		DelayMs(250);  
	}
}

LCD1602液晶滚动显示

程序实例3:

#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include<intrins.h>

sbit RS = P2^4;   //定义端口 
sbit RW = P2^5;
sbit EN = P2^6;

#define RS_CLR RS=0 
#define RS_SET RS=1

#define RW_CLR RW=0 
#define RW_SET RW=1 

#define EN_CLR EN=0
#define EN_SET EN=1

#define DataPort P0

/*------------------------------------------------
 uS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
 长度如下 T=tx2+5 uS 
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{   
	while(--t);
}

/*------------------------------------------------
 mS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void DelayMs(unsigned char t)
{
     
	while(t--)
	{
		//大致延时1mS
		DelayUs2x(245);
		DelayUs2x(245);
	}
}

/*------------------------------------------------
              判忙函数
------------------------------------------------*/
bit LCD_Check_Busy(void) 
{ 
	DataPort= 0xFF; 
	RS_CLR; 
	RW_SET; 
	EN_CLR; 
	_nop_(); 
	EN_SET;
	return (bit)(DataPort & 0x80);
}


/*------------------------------------------------
              写入命令函数
------------------------------------------------*/
void LCD_Write_Com(unsigned char com) 
{  
	while(LCD_Check_Busy()); //忙则等待
	RS_CLR; 
	RW_CLR; 
	EN_SET; 
	DataPort= com; 
	_nop_(); 
	EN_CLR;
}

/*------------------------------------------------
              写入数据函数
------------------------------------------------*/
void LCD_Write_Data(unsigned char Data) 
{ 
	while(LCD_Check_Busy()); //忙则等待
	RS_SET; 
	RW_CLR; 
	EN_SET; 
	DataPort= Data; 
	_nop_();
	EN_CLR;
}

/*------------------------------------------------
                清屏函数
------------------------------------------------*/
void LCD_Clear(void) 
{ 
	LCD_Write_Com(0x01); 
	DelayMs(5);
}

/*------------------------------------------------
              写入字符串函数
------------------------------------------------*/
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) 
{     
	if (y == 0) 
 	{     
		LCD_Write_Com(0x80 + x);     //表示第一行
 	}
	else 
 	{      
		LCD_Write_Com(0xC0 + x);      //表示第二行
 	}        
	while (*s) 
 	{     
		LCD_Write_Data( *s);     
		s ++;     
 	}
}

/*------------------------------------------------
              写入字符函数
------------------------------------------------*/
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) 
{     
	if (y == 0) 
 	{     
		LCD_Write_Com(0x80 + x);     
 	}    
	else 
 	{     
		LCD_Write_Com(0xC0 + x);     
 	}        
	LCD_Write_Data( Data);  
}

/*------------------------------------------------
              初始化函数
------------------------------------------------*/
void LCD_Init(void) 
{
	LCD_Write_Com(0x38);    /*显示模式设置*/ 
	DelayMs(5); 
	LCD_Write_Com(0x38); 
	DelayMs(5); 
	LCD_Write_Com(0x38); 
	DelayMs(5); 
	LCD_Write_Com(0x38);  
	LCD_Write_Com(0x08);    /*显示关闭*/ 
	LCD_Write_Com(0x01);    /*显示清屏*/ 
	LCD_Write_Com(0x06);    /*显示光标移动设置*/ 
	DelayMs(5); 
	LCD_Write_Com(0x0C);    /*显示开及光标设置*/
}

   
/*------------------------------------------------
                    主函数
------------------------------------------------*/ 
void main(void) 
{ 
	LCD_Init(); 
	LCD_Clear();//清屏
	LCD_Write_Char(7,0,'o');
	LCD_Write_Char(8,0,'k');
	LCD_Write_String(1,1,"hello world!");
	while (1) 
	{  
		DelayMs(200); 
		LCD_Write_Com(0x18);//左平移画面 0x1C 是右平移
	}
}

LCD1602移动显示

程序实例4:

#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include<intrins.h>

sbit RS = P2^4;   //定义端口 
sbit RW = P2^5;
sbit EN = P2^6;

#define RS_CLR RS=0 
#define RS_SET RS=1

#define RW_CLR RW=0 
#define RW_SET RW=1 

#define EN_CLR EN=0
#define EN_SET EN=1

#define DataPort P0

/*------------------------------------------------
 uS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
 长度如下 T=tx2+5 uS 
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{   
	while(--t);
}

/*------------------------------------------------
 mS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void DelayMs(unsigned char t)
{    
	while(t--)
	{
		//大致延时1mS
		DelayUs2x(245);
		DelayUs2x(245);
	}
}

/*------------------------------------------------
              判忙函数
------------------------------------------------*/
bit LCD_Check_Busy(void) 
{ 
	DataPort= 0xFF; 
	RS_CLR; 
	RW_SET; 
	EN_CLR; 
	_nop_(); 
	EN_SET;
	return (bit)(DataPort & 0x80);
}

/*------------------------------------------------
              写入命令函数
------------------------------------------------*/
void LCD_Write_Com(unsigned char com) 
{  
	while(LCD_Check_Busy()); //忙则等待
	RS_CLR; 
	RW_CLR; 
	EN_SET; 
	DataPort= com; 
	_nop_(); 
	EN_CLR;
}

/*------------------------------------------------
              写入数据函数
------------------------------------------------*/
void LCD_Write_Data(unsigned char Data) 
{ 
	while(LCD_Check_Busy()); //忙则等待
	RS_SET; 
	RW_CLR; 
	EN_SET; 
	DataPort= Data; 
	_nop_();
	EN_CLR;
}

/*------------------------------------------------
                清屏函数
------------------------------------------------*/
void LCD_Clear(void) 
{ 
	LCD_Write_Com(0x01); 
	DelayMs(5);
}

/*------------------------------------------------
              写入字符串函数
------------------------------------------------*/
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) 
{     
	if (y == 0) 
 	{     
		LCD_Write_Com(0x80 + x);     
 	}
	else 
 	{     
		LCD_Write_Com(0xC0 + x);     
 	}        
	while (*s) 
 	{     
		LCD_Write_Data( *s);     
		s ++;     
 	}
}
/*------------------------------------------------
              写入字符函数
------------------------------------------------*/
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) 
{     
	if (y == 0) 
 	{     
		LCD_Write_Com(0x80 + x);     
 	}    
	else 
 	{     
		LCD_Write_Com(0xC0 + x);     
 	}        
	LCD_Write_Data( Data);  
}

/*------------------------------------------------
              初始化函数
------------------------------------------------*/
void LCD_Init(void) 
{
	LCD_Write_Com(0x38);    /*显示模式设置*/ 
	DelayMs(5); 
	LCD_Write_Com(0x38); 
	DelayMs(5); 
	LCD_Write_Com(0x38); 
	DelayMs(5); 
	LCD_Write_Com(0x38);  
	LCD_Write_Com(0x08);    /*显示关闭*/ 
	LCD_Write_Com(0x01);    /*显示清屏*/ 
	LCD_Write_Com(0x06);    /*显示光标移动设置*/ 
	DelayMs(5); 
	LCD_Write_Com(0x0C);    /*显示开及光标设置*/
}
   
/*------------------------------------------------
                    主函数
------------------------------------------------*/ 
void main(void) 
{ 
	unsigned char i; 
	unsigned char *pa,*pb; 

	LCD_Init(); 
	LCD_Write_Com(0x0f);//光标开,光标闪烁开
	while (1) 
	{  
		pa = "Welcome to";
		pb = "hello world!";  
		LCD_Clear();  
		LCD_Write_String(2,0,pa);  //显示2行信息
		LCD_Write_String(1,1,pb);
		for(i=0;i<8;i++)            //延时2s左右
			DelayMs(250); 
		LCD_Clear();                //清屏显示其他信息
		i = 2; 
		while (*pa)                 //循环输入方式显示2行信息
		{   
			LCD_Write_Char(i,0,*pa);   
			i ++;   
			pa ++;   
			DelayMs(250);   
		}  
		i=1;  
		while (*pb) 
		{   
			LCD_Write_Char(i,1,*pb);   
			i ++;   
			pb ++;   
			DelayMs(250);   
		}  
	
		DelayMs(250);  
	}
}

LCD1602液晶按键输入显示

程序实例5:

#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include<intrins.h>

sbit RS = P2^4;   //定义端口 
sbit RW = P2^5;
sbit EN = P2^6;

#define RS_CLR RS=0 
#define RS_SET RS=1

#define RW_CLR RW=0 
#define RW_SET RW=1 

#define EN_CLR EN=0
#define EN_SET EN=1

#define DataPort P0
#define KeyPort P1

unsigned char code show_code[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};//转换成液晶显示的字符
/*------------------------------------------------
 uS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
 长度如下 T=tx2+5 uS 
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{   
	while(--t);
}

/*------------------------------------------------
 mS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void DelayMs(unsigned char t)
{
     
	while(t--)
	{
		//大致延时1mS
		DelayUs2x(245);
		DelayUs2x(245);
	}
}

/*------------------------------------------------
              判忙函数
------------------------------------------------*/
bit LCD_Check_Busy(void) 
{ 
	DataPort= 0xFF; 
	RS_CLR; 
	RW_SET; 
	EN_CLR; 
	_nop_(); 
	EN_SET;
	return (bit)(DataPort & 0x80);
}

/*------------------------------------------------
              写入命令函数
------------------------------------------------*/
void LCD_Write_Com(unsigned char com) 
{  
	while(LCD_Check_Busy()); //忙则等待
	RS_CLR; 
	RW_CLR; 
	EN_SET; 
	DataPort= com; 
	_nop_(); 
	EN_CLR;
}
/*------------------------------------------------
              写入数据函数
------------------------------------------------*/
void LCD_Write_Data(unsigned char Data) 
{ 
	while(LCD_Check_Busy()); //忙则等待
	RS_SET; 
	RW_CLR; 
	EN_SET; 
	DataPort= Data; 
	_nop_();
	EN_CLR;
}

/*------------------------------------------------
                清屏函数
------------------------------------------------*/
void LCD_Clear(void) 
{ 
	LCD_Write_Com(0x01); 
	DelayMs(5);
}
/*------------------------------------------------
              写入字符串函数
------------------------------------------------*/
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) 
{     
	if (y == 0) 
 	{     
		LCD_Write_Com(0x80 + x);     
 	}
	else 
 	{     
		LCD_Write_Com(0xC0 + x);     
 	}        
	while (*s) 
 	{     
		LCD_Write_Data( *s);     
		s ++;     
 	}
 }
 
/*------------------------------------------------
              写入字符函数
------------------------------------------------*/
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) 
{     
	if (y == 0) 
 	{     
		LCD_Write_Com(0x80 + x);     
 	}    
	else 
 	{     
		LCD_Write_Com(0xC0 + x);     
 	}        
	LCD_Write_Data( Data);  
 }
 
/*------------------------------------------------
              初始化函数
------------------------------------------------*/
void LCD_Init(void) 
{
	LCD_Write_Com(0x38);    /*显示模式设置*/ 
	DelayMs(5); 
	LCD_Write_Com(0x38); 
	DelayMs(5); 
	LCD_Write_Com(0x38); 
	DelayMs(5); 
	LCD_Write_Com(0x38);  
	LCD_Write_Com(0x08);    /*显示关闭*/ 
	LCD_Write_Com(0x01);    /*显示清屏*/ 
	LCD_Write_Com(0x06);    /*显示光标移动设置*/ 
	DelayMs(5); 
	LCD_Write_Com(0x0C);    /*显示开及光标设置*/
}
 
   /*------------------------------------------------
按键扫描函数,返回扫描键值
------------------------------------------------*/
unsigned char KeyScan(void)  //键盘扫描函数,使用行列反转扫描法
{
	unsigned char cord_h,cord_l;//行列值中间变量
	KeyPort=0x0f;            //行线输出全为0
	cord_h=KeyPort&0x0f;     //读入列线值
	if(cord_h!=0x0f)    //先检测有无按键按下
	{
		DelayMs(10);        //去抖
		if((KeyPort&0x0f)!=0x0f)
		{
			cord_h=KeyPort&0x0f;  //读入列线值
			KeyPort=cord_h|0xf0;  //输出当前列线值
			cord_l=KeyPort&0xf0;  //读入行线值
	
			while((KeyPort&0xf0)!=0xf0);//等待松开并输出
	
			return(cord_h+cord_l);//键盘最后组合码值
		}
	}
	return(0xff);     //返回该值
}

/*------------------------------------------------
按键值处理函数,返回扫键值
------------------------------------------------*/
unsigned char KeyPro(void)
{
	switch(KeyScan())
	{
		case 0x7e:return 0;break;//0 按下相应的键显示相对应的码值
		case 0x7d:return 1;break;//1
		case 0x7b:return 2;break;//2
		case 0x77:return 3;break;//3
		case 0xbe:return 4;break;//4
		case 0xbd:return 5;break;//5
		case 0xbb:return 6;break;//6
		case 0xb7:return 7;break;//7
		case 0xde:return 8;break;//8
		case 0xdd:return 9;break;//9
		case 0xdb:return 10;break;//a
		case 0xd7:return 11;break;//b
		case 0xee:return 12;break;//c
		case 0xed:return 13;break;//d
		case 0xeb:return 14;break;//e
		case 0xe7:return 15;break;//f
		default:return 0xff;break;
	}
}

/*------------------------------------------------
                    主函数
------------------------------------------------*/ 
void main(void) 
{ 
	unsigned char i,j,num; 

	LCD_Init(); 
	LCD_Write_Com(0x0F);//光标开,光标闪烁开

	LCD_Write_String(0,0,"Press the key !");

	while (1) 
	{  
		num=KeyPro();
		if(num!=0xff)
		{
			if((i==0)&&(j==0))//回到第一个字符时清屏
				LCD_Clear();//清屏
			LCD_Write_Char(0+i,0+j,show_code[num]);//依次显示输入字符
			i++;
			if(i==16)//如果第一行显示满,转到第二行
			{
				i=0;j++;
				if(j==2)//如果2行都显示满,清屏后重新从第一行显示
				{
					j=0;
				}
			}
		}
	}
}

文章来源地址https://uudwc.com/A/DNjwr

原文地址:https://blog.csdn.net/m0_49968063/article/details/132795774

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

上一篇 2023年09月12日 05:41
下一篇 2023年09月12日 05:42