LCD1602驱动(51单片机)

LCD1602介绍:
是一个只能显示字母、数字、符号的点阵型液晶模块。一行可以显示16个字符,可以显示两行,所以叫做1602。

图片:
在这里插入图片描述

硬件分析:

1602一共有16个引脚,其各个引脚的功能如下所示在这里插入图片描述

根据各个引脚的功能,需要设置如下电路(主芯片是AT89C52):
在这里插入图片描述
其中VO(VL)接的是一个电位器,你也可以接一个适当阻值的电阻连到GND。
RS-P26
RW-P25
E-P27
DB0~7接到P0~7
这十个引脚就是与1602通信的线路。

当硬件连接好后,就需要有配套的软件。

程序需要2步,缺一不可:
1、初始化1602,RS=0时发送初始化指令
2、将你要显示的数据发送给1602,此时RS=1;

程序发送数据是根据1602的驱动时序图来的,如图:
在这里插入图片描述
在控制方面,RS是决定你的发送内容是指令,还是数据,在初始化的时候RS=0,在显示数据的时候RS=1。RW脚为0(低电平),表示我要写数据。

根据上面的时序图,可以写出发送一个数据的函数,如下

void LcdWriteCom(uchar com)	  //写入命令
{
	LCD1602_E = 0;     //使能
	LCD1602_RS = 0;	   //选择发送命令
	LCD1602_RW = 0;	   //选择写入
	
	LCD1602_DATAPINS = com;     //放入命令,P0~P7
	Lcd1602_Delay1ms(1);		//等待数据稳定

	LCD1602_E = 1;	          //写入时序
	Lcd1602_Delay1ms(5);	  //保持时间
	LCD1602_E = 0;
}

LCD1602_DATAPINS定义的是P0端口,作用是根据com的值(8个bit)来给P0~7引脚赋予高低电平,通过高低电平发送给1602。

简单分析一下E这个引脚,准备发送数据时E=0,然后将数据赋给IO口,此时单片机的数据引脚已经是一个数据了。延时1ms等IO口稳定后,将E置1,告诉1602要读数据,延时5ms等1602读完,此时1602已经将数据存入内存里,最后将E脚置0。

1602的初始化
我这边初始化需要5条指令,来设置常用的功能。
1.功能设置指令
在这里插入图片描述

2.显示开关控制指令在这里插入图片描述

3.模式设置指令在这里插入图片描述

4.清屏指令在这里插入图片描述

5.数据指针起点
我们发给1602数据后,他会保存在SDRAM里。(H是16进制的表示)
在这里插入图片描述
所以我们第一行的16个数据就是00H到0FH,共16个。
第二行的数据从40H到4FH,也是16个。
要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符,例如第二行第一个字符的地址是 40H, 那么是否直接写入 40H 就可以将光标定位
在第二行第一个字符的位置呢?这样不行,因为写入显示地址时要求最高位 D7
恒定为高电平 1 所以实际写入的数据应该是 01000000B(40H)
+10000000B(80H)=11000000B(C0H)。
所以在程序里发送0x80来设置指针起点,0x00+0x80 = 0x80。

根据以上5条指令,就知道应该怎么初始化了,所以有如下程序:

void LcdInit()						  //LCD初始化子程序
{
 	LcdWriteCom(0x38);  //开显示  功能设置指令 
	LcdWriteCom(0x0c);  //开显示不显示光标  显示开关控制指令 
	LcdWriteCom(0x06);  //写一个指针加1  模式设置指令 
	LcdWriteCom(0x01);  //清屏  清屏指令 
	LcdWriteCom(0x80);  //设置数据指针起点 0x00+0x80 = 0x80
}

初始化完成后,就开始显示数据了。

发送显示数据的函数为LcdWriteData(与LcdWriteCom不同之处在于RS脚)

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;
}

使用一个for循环发送数据

	for(i=0;i<16;i++)
	{
		LcdWriteData(Disp[i]);	
	}

注意,你发送的数据必须是字符型的,如’1’, ‘a’ , ‘A’ , ’ ’ ,等。LCD会自动处理。
独立文件
lcd.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 
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

lcd.h

#ifndef __LCD_H_
#define __LCD_H_
/**********************************
当使用的是4位数据传输的时候定义,
使用8位取消这个定义
**********************************/
//#define LCD1602_4PINS

/**********************************
包含头文件
**********************************/
#include<reg52.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

main.c

/**************************************************************************************
*		              LCD1602液晶显示实验												  *
实现现象:下载程序后插上LCD1602液晶在开发板上,即可显示
注意事项:如果不想让点阵模块显示,可以将74HC595模块上的JP595短接片拔掉。																				  
***************************************************************************************/

#include "reg52.h"			 //此文件中定义了单片机的一些特殊功能寄存器
#include "lcd.h"

typedef unsigned int u16;	  //对数据类型进行声明定义
typedef unsigned char u8;

u8 Disp[]=" Pechin Science ";

/*******************************************************************************
* 函 数 名         : main
* 函数功能		   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void main(void)
{
	u8 i;
	LcdInit();
	for(i=0;i<16;i++)
	{
		LcdWriteData(Disp[i]);	
	}
	while(1);				
}

程序来自普中科技

附上完整工程
链接:https://pan.baidu.com/s/1q3HKwRNIsdu_qLvXDnGfGA
提取码:d1lq

  • 6
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
/************************ *************************************************** 程序名称:LCD.C 程序功能:LCD1602驱动程序 ****************************************************************************/ #include #include sbit RS = P2^0; sbit RW = P2^1; sbit E = P2^2; sbit DPORT = P0; const unsigned char NoDisp = 0; //无显示 const unsigned char NoCur = 1; //有显示无光标 const unsigned char CurNoFlash = 2; //有光标但不闪烁 const unsigned char CurFlash = 3; //有光标且闪烁 void LcdPos( unsigned char, unsigned char ); //确定光标位置 void LcdWd(unsigned char); //写字符 void LcdWc(unsigned char); //送控制字(检测忙信号) void LcdWcn(unsigned char); //送控制字子程序(不检测忙信号) void mDelay(unsigned char); //延时,毫秒数由j决定 void WaitIdle(); //正常读写操作之前检测LCD控制器状态 void SetCur(unsigned char para); //设置光标的4种状态 void WriteString(unsigned char *s, unsigned char xPos, unsigned char yPos); //向光标处写字符串 void LcdWc( unsigned char c ); //清屏 void WriteChar(unsigned char c, unsigned char xPos, unsigned char yPos); //向光标出处写字符 void RstLcd(); //LCD复位函数 /************************************************************** 函数名称:void WaitIdle() 功能:正常读写操作之前检测LCD控制器状态 **************************************************************/ void WaitIdle() { unsigned char temp; //定义临时变量 RS = 0; //RS=0输入指令,RS=1输入数据 RW = 1; //RW=1从LCD读取信息,RW=0向LCD写入指令或数据 E = 1; //E=1读取信息,E在下降沿从1到0执行指令 _nop_(); for(; ;) { temp = DPORT; temp &= 0x80; if ( temp == 0 ) //DB0--DB7全都是0 { break; } } E = 0; //执行指令 } /************************************************************** 函数名称:void mDelay(unsigned char j) 功能:延时程序,延时时间有变量j决定 **************************************************************/ void mDelay( unsigned char j ) { unsigned int i = 0; for( ; j>0; j-- ) { for (i=0; i<
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值