找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 24340|回复: 8
收起左侧

完全解读lcd1602基础接口及C51实现滚动显示

[复制链接]
ID:108628 发表于 2016-3-13 13:20 | 显示全部楼层 |阅读模式
第一次写教程哈,多多包涵/羞射

先介绍下lcd1602芯片,LCD1602 分为带背光和不带背光两种,基控制器大部分为 HD44780,带背光的比不带背光的厚,是否带背光在应用中并无差别.

字符型液晶显示模块是一种专门用于显示字母、数字、符号等点阵式LCD,目前常用16*1,16*2,20*2和40*2行等的模块。lcd1602即为1602字符型液晶显示器为例,介绍其用法。一般1602字符型液晶显示器实物如图所示。

正面


背面


LCD1602主要技术参数:

显示容量:16×2个字符

芯片工作电压:4.5—5.5V

工作电流:2.0mA(5.0V)

模块最佳工作电压:5.0V

字符尺寸:2.95×4.35(W×H)mm

引脚功能说明

LCD1602采用标准的14脚(无背光)或16脚(带背光)接口,各引脚接口说明如表所示:

各引脚接口


第1脚:VSS为地电源。

第2脚:VDD接5V正电源。

第3脚:VL为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。

第4脚:RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。

第5脚:R/W为读写信号线,高电平时进行读操作,低电平时进行写操作。当RS和R/W共同为低电平时可以写入指令或者显示地址,当RS为低电平R/W为高电平时可以读忙信号,当RS为高电平R/W为低电平时可以写入数据。

第6脚:E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。

第7~14脚:D0~D7为8位双向数据线。

第15脚:背光源正极。

第16脚:背光源负极。


LCD地址映射图


注释:1602为2行16列,屏幕所能显示的地址为00H~0FH(第一行),40H~4FH(第二行),其他地址可以存储待显示的数据。这就给我们的花样显示提供了条件哈:-D



运行时序图:



注释:这里的读操作指的是C51读1602的总线数据,RS=0,RW=1的时候,E给高电平则可以读到显示屏的状态,这个功能一般用于读忙,除了初始化之外,每次对1602进行读写操作都要读忙检测,当总线最高为STAD7=1则为繁忙,禁止读写操作。



注释:这里指的是C51往1602写数据/命令,通过使能E的高脉冲写入,在E的下降沿就执行写入的命令或者显示写入的数据。


接下来简要介绍下1602的相关指令

指令表(详细命令请查阅相关手册)


常用命令   :0x80+0xdd:dd为地址,这条命令用于设置显示起点坐标

                   0x0c            :开显示,无光标,光标不闪烁 。一般做带键盘输入的才加入光标,如计算器。常用的计量显示不显示光标。

                    0x06           :写一个数据,地址指针加1,由1602地址表可以看出,实际上就是设置成从左往右写数据而已。

                    0x38           : 设置显示模式,16x2显示 5x7点阵,8位数据接口。端口不够用时,这个命令也可以换用4位数据接口的。

                    0x01           :清屏。


电路连接图

这里用的带背光的1602


接下来写相关子程序:

//写入命令子函数

void LcdWriteCom(unsigned char com)

{

  LCD_RS=0;

  LCD_RW=0;

  LCD_GPIO=com;

  delay1ms(1);

  LCD_E=1;

  delay1ms(1);

  LCD_E=0;

}

//写入数据子函数

void LcdWriteData(unsigned char dat)

{

  LCD_RS=1;

  LCD_RW=0;

  LCD_GPIO=dat;

  delay1ms(1);

  LCD_E=1;

  delay1ms(1);

  LCD_E=0;

}

//读忙子函数

bit LCD_bz(void)

{

  bit bz;

  LCD_RS=0;

  LCD_RW=1;

  LCD_E=1;

  delay1ms(10);

  P0=0xff;           //C51单片机读引脚要先置高电平,原因不赘述,很多资料没有这一步骤,大家格外注意下

  bz=(bit)(LCD_GPIO&0x80);

  LCD_E=0;

  return bz;

}


//延时子程序

void delay1ms(unsigned int t)

{

  unsigned int i,j;              //节约内存起见,建议用uchar,由于后面要做动态显示,为了满足显示效果,这里用了uint

  for(i=0;i

  {

    for(j=0;j<300;j++);

  }

}

//初始化显示屏程序

void LcdInit()

{

  LcdWriteCom(0x38);//显示模式2行16列

  LcdWriteCom(0x0c);//开显示 无光标 不闪烁

  LcdWriteCom(0x06);//写一个指针加1

  LcdWriteCom(0x01);//清屏

  LcdWriteCom(0x80);//设置(0,0)为起点

}


主程序:

//我们要把第一行做成一个16字符固定显示,第二行做成滚动显示25字符

//这里采用的是1602指针右移的基础命令而不是整屏右移命令

#include

#define LCD_GPIO  P0

void LcdWriteCom(unsigned char); //写入命令子函数声明

void LcdWriteData(unsigned char);//写入数据子函数声明

void LcdInit();//显示屏初始化子函数声明

void delay1ms(unsigned int);//延时函数声明

bit LCD_bz(void);//读忙函数声明

sbit LCD_RW=P2^5;

sbit LCD_RS=P2^6;

sbit LCD_E=P2^7;

unsigned char displayDate1[]="    I'm Cesar   ";//一共16个字符(包括空格在内)

unsigned char displayDate2[]=" Please add QQ775222573  ";//一共25个字符

void main(void)

{

  unsigned char i=0,j=0,n=0;

  LcdInit();

LcdWriteCom(0x80);//设置坐标为第一行第一个字符

for(i=;i<16;i++)

{

   LcdWriteData(displayDate1[ i]);

}

while(1)

  {

if(LCD_bz())

      continue;//读忙,结束本次循环


LcdWriteCom(0x80+0x40);//设置第二行第一个字符起点

for(j=n;j<25+n;j++)//我们没有进行整屏右移,但是我们进行了数组右移O(∩_∩)O~

{

   LcdWriteData(displayDate2[j]);

}

      n++;//数组的显示起点右移,这样实现了滚动

if(n>=(25-15))//当显示移到最右边时,停顿片刻,返回起点再次循环

   {

         n=0;

         delay1ms(2000);

        }

      delay1ms(600);

  }

}

下载到C51调试结果:





好了,本次教程结束,写了一个上午,吃饭去了/(ㄒoㄒ)/~~。

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:104361 发表于 2016-8-29 14:37 | 显示全部楼层
看着很不错,拿来研究下
回复

使用道具 举报

ID:161933 发表于 2017-2-18 14:56 | 显示全部楼层
//读忙子函数
bit LCD_bz(void)
{
  bit bz;
  LCD_RS=0;
  LCD_RW=1;
  LCD_E=1;
  delay1ms(10);
  P0=0xff;           //C51单片机读引脚要先置高电平,原因不赘述,很多资料没有这一步骤,大家格外注意下
  bz=(bit)(LCD_GPIO&0x80);
  LCD_E=0;
  return bz;
}

这个读忙子函数的作用就是bz=(bit)(LCD_GPIO&0x80),取LCD_GPIO 的最高位,返回给bz?为什么LCD_GPIO的最高位就能反映LCD的忙闲状态呢?


回复

使用道具 举报

ID:161933 发表于 2017-2-18 14:59 | 显示全部楼层
while(1)
  {
if(LCD_bz())
      continue;//读忙,结束本次循环

主程序中,加入这个if(LCD_bz())函数的作用是什么,不加会怎样呢?
continue;跳转到哪里去了?
回复

使用道具 举报

ID:227453 发表于 2017-8-27 10:19 | 显示全部楼层
if(n>=(25-15))//当显示移到最右边时,停顿片刻,返回起点再次循环
请问这句里面的25-15是怎么来的,怎么理解
回复

使用道具 举报

ID:560111 发表于 2019-6-17 21:53 | 显示全部楼层
我想问一下那个定义cmd和data时的gpio是什么啊
回复

使用道具 举报

ID:440312 发表于 2019-6-21 09:41 | 显示全部楼层
有完整仿真电路吗
回复

使用道具 举报

ID:440312 发表于 2019-6-25 09:13 | 显示全部楼层
liquidlin 发表于 2019-6-17 21:53
我想问一下那个定义cmd和data时的gpio是什么啊

cmd是指令,data是数据,gpio在哪没找到,还有,我猜你在做x,左右上下滚动显示,找到能分享一下嘛
回复

使用道具 举报

ID:440312 发表于 2019-9-30 08:14 来自手机 | 显示全部楼层
DAFAWW 发表于 2019-6-25 09:13
cmd是指令,data是数据,gpio在哪没找到,还有,我猜你在做x,左右上下滚动显示,找到能分享一下嘛

刚刚看到,找到了,我发了帖子,你可以去看看
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表