51单片机LCD1602

前言


        LCD1602(Liquid Crystal Display)液晶显示屏是一种字符型液晶显示模块,可以显示ASCII码的标准字符和其它的一些内置特殊字符,还可以有8个自定义字符。LCD1602主要是做调试用的,它可以帮助我们显示程序的执行结果,让程序在单片机外部可视化

     

规格参数


LCD1602主要参数:

  • 显示字符:16×2个字符
  • 工作电压:4.5~5V
  • 工作电流:2.0mA
  • 工作温度:-20°C~70°C
  • 模块最佳工作电压:5.0V
  • 单个字符尺寸2.95×4.35(W×Hmm)
  • 引脚:16脚

        LCD1602是一种点阵型的显示模块,总共有2行16列,也就是可以同时显示32个字符,每个字符都是由5*7的液晶矩阵显示,这样算下来总共有2*16*5*7等于1120颗点阵组成,然而只需要14个引脚即可控制它在任何位置显示任何字符:

第1脚:GND(接地)

第2脚:VSS(接电源+5v)

第3脚:VO(对比度调节电压)接高电平1时对比度最低,低电平0时对比度最高,可用电位器调节

第4脚:RS(数据/命令选择)接高电平1时选择数据寄存器,低电平0时选择指令寄存器

第5脚:R/W(读写选择)接高电平1时进行读操作,低电平0时进行写操作

第6脚:E(使能引脚)使能,接高电平1时读取信息,下降沿执行命令

第7~14脚:D0~D7(双向数据端)可以收发数据,是主要控制的引脚

15,16脚:分别为背光的正负极

内部构造及其原理


   

        LCD1602内置了CGRAM和CGROM字模库,里面包含了ASCLL码表的所有字符和一些特殊字符的字模数据,字模数据就是在5*7的点阵里点亮哪几个点可以显示其相应的字符,再由引脚控制输出在哪个位置上,即可完成显示丰富多样的内容的任务。这个过程很像数码管的显示,字模库就是数码管段选的数组,外部引脚控制输出在哪个位置就是数码管的位选,当然其中详细的流程要比数码管复杂得多。

        还有需要注意的一点是:我们想要显示的字符实际是先写在DDRAM(数据显示区)里的,再把DDRAM存储的数据对照字模库输出到屏幕上,而这个DDRAM的矩阵是40*2的,屏幕只有16*2,也就是说数据显示区可以存储两个半屏幕的数据,但是只能显示前16列,为什么要这样设计呢?这是因为芯片里有一个虚拟光标,可以通过指令来控制光标的移动,从而控制屏幕的移动,并且当移动到末尾又会重新回到起始位置,这样就可以实现屏幕循环滚动的效果。

        关于时序,由于我们在使用过程中几乎不会用到读数据的操作,所以这里只介绍写数据的指令:

        对照上面的引脚定义来分析此图,首先不难看出共有两种时序信号,分别是写指令和写数据(其实是四种,还有读指令和读数据)写指令是用来控制操作的,例如光标移动等,写数据就写入要显示的字符。当RS配置为为高电平1,R/W为低电平0时即为写数据模式,一旦检测到使能引脚E的上升沿跳变便开始写入D0~D7对应的数据,这样就完成了一次写数据,再不断循环此过程就完成了数据的写入,总的来说这个时序逻辑还是很简单易懂的。

        至于指令部分就不一一介绍了,可以参照下面的表格:

         函数的功能都是遵照表格上的指令来实现的,其实这款显示屏的功能还是相当丰富的!

程序源码


        程序部分不必过分深究,只需要知道有哪些函数,分别是什么功能,了解函数的参数类型,并且会用即可,一般都是封装成模块直接拿来调用的。

#include <REGX52.H>

//引脚定义
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_E=P2^7;
#define LCD_DataPort P0

void LCD_Delay()		//@12.000MHz 1ms
{
	unsigned char i, j;

	i = 2;
	j = 239;
	do
	{
		while (--j);
	} while (--i);
}

void LCD_WriteCommand(unsigned char Command)
{
	LCD_RS=0;
	LCD_RW=0;
	LCD_DataPort=Command;
	LCD_E=1;
	LCD_Delay();
	LCD_E=0;
	LCD_Delay();
}

void LCD_WriteData(unsigned char Data)
{
	LCD_RS=1;
	LCD_RW=0;
	LCD_DataPort=Data;
	LCD_E=1;
	LCD_Delay();
	LCD_E=0;
	LCD_Delay();
}

void LCD_Init(void)
{
	LCD_WriteCommand(0x38);
	LCD_WriteCommand(0x0C);
	LCD_WriteCommand(0x06);
	LCD_WriteCommand(0x01);
}

void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
	if(Line==1)
	{
		LCD_WriteCommand(0x80|(Column-1));
	}
	else
	{
		LCD_WriteCommand(0x80|(Column-1)+0x40);
	}
}

void LCD_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char)
{
	LCD_SetCursor(Line,Column);
	LCD_WriteData(Char);
}

void LCD_ShowString(unsigned char Line,unsigned char Column,unsigned char *String)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=0;String[i]!='\0';i++)
	{
		LCD_WriteData(String[i]);
	}
}

int LCD_Pow(int X,int Y)
{
	unsigned char i;
	int Result=1;
	for(i=0;i<Y;i++)
	{
		Result*=X;
	}
	return Result;
}

void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData('0'+Number/LCD_Pow(10,i-1)%10);
	}
}

void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
	unsigned char i;
	unsigned int Number1;
	LCD_SetCursor(Line,Column);
	if(Number>=0)
	{
		LCD_WriteData('+');
		Number1=Number;
	}
	else
	{
		LCD_WriteData('-');
		Number1=-Number;
	}
	for(i=Length;i>0;i--)
	{
		LCD_WriteData('0'+Number1/LCD_Pow(10,i-1)%10);
	}
}

void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	unsigned char SingleNumber;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		SingleNumber=Number/LCD_Pow(16,i-1)%16;
		if(SingleNumber<10)
		{
			LCD_WriteData('0'+SingleNumber);
		}
		else
		{
			LCD_WriteData('A'+SingleNumber-10);
		}
	}
}

void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData('0'+Number/LCD_Pow(2,i-1)%2);
	}
}

        下面是头文件和对应函数的说明:

#ifndef __LCD1602_H__
#define __LCD1602_H__

void LCD_Init(void);
void LCD_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,unsigned char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);

//LCD_Init()                   LCD1602初始化
//LCD_ShowChar()               显示单字符
//LCD_ShowString()             显示字符串
//LCD_ShowNum()                显示十进制数
//LCD_ShowSignedNum            显示有符号数
//LCD_ShowHexNum()             显示十六进制数
//LCD_ShowBinNum()             显示二进制数
#endif

        比如我们再在1行1列显示字符A,在1行3列显示字符串Hello,在1行9列显示数字66,在1行12列显示有符号数字-88,在2行1列显示十六进制数字0xA5,在2行4列显示二进制数字0xA5,在2行13列显示编码为0xDF的字符,在2行14列显示摄氏度字符,就可以这样写:

#include <REGX52.H>
#include "LCD1602.h"
#include "Delay.h"

void main()
{
	LCD_Init();						
	LCD_ShowChar(1,1,'A');		
	LCD_ShowString(1,3,"Hello");	
	LCD_ShowNum(1,9,66,2);			
	LCD_ShowSignedNum(1,12,-88,2);	
	LCD_ShowHexNum(2,1,0xA5,2);		
	LCD_ShowBinNum(2,4,0xA5,8);		
	LCD_ShowChar(2,13,0xDF);		
	LCD_ShowChar(2,14,'C');			
	while(1){}
}

显示效果:

总结


        LCD1602是学习51单片机较好的工具,也是初步了解寄存器和时序较好的选择,结合其他外设可以开发简单的密码锁,温度计等有趣的小项目。

  • 5
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

且看林地几华里

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值