嵌入式开发学习(STC51-18-LCD液晶显示)

news2024/12/30 2:33:59

内容

在LCD1602液晶上显示字符信息;

LCD1602介绍

简介

1602液晶也叫1602字符型液晶,它能显示2行字符信息,每行又能显示16个字符;

它是一种专门用来显示字母、数字、符号的点阵型液晶模块;

它是由若干个5x7或者5x10的点阵字符位组成,每个点阵字符位都可以用显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用,正因为如此,所以它不能很好的显示图片;

管脚说明

LCD1602有16个管脚孔,从左至右管脚编号顺序是1-16

其功能定义如下所示:
在这里插入图片描述
部分管脚说明:

  • 3脚:VL,液晶显示偏压信号,用于调整LCD1602的显示对比度,一般会外接电位器用以调整偏压信号,注意此脚电压为0时可以得到最强的对比度;
  • 4脚:RS,数据/命令选择端,当此脚为高电平时,可以对1602进行数据字节的传输操作;而低电平时,则是进行命令字节的传输操作;命令字节,即是用来对LCD1602的一些工作方式作设置的字节;数据字节,即使用以在1602上显示的字节;LCD1602的数据是8位的;
  • 5脚:R/W,读写选择端;当此脚为高电平可对LCD1602进行读数据操作,反之进行写数据操作;
  • 6脚:E,使能信号,其实是LCD1602的数据控制时钟信号,利用该信号的上升沿实现对LCD1602的数据传输;
  • 7~14脚:8位并行数据口,而51单片机一组IO也是8位,使得对LCD1602的数据读写大为方便;

DDRAM说明

在LCD1602内部含有80个字节的DDRAM,它是用来寄存显示字符的;

其地址和屏幕的对应关系如下表:
在这里插入图片描述
在这里插入图片描述
从上图可知,不是所有的地址都可以直接用来显示字符数据,只有第一行中的00-0F,第二行中的40-4F才能显示,其他地址只能用于存储;

要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符,而且写入显示地址时要求最高位D7恒定为高电平1,例如第二行第一个字符的地址是40H,所以要写入的数据应该是01000000B(40H)+10000000B(80H)=11000000B(C0H);

在1602中我们只用前16个地址就行了,第二行也一样用前16个地址;

常用指令

在使用LCD1602时,我们需要掌握一些常用的指令,这些指令对于LCD1602初始化是必须的;

清屏指令

在这里插入图片描述

  • 清除液晶显示器,即将DDRAM的内容全部填入"空白"的ASCII码20H;
  • 光标归位,即将光标撤回液晶显示屏的左上方;
  • 将地址计数器(AC)的值设为0;

模式设置指令

在这里插入图片描述

  • 设定每次写入1位数据后光标的移位方向,并且设定每次写入的一个字符是否移动;
  • I/D:0 = 写入新数据后光标左移;1 = 写入新数据后光标右移;
  • S:0 = 写入新数据后显示屏不移动;1 = 写入新数据后显示屏整体右移1个字符;

显示开关控制指令

在这里插入图片描述

  • 控制显示器开/关、光标显示/关闭以及光标是否闪烁;
  • D:0 = 显示功能关;1 = 显示功能开;
  • C:0 = 无光标;1 = 有光标;
  • B:0 = 光标闪烁;1 = 光标不闪烁;

功能设定指令

在这里插入图片描述

  • 设定数据总线位数、显示的行数及字型;
  • DL:0 = 数据总线为4位;1 = 数据总线为8位;
  • N:0 = 显示1行;1 = 显示2行;
  • F:0 = 5×7点阵/每字符;1 = 5×10点阵/每字符;

使用方法

要使用LCD1602,首先需要对其初始化,即通过写入一些特定的指令实现;

然后选择要在LCD1602的哪个位置显示并将所要显示的数据发送到LCD的DDRAM;

使用LCD1602通常都是用于写数据进去,很少使用读功能;

LCD1602操作步骤如下所示:

1 初始化
2 写命令(RS=L),设置显示坐标
3 写数据(RS=H)

工作时序

LCD1602一般不需要读出它的数据的状态或者数据本身;

所以只需要看两个写时序:

  • 当要写指令字,设置LCD1602的工作方式时:把RS置为低电平,RW置为低电平,然后将数据送到数据口D0~D7,最后E引脚一个高脉冲将数据写入;
  • 当要写入数据字,在LCD1602上实现显示时:把RS置为高电平,RW置为低电平,然后将数据送到数据口D0~D7,最后E引脚一个高脉冲将数据写入;
  • 写指令和写数据,差别仅仅在于 RS 的电平不一样而已;

LCD1602时序图:
在这里插入图片描述
在这里插入图片描述
从上图可以看到,以上给的时间参数全部是ns级别的,而51单片机的机器周期是1us,指令周期是2-4个机器周期,所以即便在程序里不加延时程序,也可以很好的配合LCD1602的时序要求;

当要写命令字节的时候,时间由左往右,RS变为低电平,R/W变为低电平,注意看是RS的状态先变化完成;

然后这时,DB0~DB7上数据进入有效阶段,接着E引脚有一个整脉冲的跳变,接着要维持时间最小值为tpw=400ns的E脉冲宽度;

然后E引脚负跳变,RS电平变化,R/W电平变化,这样便是一个完整的LCD1602写命令的时序;

注意:这里介绍的是8位LCD1602,现在某些公司为简化引脚数,使用4位LCD1602;使用4位LCD1602时,应该多看手册,找到不同点,对原有程序加以修改;

原理图

在这里插入图片描述
在这里插入图片描述
从线路图中可知,LCD1602的8位数据口D0-D7与单片机的P0.0-P0.7管脚连接,LCD1602的RS、WR、E脚与单片机的P2.6、P2.5、P2.7管脚连接;

RJ1是一个电位器,用来调节LCD1602对比度即显示亮度;

思路

根据lcd1602的写指令和数据的时序编写相应程序;

根据lcd1602的指令格式,编写必要的初始化、清屏和显示程序;

编码

User

main.c

/*
 * @Description: 使LCD1602上显示字符信息
 */
#include "public.h"
#include "lcd1602.h"

void main()
{
	lcd1602_init();							   // LCD1602初始化
	lcd1602_show_string(0, 0, "Hello World!"); // 第一行显示
	lcd1602_show_string(0, 1, "0123456789");   // 第二行显示
	while (1)
	{
	}
}

Public

public.h

#ifndef _public_H
#define _public_H

#include "reg52.h"

typedef unsigned int u16; // 对系统默认数据类型进行重定义
typedef unsigned char u8;

void delay_10us(u16 ten_us);
void delay_ms(u16 ms);

#endif

public.c

#include "public.h"

/**
 * @description: 延时函数,ten_us=1时,大约延时10us
 * @param {u16} ten_us 延时倍数
 * @return {*}
 */
void delay_10us(u16 ten_us)
{
	while (ten_us--)
		;
}

/**ms延时函数,ms=1时,大约延时1ms***
 * @param {u16} ms 延时倍数
 * @return {*}
 */
void delay_ms(u16 ms)
{
	u16 i, j;
	for (i = ms; i > 0; i--)
		for (j = 110; j > 0; j--)
			;
}

App/lcd1602

lcd1602.h

#ifndef _lcd1602_H
#define _lcd1602_H

#include "public.h"

// LCD1602数据口4位和8位定义,若为1,则为LCD1602四位数据口驱动,反之为8位
#define LCD1602_4OR8_DATA_INTERFACE 0 // 默认使用8位数据口LCD1602

// 管脚定义
sbit LCD1602_RS = P2 ^ 6;	// 数据命令选择
sbit LCD1602_RW = P2 ^ 5;	// 读写选择
sbit LCD1602_E = P2 ^ 7;	// 使能信号
#define LCD1602_DATAPORT P0 // 宏定义LCD1602数据端口

// 函数声明
void lcd1602_init(void);
void lcd1602_clear(void);
void lcd1602_show_string(u8 x, u8 y, u8 *str);

#endif

lcd1602.c

#include "lcd1602.h"

#if (LCD1602_4OR8_DATA_INTERFACE == 0) // 8位LCD
/**
 * @description: LCD1602写命令
 * @param {u8} cmd 指令
 * @return {*}
 */
void lcd1602_write_cmd(u8 cmd)
{
	LCD1602_RS = 0; // 选择命令
	LCD1602_RW = 0; // 选择写
	LCD1602_E = 0;
	LCD1602_DATAPORT = cmd; // 准备命令
	delay_ms(1);
	LCD1602_E = 1; // 使能脚E先上升沿写入
	delay_ms(1);
	LCD1602_E = 0; // 使能脚E后负跳变完成写入
}
#else // 4位LCD
void lcd1602_write_cmd(u8 cmd)
{
	LCD1602_RS = 0; // 选择命令
	LCD1602_RW = 0; // 选择写
	LCD1602_E = 0;
	LCD1602_DATAPORT = cmd; // 准备命令
	delay_ms(1);
	LCD1602_E = 1; // 使能脚E先上升沿写入
	delay_ms(1);
	LCD1602_E = 0; // 使能脚E后负跳变完成写入

	LCD1602_DATAPORT = cmd << 4; // 准备命令
	delay_ms(1);
	LCD1602_E = 1; // 使能脚E先上升沿写入
	delay_ms(1);
	LCD1602_E = 0; // 使能脚E后负跳变完成写入
}
#endif

#if (LCD1602_4OR8_DATA_INTERFACE == 0) // 8位LCD
/**
 * @description: LCD1602写数据
 * @param {u8} dat 数据
 * @return {*}
 */
void lcd1602_write_data(u8 dat)
{
	LCD1602_RS = 1; // 选择数据
	LCD1602_RW = 0; // 选择写
	LCD1602_E = 0;
	LCD1602_DATAPORT = dat; // 准备数据
	delay_ms(1);
	LCD1602_E = 1; // 使能脚E先上升沿写入
	delay_ms(1);
	LCD1602_E = 0; // 使能脚E后负跳变完成写入
}
#else
void lcd1602_write_data(u8 dat)
{
	LCD1602_RS = 1; // 选择数据
	LCD1602_RW = 0; // 选择写
	LCD1602_E = 0;
	LCD1602_DATAPORT = dat; // 准备数据
	delay_ms(1);
	LCD1602_E = 1; // 使能脚E先上升沿写入
	delay_ms(1);
	LCD1602_E = 0; // 使能脚E后负跳变完成写入

	LCD1602_DATAPORT = dat << 4; // 准备数据
	delay_ms(1);
	LCD1602_E = 1; // 使能脚E先上升沿写入
	delay_ms(1);
	LCD1602_E = 0; // 使能脚E后负跳变完成写入
}
#endif

#if (LCD1602_4OR8_DATA_INTERFACE == 0) // 8位LCD
/**
 * @description: LCD1602初始化
 * @return {*}
 */
void lcd1602_init(void)
{
	lcd1602_write_cmd(0x38); // 数据总线8位,显示2行,5*7点阵/字符
	lcd1602_write_cmd(0x0c); // 显示功能开,无光标,光标闪烁
	lcd1602_write_cmd(0x06); // 写入新数据后光标右移,显示屏不移动
	lcd1602_write_cmd(0x01); // 清屏
}
#else
void lcd1602_init(void)
{
	lcd1602_write_cmd(0x28); // 数据总线4位,显示2行,5*7点阵/字符
	lcd1602_write_cmd(0x0c); // 显示功能开,无光标,光标闪烁
	lcd1602_write_cmd(0x06); // 写入新数据后光标右移,显示屏不移动
	lcd1602_write_cmd(0x01); // 清屏
}
#endif

/**
 * @description: LCD1602清屏
 * @return {*}
 */
void lcd1602_clear(void)
{
	lcd1602_write_cmd(0x01);
}

/**
 * @description: LCD1602显示字符
 * @param {u8} x 坐标
 * @param {u8} y 坐标
 * @param {u8} *str 要显示的字符串
 * @return {*}
 */
void lcd1602_show_string(u8 x, u8 y, u8 *str)
{
	u8 i = 0;

	if (y > 1 || x > 15)
		return; // 行列参数不对则强制退出

	if (y < 1) // 第1行显示
	{
		while (*str != '\0') // 字符串是以'\0'结尾,只要前面有内容就显示
		{
			if (i < 16 - x) // 如果字符长度超过第一行显示范围,则在第二行继续显示
			{
				lcd1602_write_cmd(0x80 + i + x); // 第一行显示地址设置
			}
			else
			{
				lcd1602_write_cmd(0x40 + 0x80 + i + x - 16); // 第二行显示地址设置
			}
			lcd1602_write_data(*str); // 显示内容
			str++;					  // 指针递增
			i++;
		}
	}
	else // 第2行显示
	{
		while (*str != '\0')
		{
			if (i < 16 - x) // 如果字符长度超过第二行显示范围,则在第一行继续显示
			{
				lcd1602_write_cmd(0x80 + 0x40 + i + x);
			}
			else
			{
				lcd1602_write_cmd(0x80 + i + x - 16);
			}
			lcd1602_write_data(*str);
			str++;
			i++;
		}
	}
}

编译和结果

按F7编译,无错误,生成.hex文件,使用pz-isp将hex文件下载到单片机

结果:lcd液晶屏上正确显示内容;
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/842529.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PEMFC氢氧质子交换燃料电池MATLAB仿真模型

氢氧燃料电池静态模型&#xff1a; &#xff08;1&#xff09;热力学电动势En &#xff08;2&#xff09;活化极化过电势Vact 活化损失主要是因为电极表面的反应速度过慢&#xff0c;在驱动电子传递到或者传送出电极的化学反应时&#xff0c;部分电压会被消耗。 &#xff08;…

机器学习——SMO算法推导与实践

一、 硬间隔-SMO算法推导 明天再说&#xff0c;啊。。。。感觉天空明朗了很多&#xff0c;即使现在已经很晚了 还是要打开柯南&#xff0c;看看电视&#xff0c;等待天气预报所说的台风天吧&#xff01; 一时之间&#xff0c;忽然失去了用markdown语法写下推导过程的勇气。。。…

干货:电视盒子什么牌子好?数码博主盘点电视盒子排名

电视盒子是我们观影不可缺少的装备之一&#xff0c;但面对众多的电视盒子产品&#xff0c;大家在选购时会疑惑电视盒子什么牌子好&#xff0c;我作为数码测评博主&#xff0c;本期要分享的主题是电视盒子&#xff0c;通过对比今年测评过的26款热门电视盒子&#xff0c;我整理了…

Tkinter的超强主题扩展-ttkbootstrap

1、前言 在上一篇文章 将Python脚本集成到GUI工具包-Tkinter 里&#xff0c;作者介绍了 Tkinter&#xff0c;并开发了测试参数组合生成器小工具&#xff0c;虽然功能上已经满足了所要的需求&#xff0c;但是页面展示方面很不美观&#xff0c;需要改进一下。 本篇将介绍一款 T…

使用罗技鼠标后 弹出当前页面的脚本发生错误AppData/Local/Temp/LogiUI/Pak/js/jquery-1.3.2.min.js解决

使用的台式机&#xff0c;没有蓝牙驱动&#xff0c;在用logi无线鼠标时&#xff0c;把鼠标连接插入台式机后弹出的如上图所示这个提示&#xff0c;无论是点是/否&#xff0c;还是X掉上图提示&#xff0c;电脑右下角的图依然存在。不习惯这丫的存在。 我重启还是有&#xff0c;然…

1. Git基础知识

文章目录 Git基础知识一、集中式与分布式二、中心服务器三、工作流四、分支实现五、冲突六、Fast forward七、储藏&#xff08;Stashing&#xff09;八、SSH 传输设置九、.gitignore 文件十、Git 命令一览十一、和远端仓库交互 Git基础知识 一、集中式与分布式 Git 属于分布式…

服务蓝图:提升和改善服务系统的工具

服务蓝图&#xff1a;提升和改善服务系统的工具 Service Blueprint 翻译成服务提供计划比较恰当 趣讲大白话&#xff1a;精细耕耘&#xff0c;才有好体验 【趣讲信息科技249期】 **************************** 西方擅长的是工具和方法 把一件事情透过工具和方法做到人人能懂 日…

Day 74:通用BP神经网络 (1. 集中管理激活函数)

代码&#xff1a; package dl;/*** Activator.*/public class Activator {/*** Arc tan.*/public final char ARC_TAN a;/*** Elu.*/public final char ELU e;/*** Gelu.*/public final char GELU g;/*** Hard logistic.*/public final char HARD_LOGISTIC h;/*** Identit…

web集群学习:源码安装nginx配置启动服务脚本、IP、端口、域名的虚拟主机

目录 1、源码安装nginx&#xff0c;并提供服务脚本。 2、配置基于ip地址的虚拟主机 3、配置基于端口的虚拟主机 4、配置基于域名的虚拟主机 1、源码安装nginx&#xff0c;并提供服务脚本。 1、源码安装会有一些软件依赖 &#xff08;1&#xff09;检查并安装 Nginx 基础依赖…

探索远程访问内网群晖NAS 6.X(使用独立域名)【内网穿透】

使用自己的域名远程访问内网群晖NAS 6.X【内网穿透】 文章目录 使用自己的域名远程访问内网群晖NAS 6.X【内网穿透】 在之前的文章中&#xff0c;我们向大家演示了如何使用cpolar&#xff0c;创建一条固定的、能够在公共互联网登录内网群晖NAS的数据隧道。这条隧道已经能够应对…

新能源汽车交流充电桩控制主板的功能维度

新能源汽车交流充电桩控制主板的功能维度 交流充电桩主板是电动汽车充电站的关键组件&#xff0c;它负责控制充电过程&#xff0c;保护设备和电网免受电动汽车充电的冲击。它具有控制、保护、检测、报警和记录等功能&#xff0c;可以有效地控制充电过程&#xff0c;保证交流充电…

防火墙第五次作业

1. 什么是恶意软件&#xff1f; 恶意软件官方的一个定义&#xff1a;恶意软件 (Malware) 从“恶意”(malicious) 和“软件”(software) 这两个词合并而来&#xff0c;是一个通用术语&#xff0c;可以指代病毒、蠕虫、特洛伊木马、勒索软件、间谍软件、广告软件和其他类型的有害…

java 版本企业招标投标管理系统源码+多个行业+tbms+及时准确+全程电子化tbms

​ 功能描述 1、门户管理&#xff1a;所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含&#xff1a;招标公告、非招标公告、系统通知、政策法规。 2、立项管理&#xff1a;企业用户可对需要采购的项目进行立项申请&#xff0c;并提交审批&#xff0c;查…

图像 检测 - DETR: End-to-End Object Detection with Transformers (arXiv 2020)

图像 检测 - DETR: End-to-End Object Detection with Transformers - 端到端目标检测的Transformers&#xff08;arXiv 2020&#xff09; 摘要1. 引言2. 相关工作2.1 集预测2.2 Transformers和并行解码2.3 目标检测 3. DETR模型References 声明&#xff1a;此翻译仅为个人学习…

【Grafana】中文界面配置 v10.0.3

比如通过 docker run -d -p 3000:3000 -v /e/code/monitor/grafana/grafana.ini.txt:/etc/grafana/grafana.ini grafana/grafana运行一个容器&#xff08;最新是v10.0.3&#xff09;。 在 /admin/settings 可以看到 users 部分有一个 default_language 配置。 所以在挂载到 …

EC200 CAT1 拨号PPP

**硬件支持型号 点击 查看 硬件支持 详情** DTU701 产品详情 DTU702 产品详情 DTU801 产品详情 DTU802 产品详情 DTU902 产品详情 G5501 产品详情 目前 DTU系列 产品&#xff0c;WIFI4G拨号 &#xff0c;默认开机自启动拨号。 WIFI 只需要 根据现场 修改SSID热点和密码…

智慧消防 | 气体灭火系统压力在线监测正当其时

气体灭火设备在消防安全系统中扮演着重要的角色。根据最新版的《气瓶安全技术规程》TSG23-2021规定&#xff0c;IG541气体钢瓶需要每3年进行一次检测。未按时进行检测可能导致压力掉压、瓶体外部锈蚀、钢瓶位置钢瓶内部腐蚀等风险&#xff0c;这些问题都可能对消防安全和效能产…

MySQL面试1

Mysql的面试突击1 Mysql的体系结构是什么样子的&#xff08;查询语句怎么进行执行的&#xff09; mysql的架构&#xff1a;单进程多线程的架构模式 CLient -----> Server架构 Mysql的链接方式有没有性能优化的点 2个点 查询缓存(Query Cache) MySQL 内部自带了一个缓存模…

【Nginx】静态资源部署、反向代理、负载均衡

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ nginx静态资源部署、反向代理、负载均衡 &…

laravel项目运行问题记录

一.首页404未找到 检查项目配置是否配置好 解决地址:phpstudy网站或站点创建成功,打开无响应_php打开提示站点创建成功_荒-漠的博客-CSDN博客 二.vendor目录不存在 composer未安装 解决地址:laravel安装composer依赖_荒-漠的博客-CSDN博客 三.首页可以展示 里面路径404 未配…