51单片机复习程序例举004--HD44780控制的1602LCD


1、在HD44780控制的1602LCD的显示屏上显示两条字符串 和 两个用户自定义的字符

/******************************************************************************
 *	说明:AT89S52芯片,12M晶振
 *	外设:HD44780控制的1602LCD:两行显示,每行最多显示40个预显示字符中的16个字符
 * 		  11条控制指令 
 *	本程序:在HD44780控制的1602LCD上显示2行字符串,按键K1,显示一个用户自定义字符
 *			循环按键,循环显示
 ******************************************************************************/

#include<reg52.h>
#include<intrins.h>

sbit K1 = P1^4 ;	//按键

sbit RS = P2^0 ;	//对象标志位: = 0(对象是指令或状态位);= 1(对象是数据)
sbit RW = P2^1 ;	//读写标志位: = 0(写);= 1(读)
sbit E  = P2^2 ;	//使能位:为 1 时,读写信息,为 负跳变 时,执行指令
sbit BF = P0^7 ;	//HD44780控制的1602LCD的 忙 状态位(只能通过指令读取)

//用户要显示的字符串
unsigned char code sys_str1[] = "Dragon_CSU" ;
unsigned char code sys_str2[] = "Good_Luck" ;

//用户自定义的字符编码方式:在8*8的点阵中选“右上角”的“5列*7行”点阵 存放数据
unsigned char code user_str[] = {0x10,0x06,0x09,0x08,0x08,0x09,0x06,0x00};/* 自定义字符 ℃ */


/******************************************************************************
 *	名称:delay1ms()
 *	功能:延时1ms
 *	参数:int t
 *	返回:无
 ******************************************************************************/
void delay1ms(int t)
{
	unsigned char i ;

	while(t--)
	{
		for(i = 0 ; i < 125 ; i++)
		{
			;
		}
	}
}



/******************************************************************************
 *	名称:Busy_Test()
 *	功能:检测HD44780控制的1602LCD是否处于忙状态
 *	参数:无							   
 *	返回:bit result  忙则返回 1 , 不忙则返回 0 。
 ******************************************************************************/
bit Busy_Test(void)
{
	//1、定义变量,存储返回值
	bit result ;

	//2、读状态位
	RS = 0 ; RW = 1 ; 
	E = 1 ;
	_nop_() ; _nop_() ; _nop_() ; _nop_() ;	 //延时4个机器周期,给硬件响应,
											 //即:使E=1;稳定
	result = BF ;	//将忙状态位BF的值读给函数要返回的变量

	//3、将时能位E复位到低电平
	E = 0 ;

	//4、将忙状态位读的结果作为函数的参数返回
	return result ;

} 


/******************************************************************************
 *	名称:Write_Com()
 *	功能:向HD44780写控制1602LCD的控制指令
 *	参数:unsigned char dictate
 *	返回:无
 ******************************************************************************/
 void Write_Com(unsigned char dictate)
 {
 	//1、检测LCD忙状态,忙,则等待
	while(Busy_Test() == 1) { ; }

	//2、向HD44780控制的1602LCD写控制指令
		/*----2.1、操作对象是指令,执行对象:写入----------------------------*/
			RS = 0 ;
		    RW = 0 ;

		/*----2.2、在E 为 0 时,先将指令数据写到P0口的DB0--DB7数据线上-------*/
			E = 0 ;

			_nop_() ; //给硬件反应时间,等待E = 0 ;稳定 
			_nop_() ;

			P0 = dictate ;	//将指令先暂时写到数据线上

			_nop_() ; //确保硬件把指令数据写完了
			_nop_() ; 
			_nop_() ; 
			_nop_() ; 

		/*----2.3、在E 为 1 时,将数据线上的指令数据写到DH44780的寄存器里----*/
			E = 1 ;
			_nop_(); _nop_(); _nop_(); _nop_(); //等待 E = 1 稳定

		/*----2.4、在E 为 下降沿 时,执行写入的指令--------------------------*/
			E = 0 ;	//从 E = 1 到 E = 0 产生下降沿,HD44780执行指令

 }


/******************************************************************************
 *	名称:Write_Address()
 *	功能:通过指令来控制第一个要显示的字符或下一个即将要显示的字符在LCD上的位置
 *	参数:unsigned char addr  在LCD上要显示的位置
 *	返回:无
 ******************************************************************************/
void Write_Address(unsigned char addr)
{
	//向HD44780写指令8:设定DDRAM地址的指令。
	//即:即将要显示的字符在1602LCD上的指令需要的地址 = 0x80|(字符在LCD屏幕上的位置)
	Write_Com(0x80|addr) ;
}

/******************************************************************************
 *	名称:Write_Data()
 *	功能:1、向HD44780控制的1602LCD写要显示的字符数据;
 *		  2、向CGRAM中,对应地址的存储单元写用户自定义的字符数据
 *	参数:unsigned char char_data 要显示的字符(其实字符的值和它的ASCII码值一样)
 *	返回:无
 ******************************************************************************/
void Write_Data(unsigned char char_data)
{
	//1、检测HD44780控制的1602LCD忙状态位,忙,则等待
	while(Busy_Test() == 1) { ; }
	//2、向HD44780控制的1602LCD写要显示的字符数据
		/*----2.1、操作对象是数据,执行对象:写入----------------------------*/
			RS = 1 ;
		    RW = 0 ;

		/*----2.1、在E 为 0 时,先将字符数据写到P0口的DB0--DB7数据线上-------*/
			E = 0 ;
			_nop_() ; _nop_() ; //给硬件反应时间,等待E = 0 ;稳定
			P0 = char_data ;	//将字符数据先暂时写到数据线上
			_nop_() ; _nop_() ; _nop_() ; _nop_() ; //确保硬件把字符数据写完了

		/*----2.2、在E 为 1 时,将数据线上的字符数据写到DH44780的寄存器里----*/
			E = 1 ;
			_nop_(); _nop_(); _nop_(); _nop_(); //等待 E = 1 稳定

		/*----2.3、在E 为 下降沿 时,执行写入的指令--------------------------*/
			E = 0 ;	//从 E = 1 到 E = 0 产生下降沿,HD44780执行指令

}

/******************************************************************************
 *	名称:HD44780_1602LCD_Init()
 *	功能:对HD44780控制的1602LCD进行初始化 (包含硬件类型,屏显,光标)
 *	参数:无
 *	返回:无
 ******************************************************************************/
void HD44780_1602LCD_Init(void)
{
	//1、首次写指令前,给LCD硬件一段较长的反应时间
	delay1ms(15) ;
	//2、显示模式设置
		/*----1、匹配硬件的设置: 指令6:8位数据线,2行显示,5*7点阵------------*/
		Write_Com(0x38) ; delay1ms(5) ; //3次写指令,确保硬件匹配成功
		Write_Com(0x38) ; delay1ms(5) ; 
		Write_Com(0x38) ; delay1ms(5) ; 

		/*----2、显示屏、光标、闪烁的设置: 指令4:开显示,开光标,光标闪烁------*/
		Write_Com(0x0f) ; delay1ms(5) ;

		/*----3、光标、屏幕移动的设置: 指令3:光标右移,屏幕整体不移动----------*/
		Write_Com(0x06) ; delay1ms(5) ;

	//3、清屏。指令1
	Write_Com(0x01) ; delay1ms(5) ;	 

}



/******************************************************************************
===============================================================================
                       void main(void)函数部分
===============================================================================
*******************************************************************************/
void main(void)
{
	//1、定义相关变量
	unsigned char i ;

	//2、对HD44780控制的1602LCD进行初始化
	HD44780_1602LCD_Init() ;

	//3、在HD44780控制的1602LCD上显示信息
	while(1)
	{
		/*----3.1要显示的字符来源于CGROM的160个字符的库-----------------*/
		//3.1.1 根据需求选择是否清屏
		Write_Com(0x01) ; delay1ms(5) ;

		//3.1.2 在显示1602LCD上显示第一个字符串
			//3.1.2.1 设置在LCD1602上显示字符的开始位置 : 从 第1行 坐标0 开始显示
			Write_Address(0x00+0) ; delay1ms(5) ;	

			//3.1.2.2 显示要显示的字符串
			i = 0 ;
			while(sys_str1[i] != '\0')
			{
				Write_Data(sys_str1[i]) ;
				i++ ;
				delay1ms(100) ;
			}

		//3.1.3 在显示1602LCD上显示第二个字符串
			//3.1.3.1 设置在LCD1602上显示字符的开始位置 : 从 第2行 坐标0 开始显示
			Write_Address(0x40+0) ; delay1ms(5) ;	

			//3.1.3.2 显示要显示的字符串
			i = 0 ;
			while(sys_str2[i] != '\0')
			{
				Write_Data(sys_str2[i]) ;
				i++ ;
				delay1ms(100) ;
			}
			//3.1.3.3 无按键按下,等待
			while(K1 == 1) { ; }	

		/*----3.2要显示的字符来源于CGRAM的8个用户自己定义的字符---------*/
			//3.2.1 将用户自定义的字符写入CGRAM中
				/*----1、指令7:设定将自定义字符数据存入CGRAM中存储单元的地址------------*/
				//指令固定值01、第n个自定义字符、存储第n个自定义字符的数组的首地址(8byte)
				Write_Com(0x40) ; // 01 000 000 :
				delay1ms(5) ;
				
				/*----2、将用户自定义的字符写入CGRAM中对应地址的存储单元中----------------*/
				i = 0 ;
				for(i = 0 ; i < 8 ; i++)
				{
					Write_Data(user_str[i]) ;
				}
				
			//3.2.2 在HD44780控制的1602LCD屏幕指定位置上显示自定义字符
				/*----1、设定在1602LCD屏幕上显示的坐标位置(地址)------------*/ 
				Write_Address(0x40+10) ; //显示在第二行的第十位
				delay1ms(5) ;

				/*----2、将CGROM/CGRAM对应地址中的数据,显示在屏幕对应的位置---*/
				Write_Data(0x00) ; //显示CGRAM中8个自定义字符的第1个
								   //和显示CGROM中数据不同之处在于:不用和0x80相与

			//3.2.3 无按键按下,等待
			delay1ms(1000) ; 
			while(K1 == 1) { ; }
	}			
		
}


/******************************************************************************
 *	名称:
 *	功能:
 *	参数:
 *	返回:
 ******************************************************************************/


2、HD44780控制的1602LCD,各功能函数模块化,程序例举

/******************************************************************************
 *	说明:AT89S52芯片,12M晶振
 *	外设:HD44780控制的1602LCD:两行显示,每行最多显示40个预显示字符中的16个字符
 * 		  11条控制指令 
 *	本程序:在HD44780控制的1602LCD上显示2行字符串,按键K1,显示一个用户自定义字符
 *			循环按键,循环显示
 ******************************************************************************/

#include<reg52.h>
#include<intrins.h>

sbit K1 = P1^4 ;	//按键

sbit RS = P2^0 ;	//对象标志位: = 0(对象是指令或状态位);= 1(对象是数据)
sbit RW = P2^1 ;	//读写标志位: = 0(写);= 1(读)
sbit E  = P2^2 ;	//使能位:为 1 时,读写信息,为 负跳变 时,执行指令
sbit BF = P0^7 ;	//HD44780控制的1602LCD的 忙 状态位(只能通过指令读取)

//用户要显示的字符串
unsigned char code sys_str0[] = "Dragon_CSU" ;
unsigned char code sys_str1[] = "Good_Luck" ;

//用户自定义的字符编码方式:在8*8的点阵中选“右上角”的“5列*7行”点阵 存放数据
unsigned char code user_str0[] = {0x10,0x06,0x09,0x08,0x08,0x09,0x06,0x00};/* 自定义字符 ℃ */
unsigned char code user_str1[] = {0x1f,0x04,0x04,0x1f,0x04,0x04,0x1f,0x00};/* 自定义字符 王 */


/******************************************************************************
 *	名称:delay1ms()
 *	功能:延时1ms
 *	参数:int t
 *	返回:无
 ******************************************************************************/
void delay1ms(int t)
{
	unsigned char i ;

	while(t--)
	{
		for(i = 0 ; i < 125 ; i++)
		{
			;
		}
	}
}



/******************************************************************************
 *	名称:Busy_Test()
 *	功能:检测HD44780控制的1602LCD是否处于忙状态
 *	参数:无							   
 *	返回:bit result  忙则返回 1 , 不忙则返回 0 。
 ******************************************************************************/
bit Busy_Test(void)
{
	//1、定义变量,存储返回值
	bit result ;

	//2、读状态位
	RS = 0 ; RW = 1 ; 
	E = 1 ;
	_nop_() ; _nop_() ; _nop_() ; _nop_() ;	 //延时4个机器周期,给硬件响应,
											 //即:使E=1;稳定
	result = BF ;	//将忙状态位BF的值读给函数要返回的变量

	//3、将时能位E复位到低电平
	E = 0 ;

	//4、将忙状态位读的结果作为函数的参数返回
	return result ;

} 


/******************************************************************************
 *	名称:Write_Com()
 *	功能:向HD44780写控制1602LCD的控制指令
 *	参数:unsigned char dictate
 *	返回:无
 ******************************************************************************/
 void Write_Com(unsigned char dictate)
 {
 	//1、检测LCD忙状态,忙,则等待
	while(Busy_Test() == 1) { ; }

	//2、向HD44780控制的1602LCD写控制指令
		/*----2.1、操作对象是指令,执行对象:写入----------------------------*/
			RS = 0 ;
		    RW = 0 ;

		/*----2.2、在E 为 0 时,先将指令数据写到P0口的DB0--DB7数据线上-------*/
			E = 0 ;

			_nop_() ; //给硬件反应时间,等待E = 0 ;稳定 
			_nop_() ;

			P0 = dictate ;	//将指令先暂时写到数据线上

			_nop_() ; //确保硬件把指令数据写完了
			_nop_() ; 
			_nop_() ; 
			_nop_() ; 

		/*----2.3、在E 为 1 时,将数据线上的指令数据写到DH44780的寄存器里----*/
			E = 1 ;
			_nop_(); _nop_(); _nop_(); _nop_(); //等待 E = 1 稳定

		/*----2.4、在E 为 下降沿 时,执行写入的指令--------------------------*/
			E = 0 ;	//从 E = 1 到 E = 0 产生下降沿,HD44780执行指令

 }


/******************************************************************************
 *	名称:Write_Address()
 *	功能:通过指令来控制第一个要显示的字符或下一个即将要显示的字符在LCD上的位置
 *	参数:unsigned char addr  在LCD上要显示的位置
 *	返回:无
 ******************************************************************************/
void Write_Address(unsigned char addr)
{
	//向HD44780写指令8:设定DDRAM地址的指令。
	//即:即将要显示的字符在1602LCD上的指令需要的地址 = 0x80|(字符在LCD屏幕上的位置)
	Write_Com(0x80|addr) ;
}

/******************************************************************************
 *	名称:Write_Data()
 *	功能:1、向HD44780控制的1602LCD写要显示的字符数据;
 *		  2、向CGRAM中,对应地址的存储单元写用户自定义的字符数据
 *	参数:unsigned char char_data 要显示的字符(其实字符的值和它的ASCII码值一样)
 *	返回:无
 ******************************************************************************/
void Write_Data(unsigned char char_data)
{
	//1、检测HD44780控制的1602LCD忙状态位,忙,则等待
	while(Busy_Test() == 1) { ; }
	//2、向HD44780控制的1602LCD写要显示的字符数据
		/*----2.1、操作对象是数据,执行对象:写入----------------------------*/
			RS = 1 ;
		    RW = 0 ;

		/*----2.1、在E 为 0 时,先将字符数据写到P0口的DB0--DB7数据线上-------*/
			E = 0 ;
			_nop_() ; _nop_() ; //给硬件反应时间,等待E = 0 ;稳定
			P0 = char_data ;	//将字符数据先暂时写到数据线上
			_nop_() ; _nop_() ; _nop_() ; _nop_() ; //确保硬件把字符数据写完了

		/*----2.2、在E 为 1 时,将数据线上的字符数据写到DH44780的寄存器里----*/
			E = 1 ;
			_nop_(); _nop_(); _nop_(); _nop_(); //等待 E = 1 稳定

		/*----2.3、在E 为 下降沿 时,执行写入的指令--------------------------*/
			E = 0 ;	//从 E = 1 到 E = 0 产生下降沿,HD44780执行指令

}

/******************************************************************************
 *	名称:HD44780_1602LCD_Init()
 *	功能:对HD44780控制的1602LCD进行初始化 (包含硬件类型,屏显,光标)
 *	参数:无
 *	返回:无
 ******************************************************************************/
void HD44780_1602LCD_Init(void)
{
	//1、首次写指令前,给LCD硬件一段较长的反应时间
	delay1ms(15) ;
	//2、显示模式设置
		/*----1、匹配硬件的设置: 指令6:8位数据线,2行显示,5*7点阵------------*/
		Write_Com(0x38) ; delay1ms(5) ; //3次写指令,确保硬件匹配成功
		Write_Com(0x38) ; delay1ms(5) ; 
		Write_Com(0x38) ; delay1ms(5) ; 

		/*----2、显示屏、光标、闪烁的设置: 指令4:开显示,开光标,光标闪烁------*/
		Write_Com(0x0f) ; delay1ms(5) ;

		/*----3、光标、屏幕移动的设置: 指令3:光标右移,屏幕整体不移动----------*/
		Write_Com(0x06) ; delay1ms(5) ;

	//3、清屏。指令1
	Write_Com(0x01) ; delay1ms(5) ;	 

}

/******************************************************************************
 *	名称:Write_User_char()
 *	功能:将一个用户自定义的字符写入CGRAM中(CGRAM最多写8个字符)
 *	参数:unsigned char addr_num : 存入CGRAM中的第addr_num个8字节存储块 (0--8)
 *	参数:unsigned char *str : 指向存放用户自定义字符的数组
 *	返回:无
 ******************************************************************************/
 void Write_User_char(unsigned char addr_num , unsigned char *str)
 {
	/*----1、定义变量--------------------------------------------------------*/
 	unsigned char i ;
 	unsigned char CGRAM_addr ;

	/*----2、处理地址,CGRAM存储单元有8*8==64个字节,可存入8个自定义字符-----*/
	//指令7的指令码	  01 xxx 000 :第一个 xxx 表示自定义字符存入 第xxx个8字节的存储空间
	//									 000 表示第xxx个8字节存储空间的首地址
	addr_num = _crol_(addr_num,3) ;	
	CGRAM_addr = 0x40 | addr_num ;

	/*----1、指令7:设定将自定义字符数据存入CGRAM中存储单元的地址------------*/
	//指令固定值01、第n个自定义字符、存储第n个自定义字符的数组的首地址(8byte)
	Write_Com(CGRAM_addr) ; //
	delay1ms(5) ;
	
	/*----2、将用户自定义的字符写入CGRAM中对应地址的存储单元中----------------*/
	i = 0 ;
	for(i = 0 ; i < 8 ; i++)
	{
		Write_Data(str[i]) ;
	}

 }

/******************************************************************************
 *	名称:Dis_User_char()
 *	功能:显示自定义字符:在1602LCD屏幕指定位置上显示第num个自定义字符
 *	参数:unsigned char line , unsigned char x	 在屏幕的第line行第x列显示 
 *	参数:unsigned char num	 :显示CGRAM中8个自定义字符的第num个 num = 0-->7
 *	返回:无
 ******************************************************************************/
void Dis_User_char(unsigned char line , unsigned char x ,unsigned char num)
{
//3.2.2 
	/*----1、设定在1602LCD屏幕上显示的坐标位置(地址)------------*/ 
	Write_Address(0x40 * line + x) ; //显示在第line行的第x位
	delay1ms(5) ;

	/*----2、将CGROM/CGRAM对应地址中的数据,显示在屏幕对应的位置---*/
	Write_Data(num) ; //显示CGRAM中8个自定义字符的第num个 num = 0-->7
					   //和显示CGROM中数据不同之处在于:不用和0x80相与

}


/******************************************************************************
 *	名称:Switch_Screen()
 *	功能:控制显示屏开关,(不显示光标)
 *	参数:unsigned char scr_key = 1:开 ; = 0:关
 *	返回:无
 ******************************************************************************/
 void Switch_Screen(unsigned char scr_key)
 {
 	delay1ms(50) ;
	if(scr_key == 1)
	{
		Write_Com(0x0c) ; //指令4 ,0000 1100 :开屏幕显示 ,无光标
	}

	if(scr_key == 0)
	{
		Write_Com(0x08) ; //指令4 ,0000 1100 :关屏幕显示
	}

 	delay1ms(50) ;
 }

 /******************************************************************************
 *	名称:Switch_Cursor()
 *	功能:控制光标开关和闪烁
 *	参数:unsigned char cursor_key 
 *	参数:unsigned char twinkle_key
 *	返回:无
 ******************************************************************************/
 void Switch_Cursor(unsigned char cursor_key , unsigned char twinkle_key)
 {
 	delay1ms(50) ;
	if(cursor_key == 1)
	{
		if(twinkle_key == 1)
		{
			Write_Com(0x0f) ; //指令4 ,0000 1111 :开屏幕显示,开光标,光标闪烁
		}
		else
		{
			Write_Com(0x0e) ; //指令4 ,0000 1110 :开屏幕显示 ,开光标		
		}
	}

	if(cursor_key == 0)
	{
		Write_Com(0x0c) ; //指令4 ,0000 1100 :开屏幕显示
	}

 	delay1ms(50) ;
 }

/******************************************************************************
 *	名称:Move_Screen()
 *	功能:控制屏幕整体左右移动
 *	参数:unsigned char r_l = 1 :右移  ; = 0 :左移
 *	参数:unsigned char move_bit_num  :屏幕向右或向左移动多少位
 *	参数:unsigned char move_delay :每移动一位后,延时多少 ms
 *	返回:无
 ******************************************************************************/
 void Move_Screen(unsigned char r_l,unsigned char move_bit_num,unsigned char move_delay)
 {
 	unsigned char i ;
 	delay1ms(move_delay) ;

	if(r_l == 1) //屏幕整体右移
	{
		for(i = 0 ; i < move_bit_num ; i++)
		{
			Write_Com(0x1c) ; //指令5 : 0001 1100 屏幕整体右移一位	
			delay1ms(move_delay) ;	
		}

	}

	if(r_l == 0) //屏幕整体左移
	{
		for(i = 0 ; i < move_bit_num ; i++)
		{
			Write_Com(0x18) ; //指令5 : 0001 1000 屏幕整体左移一位	
			delay1ms(move_delay) ;	
		}

	}
 }

/******************************************************************************
 *	名称:Dis_Str()
 *	功能:在显示HD44780控制的1602LCD上显示一个字符串
 *	参数:unsigned char line , unsigned char x 在LCD上显示的位置
 *	参数:unsigned char *str 要显示的字符串的指针(首地址)
 *	返回:无
 ******************************************************************************/
void Dis_Str(unsigned char line , unsigned char x , unsigned char *str)
{
	unsigned char i ;

	//1、 设置在LCD1602上显示字符的开始位置 : 从 第line行 坐标x 开始显示
	Write_Address(0x40 * line + x) ; delay1ms(5) ;	

	//2、 显示要显示的字符串
	i = 0 ;
	while(str[i] != '\0')
	{
		Write_Data(str[i]) ;
		i++ ;
		delay1ms(100) ;
	}
}

/******************************************************************************
 *	名称:Clear_Screen()
 *	功能:清屏
 *	参数:无
 *	返回:无
 ******************************************************************************/
 void Clear_Screen(void)
 {
	delay1ms(5) ;
	Write_Com(0x01) ; 
	delay1ms(5) ; 
 }


/******************************************************************************
===============================================================================
                       void main(void)函数部分
===============================================================================
*******************************************************************************/
void main(void)
{
	//1、定义相关变量
//	unsigned char i ;

	//2、对HD44780控制的1602LCD进行初始化
	HD44780_1602LCD_Init() ;

	//3、在HD44780控制的1602LCD上显示信息
	while(1)
	{
		/*----3.1要显示的字符来源于CGROM的160个字符的库-----------------*/
			//3.1.1 根据需求选择是否清屏
			Clear_Screen() ;
	
			//3.1.2 在显示1602LCD上显示第一个字符串 从第1行第0位开始显示
				Dis_Str(0 , 0 , sys_str0) ; 
	
			//3.1.3 在显示1602LCD上显示第二个字符串	从第2行第0位开始显示
				Dis_Str(1 , 0 , sys_str1) ;
				
			//3.1.4 无按键按下,等待
			delay1ms(1000) ; 
			while(K1 == 1) { ; }	

		/*----3.2要显示的字符来源于CGRAM的8个用户自己定义的字符---------*/
			//3.2.1 将用户自定义的字符写入CGRAM中
			Write_User_char(0 , user_str0) ;
			Write_User_char(1 , user_str1) ;
				
			//3.2.2 在HD44780控制的1602LCD屏幕指定位置上显示自定义字符
			Dis_User_char(1 , 11 , 0x00) ;
			Dis_User_char(1 , 13 , 0x01) ;

			//3.2.3 无按键按下,等待
			delay1ms(1000) ; 
			while(K1 == 1) { ; }

		/*----3.3关闭屏幕------------------------------------------------*/
			//3.3.1 关闭屏幕
			Switch_Screen(0) ;
			//3.3.2 无按键按下,等待
			delay1ms(1000) ; 
			while(K1 == 1) { ; }

		/*----3.4打开屏幕------------------------------------------------*/
			//3.4.1 打开屏幕
			Switch_Screen(1) ;
			//3.4.2 无按键按下,等待
			delay1ms(1000) ; 
			while(K1 == 1) { ; }

		/*----3.5打开光标------------------------------------------------*/
			//3.5.1 打开光标
			Switch_Cursor(1 , 1) ;	//1,1:打开光标、闪烁 ;1,0:打开、不闪烁
			//3.5.2 无按键按下,等待
			delay1ms(1000) ; 
			while(K1 == 1) { ; }

		/*----3.6关闭光标------------------------------------------------*/
			//3.6.1 关闭光标
			Switch_Cursor(0 , 0) ;
			//3.6.2 无按键按下,等待
			delay1ms(1000) ; 
			while(K1 == 1) { ; }

		/*----3.7屏幕整体左移--------------------------------------------*/
			//3.7.1 左移16位,每移一位延时500ms
			Move_Screen(0 , 16 , 500) ;
			//3.7.2 无按键按下,等待
			delay1ms(1000) ; 
			while(K1 == 1) { ; }

		/*----3.8屏幕整体右移--------------------------------------------*/
			//3.8.1 左移16位,每移一位延时500ms
			Move_Screen(1 , 16 , 500) ;
			//3.8.2 无按键按下,等待
			delay1ms(1000) ; 
			while(K1 == 1) { ; }
	}			
		
}


/******************************************************************************
 *	名称:
 *	功能:
 *	参数:
 *	返回:
 ******************************************************************************/

3、AT89S52 + 外设HD44780控制的1602LCD,将驱动控制1602LCD的函数封装成文件

(1)、HD44780控制的1602LCD的库文件

/**************************************************************************************************
 * 	HD44780_1602LCD配置文件:HD44780_1602LCD.c和HD44780_1602LCD.h配套使用
 *	本程序当时是依据AT89S52单片机开发板写的
 *	RS R/W E 这三位引脚分别和单片机引脚 P2^0 P2^1 P2^2 相连
 *	八位数据引脚DB0……DB7分别和单片机的P0端口的P0^0……P0^7相连 (BF位其实就对应DB7引脚和P0^7相连)
 *	将此文件来驱动1602LCD时,只需更改下面的位定义和数据线的端口号即可
 *	对于HD44780控制的1602LCD的详细资料和11条指令的描述参考一下连接
 *	http://blog.csdn.net/dragon12345666/article/details/22819827
 **************************************************************************************************/


#include"HD44780_1602LCD.h"


/******************************************************************************
 *	名称:dlcd_delay1ms()
 *	功能:延时1ms
 *	参数:int t
 *	返回:无
 ******************************************************************************/
void lcd_delay1ms(int t)
{
	unsigned char i ;

	while(t--)
	{
		for(i = 0 ; i < 125 ; i++)
		{
			;
		}
	}
}



/******************************************************************************
 *	名称:Busy_Test()
 *	功能:检测HD44780控制的1602LCD是否处于忙状态
 *	参数:无							   
 *	返回:bit result  忙则返回 1 , 不忙则返回 0 。
 ******************************************************************************/
bit Busy_Test(void)
{
	//1、定义变量,存储返回值
	bit result ;

	//2、读状态位
	RS = 0 ; RW = 1 ; 
	E = 1 ;
	_nop_() ; _nop_() ; _nop_() ; _nop_() ;	 //延时4个机器周期,给硬件响应,
											 //即:使E=1;稳定
	result = BF ;	//将忙状态位BF的值读给函数要返回的变量

	//3、将时能位E复位到低电平
	E = 0 ;

	//4、将忙状态位读的结果作为函数的参数返回
	return result ;

} 


/******************************************************************************
 *	名称:Write_Com()
 *	功能:向HD44780写控制1602LCD的控制指令
 *	参数:unsigned char dictate
 *	返回:无
 ******************************************************************************/
 void Write_Com(unsigned char dictate)
 {
 	//1、检测LCD忙状态,忙,则等待
	while(Busy_Test() == 1) { ; }

	//2、向HD44780控制的1602LCD写控制指令
		/*----2.1、操作对象是指令,执行对象:写入----------------------------*/
			RS = 0 ;
		    RW = 0 ;

		/*----2.2、在E 为 0 时,先将指令数据写到P0口的DB0--DB7数据线上-------*/
			E = 0 ;

			_nop_() ; //给硬件反应时间,等待E = 0 ;稳定 
			_nop_() ;

			P0 = dictate ;	//将指令先暂时写到数据线上

			_nop_() ; //确保硬件把指令数据写完了
			_nop_() ; 
			_nop_() ; 
			_nop_() ; 

		/*----2.3、在E 为 1 时,将数据线上的指令数据写到DH44780的寄存器里----*/
			E = 1 ;
			_nop_(); _nop_(); _nop_(); _nop_(); //等待 E = 1 稳定

		/*----2.4、在E 为 下降沿 时,执行写入的指令--------------------------*/
			E = 0 ;	//从 E = 1 到 E = 0 产生下降沿,HD44780执行指令

 }


/******************************************************************************
 *	名称:Write_Address()
 *	功能:通过指令来控制第一个要显示的字符或下一个即将要显示的字符在LCD上的位置
 *	参数:unsigned char addr  在LCD上要显示的位置
 *	返回:无
 ******************************************************************************/
void Write_Address(unsigned char addr)
{
	//向HD44780写指令8:设定DDRAM地址的指令。
	//即:即将要显示的字符在1602LCD上的指令需要的地址 = 0x80|(字符在LCD屏幕上的位置)
	Write_Com(0x80|addr) ;
}

/******************************************************************************
 *	名称:Write_Data()
 *	功能:1、向HD44780控制的1602LCD写要显示的字符数据;
 *		  2、向CGRAM中,对应地址的存储单元写用户自定义的字符数据
 *	参数:unsigned char char_data 要显示的字符(其实字符的值和它的ASCII码值一样)
 *	返回:无
 ******************************************************************************/
void Write_Data(unsigned char char_data)
{
	//1、检测HD44780控制的1602LCD忙状态位,忙,则等待
	while(Busy_Test() == 1) { ; }
	//2、向HD44780控制的1602LCD写要显示的字符数据
		/*----2.1、操作对象是数据,执行对象:写入----------------------------*/
			RS = 1 ;
		    RW = 0 ;

		/*----2.1、在E 为 0 时,先将字符数据写到P0口的DB0--DB7数据线上-------*/
			E = 0 ;
			_nop_() ; _nop_() ; //给硬件反应时间,等待E = 0 ;稳定
			P0 = char_data ;	//将字符数据先暂时写到数据线上
			_nop_() ; _nop_() ; _nop_() ; _nop_() ; //确保硬件把字符数据写完了

		/*----2.2、在E 为 1 时,将数据线上的字符数据写到DH44780的寄存器里----*/
			E = 1 ;
			_nop_(); _nop_(); _nop_(); _nop_(); //等待 E = 1 稳定

		/*----2.3、在E 为 下降沿 时,执行写入的指令--------------------------*/
			E = 0 ;	//从 E = 1 到 E = 0 产生下降沿,HD44780执行指令

}

/******************************************************************************
 *	名称:HD44780_1602LCD_Init()
 *	功能:对HD44780控制的1602LCD进行初始化 (包含硬件类型,屏显,光标)
 *	参数:无
 *	返回:无
 ******************************************************************************/
void HD44780_1602LCD_Init(void)
{
	//1、首次写指令前,给LCD硬件一段较长的反应时间
	lcd_delay1ms(15) ;
	//2、显示模式设置
		/*----1、匹配硬件的设置: 指令6:8位数据线,2行显示,5*7点阵------------*/
		Write_Com(0x38) ; lcd_delay1ms(5) ; //3次写指令,确保硬件匹配成功
		Write_Com(0x38) ; lcd_delay1ms(5) ; 
		Write_Com(0x38) ; lcd_delay1ms(5) ; 

		/*----2、显示屏、光标、闪烁的设置: 指令4:开显示,开光标,光标闪烁------*/
		Write_Com(0x0f) ; lcd_delay1ms(5) ;

		/*----3、光标、屏幕移动的设置: 指令3:光标右移,屏幕整体不移动----------*/
		Write_Com(0x06) ; lcd_delay1ms(5) ;

	//3、清屏。指令1
	Write_Com(0x01) ; lcd_delay1ms(5) ;	 

}

/******************************************************************************
 *	名称:Write_User_char()
 *	功能:将一个用户自定义的字符写入CGRAM中(CGRAM最多写8个字符)
 *	参数:unsigned char addr_num : 存入CGRAM中的第addr_num个8字节存储块 (0--8)
 *	参数:unsigned char *str : 指向存放用户自定义字符的数组
 *	返回:无
 ******************************************************************************/
 void Write_User_char(unsigned char addr_num , unsigned char *str)
 {
	/*----1、定义变量--------------------------------------------------------*/
 	unsigned char i ;
 	unsigned char CGRAM_addr ;

	/*----2、处理地址,CGRAM存储单元有8*8==64个字节,可存入8个自定义字符-----*/
	//指令7的指令码	  01 xxx 000 :第一个 xxx 表示自定义字符存入 第xxx个8字节的存储空间
	//									 000 表示第xxx个8字节存储空间的首地址
	addr_num = _crol_(addr_num,3) ;	
	CGRAM_addr = 0x40 | addr_num ;

	/*----1、指令7:设定将自定义字符数据存入CGRAM中存储单元的地址------------*/
	//指令固定值01、第n个自定义字符、存储第n个自定义字符的数组的首地址(8byte)
	Write_Com(CGRAM_addr) ; //
	lcd_delay1ms(5) ;
	
	/*----2、将用户自定义的字符写入CGRAM中对应地址的存储单元中----------------*/
	i = 0 ;
	for(i = 0 ; i < 8 ; i++)
	{
		Write_Data(str[i]) ;
	}

 }

/******************************************************************************
 *	名称:Dis_User_char()
 *	功能:显示自定义字符:在1602LCD屏幕指定位置上显示第num个自定义字符
 *	参数:unsigned char line , unsigned char x	 在屏幕的第line行第x列显示 
 *	参数:unsigned char num	 :显示CGRAM中8个自定义字符的第num个 num = 0-->7
 *	返回:无
 ******************************************************************************/
void Dis_User_char(unsigned char line , unsigned char x ,unsigned char num)
{
//3.2.2 
	/*----1、设定在1602LCD屏幕上显示的坐标位置(地址)------------*/ 
	Write_Address(0x40 * line + x) ; //显示在第line行的第x位
	lcd_delay1ms(5) ;

	/*----2、将CGROM/CGRAM对应地址中的数据,显示在屏幕对应的位置---*/
	Write_Data(num) ; //显示CGRAM中8个自定义字符的第num个 num = 0-->7
					   //和显示CGROM中数据不同之处在于:不用和0x80相与

}


/******************************************************************************
 *	名称:Switch_Screen()
 *	功能:控制显示屏开关,(不显示光标)
 *	参数:unsigned char scr_key = 1:开 ; = 0:关
 *	返回:无
 ******************************************************************************/
 void Switch_Screen(unsigned char scr_key)
 {
 	lcd_delay1ms(50) ;
	if(scr_key == 1)
	{
		Write_Com(0x0c) ; //指令4 ,0000 1100 :开屏幕显示 ,无光标
	}

	if(scr_key == 0)
	{
		Write_Com(0x08) ; //指令4 ,0000 1100 :关屏幕显示
	}

 	lcd_delay1ms(50) ;
 }

 /******************************************************************************
 *	名称:Switch_Cursor()
 *	功能:控制光标开关和闪烁
 *	参数:unsigned char cursor_key 
 *	参数:unsigned char twinkle_key
 *	返回:无
 ******************************************************************************/
 void Switch_Cursor(unsigned char cursor_key , unsigned char twinkle_key)
 {
 	lcd_delay1ms(50) ;
	if(cursor_key == 1)
	{
		if(twinkle_key == 1)
		{
			Write_Com(0x0f) ; //指令4 ,0000 1111 :开屏幕显示,开光标,光标闪烁
		}
		else
		{
			Write_Com(0x0e) ; //指令4 ,0000 1110 :开屏幕显示 ,开光标		
		}
	}

	if(cursor_key == 0)
	{
		Write_Com(0x0c) ; //指令4 ,0000 1100 :开屏幕显示
	}

 	lcd_delay1ms(50) ;
 }

/******************************************************************************
 *	名称:Move_Screen()
 *	功能:控制屏幕整体左右移动
 *	参数:unsigned char r_l = 1 :右移  ; = 0 :左移
 *	参数:unsigned char move_bit_num  :屏幕向右或向左移动多少位
 *	参数:unsigned char move_delay :每移动一位后,延时多少 ms
 *	返回:无
 ******************************************************************************/
 void Move_Screen(unsigned char r_l,unsigned char move_bit_num,unsigned char move_delay)
 {
 	unsigned char i ;
 	lcd_delay1ms(move_delay) ;

	if(r_l == 1) //屏幕整体右移
	{
		for(i = 0 ; i < move_bit_num ; i++)
		{
			Write_Com(0x1c) ; //指令5 : 0001 1100 屏幕整体右移一位	
			lcd_delay1ms(move_delay) ;	
		}

	}

	if(r_l == 0) //屏幕整体左移
	{
		for(i = 0 ; i < move_bit_num ; i++)
		{
			Write_Com(0x18) ; //指令5 : 0001 1000 屏幕整体左移一位	
			lcd_delay1ms(move_delay) ;	
		}

	}
 }

/******************************************************************************
 *	名称:Dis_Str()
 *	功能:在显示HD44780控制的1602LCD上显示一个字符串
 *	参数:unsigned char line , unsigned char x 在LCD上显示的位置
 *	参数:unsigned char *str 要显示的字符串的指针(首地址)
 *	返回:无
 ******************************************************************************/
void Dis_Str(unsigned char line , unsigned char x , unsigned char *str)
{
	unsigned char i ;

	//1、 设置在LCD1602上显示字符的开始位置 : 从 第line行 坐标x 开始显示
	Write_Address(0x40 * line + x) ; lcd_delay1ms(5) ;	

	//2、 显示要显示的字符串
	i = 0 ;
	while(str[i] != '\0')
	{
		Write_Data(str[i]) ;
		i++ ;
		lcd_delay1ms(100) ;
	}
}

/******************************************************************************
 *	名称:Clear_Screen()
 *	功能:清屏
 *	参数:无
 *	返回:无
 ******************************************************************************/
 void Clear_Screen(void)
 {
	lcd_delay1ms(5) ;
	Write_Com(0x01) ; 
	lcd_delay1ms(5) ; 
 }



(2)、HD44780控制的1602LCD的头文件

/**************************************************************************************************
 * 	HD44780_1602LCD配置文件:HD44780_1602LCD.h
 *	本程序当时是依据AT89S52单片机开发板写的
 *	RS R/W E 这三位引脚分别和单片机引脚 P2^0 P2^1 P2^2 相连
 *	八位数据引脚DB0……DB7分别和单片机的P0端口的P0^0……P0^7相连 (BF位其实就对应DB7引脚和P0^7相连)
 *	将此文件来驱动1602LCD时,只需更改下面的位定义和数据线的端口号即可
 *	对于HD44780控制的1602LCD的详细资料和11条指令的描述参考一下连接
 *	http://blog.csdn.net/dragon12345666/article/details/22819827
 **************************************************************************************************/
#include<reg52.h>
#include<intrins.h>

sbit RS = P2^0 ;	//对象标志位: = 0(对象是指令或状态位);= 1(对象是数据)
sbit RW = P2^1 ;	//读写标志位: = 0(写);= 1(读)
sbit E  = P2^2 ;	//使能位:为 1 时,读写信息,为 负跳变 时,执行指令
sbit BF = P0^7 ;	//HD44780控制的1602LCD的 忙 状态位(只能通过指令读取)


extern bit Busy_Test(void) ;
extern void Clear_Screen(void) ;
//extern void lcd_delay1ms(int t) ;
extern void Dis_Str(unsigned char line , unsigned char x , unsigned char *str) ;
extern void Dis_User_char(unsigned char line , unsigned char x ,unsigned char num) ;
extern void HD44780_1602LCD_Init(void) ;
extern void Move_Screen(unsigned char r_l,unsigned char move_bit_num,unsigned char move_delay) ;
extern void Switch_Cursor(unsigned char cursor_key , unsigned char twinkle_key) ;
extern void Switch_Screen(unsigned char scr_key) ;
extern void Write_Address(unsigned char addr) ;
extern void Write_Com(unsigned char dictate) ;
extern void Write_Data(unsigned char char_data) ;
extern void Write_User_char(unsigned char addr_num , unsigned char *str) ;


(3)、整个程序主函数部分所在文件

/******************************************************************************
 *	说明:AT89S52芯片,12M晶振
 *	外设:HD44780控制的1602LCD:两行显示,每行最多显示40个预显示字符中的16个字符
 * 		  11条控制指令 
 *	本程序:在HD44780控制的1602LCD上显示2行字符串,按键K1,显示用户自定义字符
 *			开关屏幕、光标,屏幕显示左右移动,循环按键,循环显示
 ******************************************************************************/

#include <reg52.h>
#include <intrins.h>

#include "HD44780_1602LCD.h"


sbit K1 = P1^4 ;	//按键

//用户要显示的字符串
unsigned char code sys_str0[] = "Dragon_CSU" ;
unsigned char code sys_str1[] = "Good_Luck" ;

//用户自定义的字符编码方式:在8*8的点阵中选“右上角”的“5列*7行”点阵 存放数据
unsigned char code user_str0[] = {0x10,0x06,0x09,0x08,0x08,0x09,0x06,0x00};/* 自定义字符 ℃ */
unsigned char code user_str1[] = {0x1f,0x04,0x04,0x1f,0x04,0x04,0x1f,0x00};/* 自定义字符 王 */


/******************************************************************************
 *	名称:delay1ms()
 *	功能:延时1ms
 *	参数:int t
 *	返回:无
 ******************************************************************************/
void delay1ms(int t)
{
	unsigned char i ;

	while(t--)
	{
		for(i = 0 ; i < 125 ; i++)
		{
			;
		}
	}
}


/******************************************************************************
===============================================================================
                       void main(void)函数部分
===============================================================================
*******************************************************************************/
void main(void)
{
	//1、定义相关变量
//	unsigned char i ;

	//2、对HD44780控制的1602LCD进行初始化
	HD44780_1602LCD_Init() ;

	//3、在HD44780控制的1602LCD上显示信息
	while(1)
	{
		/*----3.1要显示的字符来源于CGROM的160个字符的库-----------------*/
			//3.1.1 根据需求选择是否清屏
			Clear_Screen() ;
	
			//3.1.2 在显示1602LCD上显示第一个字符串 从第1行第0位开始显示
				Dis_Str(0 , 0 , sys_str0) ; 
	
			//3.1.3 在显示1602LCD上显示第二个字符串	从第2行第0位开始显示
				Dis_Str(1 , 0 , sys_str1) ;
				
			//3.1.4 无按键按下,等待
			delay1ms(1000) ; 
			while(K1 == 1) { ; }	

		/*----3.2要显示的字符来源于CGRAM的8个用户自己定义的字符---------*/
			//3.2.1 将用户自定义的字符写入CGRAM中
			Write_User_char(0 , user_str0) ;
			Write_User_char(1 , user_str1) ;
				
			//3.2.2 在HD44780控制的1602LCD屏幕指定位置上显示自定义字符
			Dis_User_char(1 , 11 , 0x00) ;
			Dis_User_char(1 , 13 , 0x01) ;

			//3.2.3 无按键按下,等待
			delay1ms(1000) ; 
			while(K1 == 1) { ; }

		/*----3.3关闭屏幕------------------------------------------------*/
			//3.3.1 关闭屏幕
			Switch_Screen(0) ;
			//3.3.2 无按键按下,等待
			delay1ms(1000) ; 
			while(K1 == 1) { ; }

		/*----3.4打开屏幕------------------------------------------------*/
			//3.4.1 打开屏幕
			Switch_Screen(1) ;
			//3.4.2 无按键按下,等待
			delay1ms(1000) ; 
			while(K1 == 1) { ; }

		/*----3.5打开光标------------------------------------------------*/
			//3.5.1 打开光标
			Switch_Cursor(1 , 1) ;	//1,1:打开光标、闪烁 ;1,0:打开、不闪烁
			//3.5.2 无按键按下,等待
			delay1ms(1000) ; 
			while(K1 == 1) { ; }

		/*----3.6关闭光标------------------------------------------------*/
			//3.6.1 关闭光标
			Switch_Cursor(0 , 0) ;
			//3.6.2 无按键按下,等待
			delay1ms(1000) ; 
			while(K1 == 1) { ; }

		/*----3.7屏幕整体左移--------------------------------------------*/
			//3.7.1 左移16位,每移一位延时500ms
			Move_Screen(0 , 16 , 500) ;
			//3.7.2 无按键按下,等待
			delay1ms(1000) ; 
			while(K1 == 1) { ; }

		/*----3.8屏幕整体右移--------------------------------------------*/
			//3.8.1 左移16位,每移一位延时500ms
			Move_Screen(1 , 16 , 500) ;
			//3.8.2 无按键按下,等待
			delay1ms(1000) ; 
			while(K1 == 1) { ; }
	}			
		
}


/******************************************************************************
 *	名称:
 *	功能:
 *	参数:
 *	返回:
 ******************************************************************************/





















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值