51单片机之 LCD1602液晶显示屏

一、LCD1602的使用
51单片机之 LCD1602液晶显示屏_第1张图片
从上图可知,不是所有的地址都可以直接用来显示字符数据,只有第一行中的 00-0F,第二行中的 40-4F 才能显示,其他地址只能用于存储。
51单片机之 LCD1602液晶显示屏_第2张图片
从上图可以看到,以上给的时间参数全部是 ns 级别的,而 51 单片机的机器周期是 1us,指令周期是 2-4 个机器周期,所以即便在程序里不加延时程序,也可以很好的配合 LCD1602 的时序要求了。

LCD1602 操作步骤如下所示:
(1)初始化
(2)写命令(RS=L),设置显示坐标
(3)写数据(RS=H)
在此,不需要读出它的数据的状态或者数据本身。所以只需要看两个写时序:
① 当要写指令字,设置 LCD1602 的工作方式时:需要把 RS 置为低电平,RW置为低电平,然后将数据送到数据口 D0~D7,最后 E 引脚一个高脉冲将数据写入。
② 当要写入数据字,在 1602 上实现显示时:需要把 RS 置为高电平,RW 置为低电平,然后将数据送到数据口 D0~D7,最后 E 引脚一个高脉冲将数据写入。
写指令和写数据,差别仅仅在于 RS 的电平不一样而已。

二、硬件设计
51单片机之 LCD1602液晶显示屏_第3张图片
这里原理图是使用的 8 位 LCD1602 接口设计,从上图中可以看出,该电路是并不是独立的, LCD1602 的 8 位数据口 DB0-DB7与单片机的 P00-P07 管脚连接,LCD1602 的 RS、RW、E 脚与单片机的 P26、P25、P27 管脚连接。RJ1 是一个电位器,用来调节 LCD1602 对比度即显示亮度。

1、编写lcd.h

#ifndef _lcd_H
#define _lcd_H

#include "public.h"


//#define LCD1602_4PINS


#ifndef uchar
#define uchar unsigned char
#endif

#ifndef uint 
#define uint unsigned int
#endif


#define LCD1602_DATAPINS P0
sbit LCD1602_E=P2^7;
sbit LCD1602_RW=P2^5;
sbit LCD1602_RS=P2^6;


void LCD_WriteCmd(u8 cmd);
void LCD_WriteData(u8 dat);
void LcdInit();
void LCD_Clear();
void LCD_Dispstring(u8 x,u8 line,u8 *p);


#endif

2、编写lcd.c

#include "lcd.h"

void Lcd1602_Delay1ms(uint c)
{
    uchar a,b;
	for (; c>0; c--)
	{
		 for (b=199;b>0;b--)
		 {
		  	for(a=1;a>0;a--);
		 }      
	}
    	
}

#ifndef 	LCD1602_4PINS
void LCD_WriteCmd(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 LCD_WriteCmd(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;

//	Lcd1602_Delay1ms(1);
	LCD1602_DATAPINS = com << 4; 
	Lcd1602_Delay1ms(1);

	LCD1602_E = 1;
	Lcd1602_Delay1ms(5);
	LCD1602_E = 0;
}
#endif
	   
#ifndef 	LCD1602_4PINS		   
void LCD_WriteData(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 LCD_WriteData(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;

	LCD1602_DATAPINS = dat << 4; 
	Lcd1602_Delay1ms(1);

	LCD1602_E = 1;
	Lcd1602_Delay1ms(5);
	LCD1602_E = 0;
}
#endif
	   
#ifndef		LCD1602_4PINS
void LcdInit()
{
 	LCD_WriteCmd(0x38);
	LCD_WriteCmd(0x0c);
	LCD_WriteCmd(0x06);
	LCD_WriteCmd(0x01); 
	LCD_WriteCmd(0x80); 
}
#else
void LCD_Init()	
{
	LCD_WriteCmd(0x32);	
	LCD_WriteCmd(0x28);	 
	LCD_WriteCmd(0x0c);  
	LCD_WriteCmd(0x06); 
	LCD_WriteCmd(0x01); 
	LCD_WriteCmd(0x80);  
}
#endif



void LCD_Clear()
{
	LCD_WriteCmd(0x01);
	LCD_WriteCmd(0x80);	
}


void LCD_Dispstring(u8 x,u8 line,u8 *p)	  
{
	char i=0;
	if(line<1)
	{	
		while(*p!='\0')
		{
			if(i<16-x)
			{
				LCD_WriteCmd(0x80+i+x);	
			}
			else
			{
				LCD_WriteCmd(0x40+0x80+i+x-16);	
			}
			LCD_WriteData(*p);
			p++;
			i++;	
		}	
	}
	else
	{
		while(*p!='\0')
		{
			if(i<16-x)
			{
				LCD_WriteCmd(0x80+0x40+i+x);	
			}
			else
			{
				LCD_WriteCmd(0x80+i+x-16);	
			}
			LCD_WriteData(*p);
			p++;
			i++;	
		}	
	}		
}

3、编写main.c

#include "reg52.h"
#include "lcd.h"

typedef unsigned int ui;
typedef unsigned char uc;

uc disp[]="love story";


void main()
{
	ui i;
	LcdInit();
	for(i=0;i<16;i++)
	{
		LCD_WriteData(disp[i]);
	}
	while(1);
}

注:
在程序中我们可以看到如下程序框架:

#ifndef LCD1602_4PINS 
          ...程序段 1...
#else 
          ...程序段 2... 
#endif 

这个是条件选择编译结构,意思是:如果没有定义 LCD1602_4PINS 则执行程序段 1,否则执行程序段 2。

你可能感兴趣的:(单片机)