LCD1602的学习与理解

文章目录

  • LCD1602的学习与理解
  • 一、LCD1602知识体系的结构
  • 二、初始化程序

# 前言

看过很多博主的文章,很多都讲得不是很清楚,很可能的原因就是,这些博主在写文章的时候,认为你有一定的基础认知了,才来看的。其实,大部分来找资料的不是小白就是没怎么学明白,脑袋一团浆糊才来找资料的人,结果,看了一些博主的文章,不但没看明白,反而脑袋里又多了一段浆糊。


下面我就自己的学习,整理了一下,该怎么去学习和理解LCD1602。

一、LCD1602知识体系的结构

先看一张我画的整个LCD1602知识体系的结构图


从这个图中,我就来一点一点的讲解吧,把这个图的每一部分了解清楚,这个模块也就理解清楚了。

  1. LCD1602,由两部分组成,分别是液晶显示屏,和HD44780芯片。液晶显示屏有2行,每行显示16个字符。HD44780芯片里面的东西就多了,上面图上的右半部分都是HD44780芯片的东西。

  2. 显示数据随机存储器 (Display Data RAM,简称DDRAM)

    DDRAM就是显示数据RAM,用来寄存待显示的字符代码。共80个字节,其地址和屏幕的对应关系如下表:

    也就是说想要在LCD1602屏幕的第一行第一列显示一个"A"字,就要向DDRAM的00H地址写入“A”字的代码就行了。但具体的写入是要按LCD模块的指令格式来进行的,后面我会说到的。那么一行可有40个地址呀?是的,在1602中我们就用前16个就行了。第二行也一样用前16个地址。对应如下:
    DDRAM 地址与显示位置的对应关系

    那么,每行40个字节,显示却只用了前面的16个,剩下的干嘛去了呢?剩下的那些是为了方便滚屏使用,具体操作也是可以通过指令来设置的。

  3. 字符生成只读存储器(Character Generator ROM,简称CGROM)

    我们知道文本文件中每一个字符都是用一个字节的代码记录的。一个汉字是用两个字节的代码记录。在 PC 上我们只要打开文本文件就能在屏幕上看到对应的字符是因为在操作系统里和 BIOS 里都固化有字符字模。什么是字模?就代表了是在点阵屏幕上点亮和熄灭的信息数据,例如“A”。CGROM中就存储着HD44780已经定义好的字符字模。

    上面这个就是HD44780里面的字符字模表,每个格子都有一个地址,比如“A”的地址是0100 0001,也就是41H,可以理解成41H这个地址里存放的是‘“A”的字模(也可以理解成字符编码,因为左边的这些字母数字基本上都是ASCII编码)。

  4. 字符生成随机存储器(Character Generator RAM,简称CGRAM)
    CGRAM用于编写CGROM中没有的字符,它的存储空间大小为64字节,在上面CGROM中可以看到,最左边有一列00H-0FH地址编码是供CGRAM使用的区域,标着有16个房间,实际上只有8个房间的地址编号可以使用(第8-16个房间地址与0-7房间地址等效)。如果自定义的是58的字符,那么一个字符需要8个字节来定义,最多就只能定义8个自定义字符,如果是定义510的字符,一个字符需要16字节,最多只能定义4个字符。注意,自定义的字符是存储在CGROM中,上表就有CGRAM自定义的字符的地址编码(可以理解成CGRAM是CGROM的一部分),CGRAM的64字节空间是用于存储自定义字符的,并不是地址编码,地址编码在CGROM中,这一点要搞清楚。

  5. 地址计数器(Address Counter,简称 AC)
    存储DDRAM的地址信息,也可以存储CGRAM的地址信息,在显示时,通过指令设置AC,让光标指向相应位置。

  6. 11个指令操作





    通过这11个指令可以看出,有些位是固定的,在写初始化程序的时候,只需要去找相应的控制指令,然后设置对应的位填入就行了。

二、初始化程序

先附上硬件电路图

通过LCD1602的的结构图,可以看出,指令的读写通过引脚E RW RS三个引脚控制,数据传输通过D0-D7。
E:使能控制,读写指令数据必须打开这个开关
RS:指令或数据,低电平是指令,高电平是数据
RW:读写控制,高电平是读,低电平是写

这两个引脚自由组合有四种可能

  1. 读指令:RS=0,RW=1;
  2. 读数据:RS=1,RW=1;
  3. 写指令:RS=0,RW=0;
  4. 写数据:RS=1,RW=0;

还有一点比较重要的就是,时序图!!!
无论是读写数据或是指令,都跟时序图有关,要看懂这个时序图,才能真正理解程序是怎样读写数据指令的。


下面以一个写命令的初始化函数为例

void Lcd_WriteCom(uchar com)  //1602写命令函数
{ P0=com;  //把命令字送入P2en=0; rs=0;            //选择指令寄存器rw=0;            //选择写_nop_();//一个机械周期       en=1;           //使能线电平变化,命令送入1602的8位数据口 delay(1);en=0;
}

看着时序图的写部分,再结合代码,来分析一下:
时序图,只用看中间的部分
E控制着整个写的过程,只有E拉高之后,指令才会写进去。

  1. 图中可以看到RS RW D0-D7的电平变化都在E的变化之前,所以,在写程序的时候,可以首先把数据怼上去,然后最后一个时序D0-D7就不用管了,只需要等待E电平拉高就行了。
  2. 接下来是设置RS RW E变成相应的电平,写指令的话,RS=0,RW=0,E先变为低电平,然后从时序图中可以看到,操作了RW,RS之后,要等待一个时间tsp1之后才能拉高使能端E的电平,从表中可以查到tsp1最小时间是30ns,这个时间很小,对于51单片机来说,不需要延时,因为51单片机的晶振差不多都是12MHz左右的,一条指令的时间在1us左右,远大于30ns,但对于运行速度较快的单片机,必须延时!!!
  3. 然后拉高E的电平,持续tpw的时间,对于51单片机来说,还是不用延时,但是为了代码规范,我还是加了延时的(E的高电平持续时间要比表格中的时间长就ok),然后拉低E的电平,表示这条指令写进了HD44780芯片当中了。

如果作为小白的你,不太明白着几句话,我建议你结合我给的示例代码和时序图,反复理解一下。

写数据的操作也这个是一样的,我会在文末给出初始化的代码。

下面在说一下忙检函数,主要是用于检测1602当前是否正在进行指令操作


void Busy(void)
{uchar temp=0;do{rw=1;rs=0;en=0;_nop_();en=1;delay(1);en=0;temp=P0;}while(temp&0x80);
}

忙检函数,实际上就是读操作,像我刚才叙述的写操作一样,代码写的顺序也是根据时序图来的,只是和写操作不一样的是,数据D0-D7是在E电平拉高后产生变化的,所以在初始化程序中,就不用管数据的变化,直接设置RW RS E 就行了,最后,说明一点,当E由高电平变为低电平后,数据就已经读取到P0口了,然后再把数据赋值给temp,检测最高位BF(忙标志位)的状态。
补充一下,BF这个位是由硬件决定的,只能读,不能通过软件写。

最后是,LCD1602的初始化函数

void lcd_init()              //1602初始化函数
{ delay(1);Lcd_WriteCom(0x38);       //8位数据,双列,5*7字形       Busy();Lcd_WriteCom(0x0c);      //开启显示屏,关光标,光标不闪烁 Busy();Lcd_WriteCom(0x06);    //显示地址递增,即写一个数据后,显示位置右移一位 Busy();Lcd_WriteCom(0x01);    //清屏 Busy();Lcd_WriteCom(0x80);   //设置数据指针起点
}

关于里面的数据,0x38,0x0c啥的,这时候就要去看前面的11个指令设置了,对应去找,这些数据怎么来的,相信你也一下子就理解了。

把我写的这些都读懂了,那么我相信你对1602的使用已经有了一个大致的了解了,如果还有什么不懂的,还是看1602的数据手册吧,这篇文章看完,你也应该能看懂数据手册了,细节方面,还是去数据手册里面在找找吧。

最后,附上一个简单的初始化代码
LCD1602.h

#ifndef __LCD1602_H__
#define __LCD1602_H__
#include<reg52.h>    //包含头文件
#include"intrins.h"
#define uint unsigned int  //预定义
#define uchar unsigned char void delay(uint n);
void Busy(void);
void Lcd_WriteCom(uchar com);
void Lcd_WriteData(uchar dat);
void lcd_init();
#endif

LCD1602.c

#include"lcd1602.h"sbit rs=P2^6;    //1602的数据/指令选择控制线
sbit rw=P2^5;        //1602的读写控制线
sbit en=P2^7;        //1602的使能控制线void delay(uint n)       //延时函数
{ uint x,y;  for(x=n;x>0;x--) for(y=110;y>0;y--);
} void Busy(void)
{uchar temp=0;do{rw=1;rs=0;en=0;_nop_();en=1;delay(1);en=0;temp=P0;}while(temp&0x80);
}void Lcd_WriteCom(uchar com)  //1602写命令函数
{ P0=com;  //把命令字送入P2en=0; rs=0;            //选择指令寄存器rw=0;            //选择写_nop_();//一个机械周期       en=1;           //使能线电平变化,命令送入1602的8位数据口 delay(1);en=0;
} void Lcd_WriteData(uchar dat)        //1602写数据函数
{ P0=dat;        //把要显示的数据送入P0en=0; rs=1;        //选择数据寄存器 rw=0;        //选择写 _nop_();//一个机械周期   en=1;        //使能线电平变化,数据送入1602的8位数据口 delay(1);en=0;
} void lcd_init()              //1602初始化函数
{ delay(1);Lcd_WriteCom(0x38);       //8位数据,双列,5*7字形       Busy();Lcd_WriteCom(0x0c);      //开启显示屏,关光标,光标不闪烁 Busy();Lcd_WriteCom(0x06);    //显示地址递增,即写一个数据后,显示位置右移一位 Busy();Lcd_WriteCom(0x01);    //清屏 Busy();Lcd_WriteCom(0x80);   //设置数据指针起点
}

main.c


#include"lcd1602.h"/*P0口接1602的D0~D7*/
uchar code table[]="ni hao";             //要显示的内容放入数组tablevoid main()            //主函数
{     uchar m=0; lcd_init();       //液晶初始化 Lcd_WriteCom(0x80);   //显示地址设为80H(即00H,)上排第一位       for(m=0;m<6;m++)     //将table[]中的数据依次写入1602显示 { Lcd_WriteData(table[m]);           delay(200); } while(1);        //动态停机
}

下次再写自定义字符,和动态显示的相关文章吧。

LCD1602的学习与理解相关推荐

  1. 《C++应用程序性能优化::第五章动态内存管理》学习和理解

    <C++应用程序性能优化::第五章动态内存管理>学习和理解 说明:<C++应用程序性能优化> 作者:冯宏华等 2007年版. 2010.8.29 cs_wuyg@126.com ...

  2. 【赠书】新手速递!深度学习视频理解!

    ‍‍ 视频理解是当前计算机视觉研究领域中备受学术界和工业界关注的方向,随着视频行业的高速发展,如何利用 AI 技术更好地对视频内容进行理解变得越来越重要.今天要给大家介绍的书是<深度学习视频理解 ...

  3. 9月21日云栖精选夜读 | 如何优雅地从四个方面加深对深度学习的理解

    在今年的 ICML 上,深度学习理论成为最大的主题之一.会议第一天,Sanjeev Arora 就展开了关于深度学习理论理解的教程,并从四个方面分析了关于该领域的研究:非凸优化.超参数和泛化.深度的意 ...

  4. 《C++应用程序性能优化::第二章C++语言特性的性能分析》学习和理解

    <C++应用程序性能优化::第二章C++语言特性的性能分析>学习和理解 说明:<C++应用程序性能优化> 作者:冯宏华等 2007年版.最近出了新版,看了目录,在前面增加了一章 ...

  5. 如何优雅地从四个方面加深对深度学习的理解

    在今年的 ICML 上,深度学习理论成为最大的主题之一.会议第一天,Sanjeev Arora 就展开了关于深度学习理论理解的教程,并从四个方面分析了关于该领域的研究:非凸优化.超参数和泛化.深度的意 ...

  6. [机器学习]正则化项L1和L2的学习与理解

    正则化项L1和L2的学习与理解 一,正则化(Regularization) 稀疏模型与特征选择的关系 二, 为什么L1产生稀疏模型而L2可以防止过拟合 1, L1和L2正则化的直观理解 正则化和特征选 ...

  7. 递归求全排列的学习与理解

    递归求全排列 全排列: 从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列.当m=n时所有的排列情况叫全排列. 例题: 输出自然数 1 到n所有 ...

  8. Faster RCNN原理篇(一)——Bounding-Box Regression边界框回归的学习和理解

    Bounding-Box Regression边界框回归的学习和理解 引言 1. (Why?)为何要做边框回归? 2. (What?)什么是边框回归? 3. (How?)如何实现边框回归? 4. 边框 ...

  9. 物联网方面用哪种计算机语言,物联网学习及理解 - 编程语言

    物联网学习及理解(来自一个物联网专业学生的心得)什么是物联网 物联网能做什么一.物联网运用领域 二.物联网发展趋势 物联网怎么实现一.局域网内的物联网 二.广域网内的物联网 总结 在开始写这篇博客之前 ...

  10. 凸优化教程学习与理解(mark)

    凸优化教程学习与理解(mark) 1. 什么是凸优化 1.1 优化问题的一般形式 1.2 优化问题的几种分类 1.2.1. 早期划分为线性规划和非线性规划: 1.2.2 凸规划和非凸规划; 1.2.3 ...

最新文章

  1. 上海有线通共享上网设置(解决大部分局域网问题)
  2. Heap Allocation Profiles (heap=sites)
  3. spark streaming 5: InputDStream
  4. ilpimage to bitmap
  5. java监控数据库的增量_【安德鲁斯】基于脚本的数据库quot;增量更新quot;,如果不改变,每次更新java代码、!...
  6. SAP UI5 应用的中文乱码问题
  7. tomcat 开启远程debug
  8. 用Paint Tool SAI绘制漫画
  9. C#:解决WCF中服务引用 自动生成代码不全的问题。
  10. lisp批量生成轴线_求批量插入图纸的程序 - AutoLISP/Visual LISP 编程技术 - CAD论坛 - 明经CAD社区 - Powered by Discuz!...
  11. Linux学习笔记003----linux yum命令详解
  12. cmd上如何运行php文件,cmd - php文件在命令行可以顺利运行,在浏览器上无法正常运行...
  13. 【统计分析】3 空间点模型
  14. opencv怎么2个摄像头_内脏脂肪过高怎么办?从2个方法入手,坚持3个月甩掉小肚腩...
  15. C++ 结构体内存对齐
  16. 为什么互联网公司崇尚扁平化管理?
  17. java罗盘说明_综合罗盘各层应用说明
  18. 前度字符串转数组_java中的hashcode 前度刘郎
  19. 中小软件企业管理存在的问题
  20. Python控制鼠标和键盘-PyAutoGUI

热门文章

  1. SQLyog安装教程
  2. SQLyog 安装和配置教程
  3. ev3编码软件linux,机器人编程软件下载 乐高ev3机器人编程软件(LEGO MINDSTORMS EV3 Home Edition)V1.3.1 中文安装版 下载-脚本之家...
  4. SHA256 算法 加密文件、防文件篡改、文件校验
  5. office和计算机基础,国二ms才office计算机基础知识.ppt
  6. UEFI shell控制台向.efi文件传入参数--通过protocol实现
  7. python中文版下载-python3.8.1汉化版
  8. Python模块:win32com用法详解
  9. 追剪算法C语言,基于PLC的追剪控制系统设计.doc
  10. MAC地址厂商信息查询