【51单片机快速入门指南】6.1:LCD1602的八线、四线控制及自定义符号,完美兼容Proteus仿真

发布者:caoxians4589最新更新时间:2022-07-14 来源: csdn关键字:51单片机  LCD1602 手机看文章 扫描二维码
随时随地手机看文章

普中51-单核-A2

STC89C52

Windows 10 20H2

Proteus 8 Frofessional v8.9 SP2

Keil uVision V5.29.0.0

PK51 Prof.Developers Kit Version:9.60.0.0


硬知识

       摘自《通用1602 液晶显示模块使用手册》、《液晶LCD1602(中文资料)—— ball 2010-5-13整理》


显示特性

       单5V电源电压,低功耗、长寿命、高可靠性

       内置192种字符(160个5x7点阵字符和32个5x10点阵字符)

       具有64个字节的自定义字符RAM,可自定义8个5x8点阵字符或四个5x11点阵字符

       显示方式:STN、半透、正显

       驱动方式:1/16DUTY,1/5BIAS

       视角方向:6点

       背光方式:底部LED

       通讯方式:4位或8位并口可选

       标准的接口特性,适配MCS1和M6800系列MPU的操作时序。


接口定义

在这里插入图片描述

操作时序

写操作时序

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

读操作时序

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

寄存器

       本模块内部具有两个8位寄存器:指令寄存器(IR)和地址寄存器(DR),用户可以通过RS和R/W输入信号的组合选择指定的寄存器,进行相应的操作。下表中列出了组合选择方式。

在这里插入图片描述

       指令寄存器IR,内部存储DDRAM和CGRAM中的数据显示的指令代码和地址信息,只能由MPU对其执行写操作:

       数据寄存器DR,内部暂时存储MPU与模块内部DDRAM和CGRAM之间的传送数据,内部操作使DR与DDRAM或者CGRAM之间的数据传送自动进行:


在这里插入图片描述

忙标志位BF

       忙标志BF-1时,表明模块正在进行内部操作,此时不接受任何外部指令和数据。当Rs-0,RW-1以及E为高电平时,BF输出到DB7,每次操作之前最好先进行状态字检测,只有在确认BF-0之后,MPU才能访问模块


地址计数器(AC)

       AC地址计数器是DDRAM或者CGRAM的地址指针。随着IR中指令码的写入,指令码中携带的地址信息自动送入AC中,并行做出AC作为DDRAM的地址指针还是CGRAM的地址指针的选择。

       AC具有自动加1或者减1的功能。当DR与DDRAM或者CGRAM之间完成一次数据传后,AC自动会加1或减1,在RS=0,R/W=1且E为高电平时,AC的内容送到DB6 ~ DB0;

在这里插入图片描述

显示数据寄存器(DDRAM)

       DDRAM存储显示字符的字符码,其容量的大小决定着模块最多可显示的字符数目.DDRAM地址与LCD显示屏上的显示位置的对应关系如下:

在这里插入图片描述

       执行显示移位操作时,对应的DDRAM地址也发生移位,以每行16个字符的显示为例,移位前后的地址对应关系如下:

在这里插入图片描述

CGROM

       HD44780内置了192个常用字符的字模,存于字符产生器CGROM(Character Generator ROM)中。在CGROM中,模块已经以8位二进制数的形式,生成了5x8点阵的字符字模组字符字模(一个字符对应一组字模),字符字模是与显示字符点阵相对应的8x8矩阵位图数据(与点阵行相对应的矩阵行的高三位为“0"),同时每一组字符字模都有一个由其在CGROM中存放地址的高八位数据组成的字符码对应。

在这里插入图片描述

CGRAM

       另外还有8个允许用户自定义的字符产生RAM,称为CGRAM(Character Generator RAM)

       就单屏结构的模块而言,字符码地址范围为00H ~ FFH,其中00H ~ 07H字符码与用户在CGRAM中生成的自定义图形字符的字模组相对应:至于双屏或者多屏结构的模块,由于各显示屏结构部分的工作分别由独立的使能信号E控制,因而各结构部分间字符的发生互不影响,每一显示屏结构部分的字符码地址范围为00H ~ FFH,其中00H ~ 07H字符码与用户在CGRAM中生成的自定义图形字符的字模组相对应。


指令

清屏指令

在这里插入图片描述

光标归位指令

在这里插入图片描述

进入模式设置指令

在这里插入图片描述

显示开关控制指令

在这里插入图片描述

设定显示屏或光标移动方向指令

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

功能设定指令

在这里插入图片描述

设定CGRAM地址指令

在这里插入图片描述

设定DDRAM地址指令

在这里插入图片描述

读取忙信号或AC地址指令

在这里插入图片描述

数据写入DDRAM或CGRAM指令


在这里插入图片描述

从 CGRAM或DDRAM读出数据的指令

在这里插入图片描述

示例程序

       stdint.h见【51单片机快速入门指南】1:基础知识和工程创建

在这里插入图片描述

LCD1602.c

#include

#include "stdint.h"

#include "LCD1602.h"


//******************以下内容移植时需修改******************


void delay_ms(int i);


#define LCD1602_Port P0


sbit RS_Pin = P2 ^ 6;//寄存器选择位,RS位

sbit WR_Pin = P2 ^ 5;//读写选择位,RW

sbit EN_Pin = P2 ^ 7;//使能信号位,E位


void LCD1602_Delay()

{

//主频快就加延时

}


void LCD1602_RS_H()

{

RS_Pin = 1;

}


void LCD1602_RS_L()

{

RS_Pin = 0;

}


void LCD1602_WR_H()

{

WR_Pin = 1;

}


void LCD1602_WR_L()

{

WR_Pin = 0;

}


void LCD1602_EN_H()

{

EN_Pin = 1;

}


void LCD1602_EN_L()

{

EN_Pin = 0;

}


void LCD1602_Write_Port(uint8_t Data)

{

#ifdef USE_4_Pin

LCD1602_Port &= 0x0F;

LCD1602_Port |= (Data << 4);

#else

LCD1602_Port = Data;

#endif

}


uint8_t LCD1602_Read_Port()

{

#ifdef USE_4_Pin//4线下好像没有意义

return 0;

#else

return LCD1602_Port;

#endif

}


//******************以上内容移植时需修改******************


unsigned char code LCD1602_DIY_Char[64]=//8个自定义字符 地址为0x00~0x07

{

0x02,0x04,0x0F,0x12,0x0F,0x0A,0x1F,0x02,//年

0x0F,0x09,0x0F,0x09,0x0F,0x09,0x09,0x11,//月

0x1F,0x11,0x11,0x1F,0x11,0x11,0x1F,0x00,//日

0x16,0x09,0x08,0x08,0x08,0x09,0x06,0x00,//℃

0x00,0x11,0x0A,0x04,0x0A,0x11,0x00,0x00,//×

0x00,0x04,0x00,0x1F,0x00,0x04,0x00,0x00,//÷

0x00,0x0E,0x11,0x11,0x11,0x0A,0x1B,0x00,//Ω

0x00,0x11,0x11,0x11,0x19,0x16,0x10,0x00,//μ

};


/*****************************************************

函数功能:判断液晶模块的忙碌状态

返回值:1: 忙碌; 0: 不忙

***************************************************/

uint8_t LCD1602_Busy_Test(void)

{

#ifdef USE_4_Pin

delay_ms(2);

return 0;

#else

return ((LCD1602_Operation(0, 1, 0) & 0x80) && 1);

#endif

}


uint8_t LCD1602_Operation(uint8_t Cmd_Data_Flag, uint8_t Write_Read_Flag, uint8_t Data)

{

if(Cmd_Data_Flag)

LCD1602_RS_H();

else

LCD1602_RS_L();

if(Write_Read_Flag)

LCD1602_WR_H();

else

LCD1602_WR_L();

LCD1602_Delay();//给硬件反应时间

if(Write_Read_Flag)

{

LCD1602_EN_H();

LCD1602_Delay();//给硬件反应时间

Data = LCD1602_Read_Port();

}

else

{

LCD1602_EN_L();

LCD1602_Write_Port(Data);

LCD1602_Delay();//给硬件反应时间

LCD1602_EN_H();

LCD1602_Delay();//给硬件反应时间

}

LCD1602_EN_L();

return Data;

}


/*****************************************************

函数功能:将一个字节写入液晶模块

入口参数:Byte 字节, Cmd_Data_Flag 0为命令, 1为数据

***************************************************/

void LCD1602_Write_Byte(uint8_t Byte, uint8_t Cmd_Data_Flag)

{

while (LCD1602_Busy_Test());//如果忙就等待

#ifdef USE_4_Pin

LCD1602_Operation(Cmd_Data_Flag, 0, Byte >> 4);

while (LCD1602_Busy_Test());

LCD1602_Operation(Cmd_Data_Flag, 0, Byte & 0x0F);

#else

LCD1602_Operation(Cmd_Data_Flag, 0, Byte);

#endif

}


void LCD1602_DIY_Char_Init(void)

{

unsigned char i;

LCD1602_Write_Byte(LCD1602_Set_CGRAM_Addr, 0);//开始写入你要显示的自定义字符、汉字代码

for(i = 0; i < 64; i++)

{

LCD1602_Write_Byte(LCD1602_DIY_Char[i], 1);//开始写入你要显示的自定义字符、汉字代码

}

}


/*****************************************************

函数功能:指定字符显示的实际地址

入口参数:row 行:0或1 col:列

***************************************************/

void LCD1602_Write_Address(uint8_t row, uint8_t col)

{

if(row)

LCD1602_Write_Byte(col | 0xc0, 0);

else

LCD1602_Write_Byte(col | 0x80, 0);//显示位置的确定方法规定为"80H+地址码x"

}


void LCD1602_Write_Str(char *Str)

{

    while (*Str)//检测字符串结束标志

    {

        LCD1602_Write_Byte(*Str++, 1);//发送当前字符

    }

}


/*****************************************************

函数功能:对LCD的显示模式进行初始化设置

***************************************************/

void LCD1602_Init(void)

{

#ifdef USE_4_Pin

LCD1602_Write_Byte(LCD1602_Cursor_Return, 0);

LCD1602_Write_Byte(LCD1602_Config | LCD1602_4PIN | LCD1602_2Row | LCD1602_5X7, 0);

#else

LCD1602_Write_Byte(LCD1602_Config | LCD1602_8PIN | LCD1602_2Row | LCD1602_5X7, 0);

#endif

LCD1602_Write_Byte(LCD1602_Display_Switch | Display_Enable | Cursor_Enable | Cursor_Blink_Enable, 0);

LCD1602_Write_Byte(LCD1602_Cursor_Screen_Mode | Cursor_Right_Mode | Screen_Static_Mode, 0);

LCD1602_DIY_Char_Init();

LCD1602_Write_Byte(LCD1602_Clr, 0);//清屏幕指令,将以前的显示内容清除

}


LCD1602.h

#ifndef LCD1602_H_

#define LCD1602_H_


#define USE_8_Pin

//#define USE_4_Pin


#ifdef USE_8_Pin

#ifdef USE_4_Pin

#error

#endif

#endif


#define LCD1602_Clr0x01

#define LCD1602_Cursor_Return0x02


#define LCD1602_Cursor_Screen_Mode0x04

#define Cursor_Left_Mode0x00

#define Cursor_Right_Mode0x02

#define Screen_Static_Mode0x00

#define Screen_Right_Mode0x01


#define LCD1602_Display_Switch0x08

#define Display_Disable0x00

#define Display_Enable0x04

#define Cursor_Disable0x00

#define Cursor_Enable0x02

#define Cursor_Blink_Disable0x00

#define Cursor_Blink_Enable0x01


#define LCD1602_Cursor_Screen_Move0x10

#define Cursor_Left0x00

#define Cursor_Right0x04

#define Screen_Left0x08

#define Screen_Right0x0c


#define LCD1602_Config0x20

#define LCD1602_4PIN0x00

#define LCD1602_8PIN0x10

#define LCD1602_1Row0x00

#define LCD1602_2Row0x08

#define LCD1602_5X70x00

#define LCD1602_5X100x04


#define LCD1602_Set_CGRAM_Addr0x40

#define LCD1602_Set_DDRAM_Addr0x80


uint8_t LCD1602_Busy_Test(void);

uint8_t LCD1602_Operation(uint8_t Cmd_Data_Flag, uint8_t Write_Read_Flag, uint8_t Data);

void LCD1602_Write_Byte(uint8_t Byte, uint8_t Cmd_Data_Flag);

void LCD1602_Write_Address(uint8_t row, uint8_t col);

void LCD1602_Write_Str(char *Str);

void LCD1602_Init(void);


#endif


测试程序

四线和八线在LCD1602.h中控制

在这里插入图片描述

main.c

#include

#include "intrins.h"

#include "stdint.h"

#include "LCD1602.h"


void Delay1ms()//@11.0592MHz

{

unsigned char i, j;


_nop_();

i = 2;

j = 199;

do

{

while (--j);

} while (--i);

}



void delay_ms(int i)

{

while(i--)

Delay1ms();

}


void main(void)

{

char i;


LCD1602_Init();

LCD1602_Write_Address(0, 0);

LCD1602_Write_Str("0123456789ABCDEF");

LCD1602_Write_Address(1, 0);

for(i = 0; i < 8; ++i)

LCD1602_Write_Byte(i, 1);


while(1)

{


}

}


实验现象

在这里插入图片描述

仿真现象

需要注意的是,Proteus仿真时存储模式需设为Small才能正确显示,很神秘。

在这里插入图片描述

八线制

在这里插入图片描述

四线制

在这里插入图片描述

关键字:51单片机  LCD1602 引用地址:【51单片机快速入门指南】6.1:LCD1602的八线、四线控制及自定义符号,完美兼容Proteus仿真

上一篇:【51单片机快速入门指南】6.2:SPI 、八线、四线控制 LCD12864 屏幕及Proteus的仿真
下一篇:SPI驱动0.96/1.3寸 OLED屏幕,易修改为DMA控制

推荐阅读最新更新时间:2024-11-01 21:34

什么是51单片机寻址
让我们先来复习一下我们学过的一些指令:MOV P1,#0FFH,MOV R7,#0FFH这些指令都是将一些数据送到相应的位置中去,为什么要送数据呢?第一个因为送入的数可以让灯全灭掉,第二个是为了要实现延时,从这里我们可以看出来,在用单片机的编程语言编程时,经常要用到数据的传递,事实上数据传递是单片机编程时的一项重要工作,一共有28条指令(单片机共111条指令)。下面我们就从数据传递类指令开始吧。 分析一下MOV P1,#0FFH这条指令,我们不难得出结论,第一个词MOV是命令动词,也就是决定做什么事情的,MOV是MOVE少写了一个E,所以就是“传递”,这就是指令,规定做什么事情,后面还有一些参数,分析一下,数据传递必须要有一个“
[单片机]
什么是<font color='red'>51单片机</font>寻址
DS18B20温度测试程序(51单片机数码管显示)+电路图
下面是电路图 采用4位数码管显示 程序一共有2个文件 : /*********************************************** ds18b20.h 头文件 *************************************************/ #ifndef _DS18B20_H_ #define _DS18B20_H_ #include reg51.h #define led P1 #define ledw P2 extern unsigned char f; extern void ds18b20_reset(); extern void dela(unsigned char
[单片机]
DS18B20温度测试程序(<font color='red'>51单片机</font>数码管显示)+电路图
使用51单片机输出PWM控制舵机
SCU 的电子信息学院的某个社团会每年举办船模大赛。 因为去年的船模比赛时候懒,所以就买了成品的遥控器(天地飞6)来参赛,控制自己制作的遥控船上面的电调和舵机。最近有心情想在今年的船模比赛中自己制作遥控器,先从第一步开始吧:使用单片机来控制舵机(控制电调的原理类似)。 0x01.什么是舵机? 其实舵机就是一种伺服电机,根据要求旋转一定的角度,在我看来,知道这些就够了~~ 0x02.舵机有什么用? 就拿模型来说吧,船要转弯的话,可以采用的一种方式就是改变船后面舵片的角度来改变两侧对水的阻力,以此来让船转向,这个也是舵机一词的由来。 0x03.怎么控制? PWM波,这是什么东西呢?其
[单片机]
使用<font color='red'>51单片机</font>输出PWM<font color='red'>控制</font>舵机
STC51单片机串口发送程序
#include reg52.h #define uchar unsigned char unsigned char rtemp,sflag; unsigned char code Buffer = Welcome To The MCU World. ;//所要发送的数据 unsigned char *p; unsigned char TestBuff ; unsigned char mode=0; unsigned char ArrayIndex=0; void SerialInit() //11.0592M晶振,波特率19200 { TMOD=0x20; //设置定时器1工作方式为方式2 TH1
[单片机]
51单片机模拟I2C接口实例
电路原理图 iframe id="iframe_0.17500257049687207" src="data:text/html;charset=utf8,%3Cstyle%3Ebody%7Bmargin:0;padding:0%7D%3C/style%3E%3Cimg%20id=%22img%22%20src=%22http://www.baiheee.com/Documents/090107/090107114949/pic1.gif?_=2962239%22%20style=%22border:none;max-width:660px%22%3E%3Cscript%3Ewindow.onload%20=%20functio
[单片机]
用<font color='red'>51单片机</font>模拟I2C接口实例
基于W79E2051单片机的模拟流星雨LED控制电路设计
基于W79E2051单片机和LED恒流专用驱动芯片MBI5026设计了一款模拟流星雨LED控制电路,LED使用高亮白色,可根据需要接上36,48,64颗LED,通上电源,一字型排开的LED,会产生从上到下,从最亮的到渐暗的流星雨效果,效果逼真,可作为屋外,广场装饰灯. W79E2051单片机具有标准的串行输出口,可方便地向具有相同通信协议的驱动芯片MBI5026进行通信,同时对定时要求不高的场合,我们完全可以使用单片机内部的RC振荡时钟,这样单片机的外围元件及极简单,仅需要复位元件即可,由于流星雨效果是有着随机特性,在多个灯管同时使用时,为了达到伪随机效果,我们还推荐使用单片机的内部RC时钟.这样效果会更好.同时W79E2051在
[单片机]
基于W79E20<font color='red'>51单片机</font>的模拟流星雨LED<font color='red'>控制</font>电路设计
C51单片机模块化编程万年历设计
原文地址: C51单片机模块化编程万年历设计 作者: 给力哈 哈 程序如下: main.h #ifndef __MAIN_H__ #define __MAIN_H__ #include regx52.h #include intrins.h #include absacc.h #define uchar unsigned char #define uint unsigned int #define DQ P3_7 #endif ds18b20.h #include main.h uint sec; uint min=41; uint hour=18; uint day=20; uint month=
[单片机]
C51单片机的精准延时程序(Timer)
使用定时器 / 计数器实现精确延时 单片机系统一般常选用 11.059 2 MHz 、 12 MHz 或 6 MHz 晶振。第一种更容易产生各种标准的波特率, 后两种的一个机器周期分别为 1 μ s 和 2 μ s ,便于精确延时。本程序中假设使用频率为 12 MHz 的晶振。 最 长的延时时间可达 216=65 536 μ s 。若定时器工作在方式 2 ,则可实现极短时间的精确延时;如使用其他 定时方式,则要考虑重装定时初值的时间(重装定时器初值占用 2 个机器周期)。 在实际应用中,定时常采用中断方式,如进行适当的循环可实现几秒甚至更长时间的延时。使用定时 器 / 计数器延时从程序的执行效率和稳定性两方面考虑都是最佳的方案。但
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved