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

内容

在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.mzph.cn/news/27701.shtml

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

相关文章

WSL2安装CentOS7和CentOS8

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、下载ZIP包&#xff1f;二、安装1.打开Windows子系统支持2.安装到指定位置3.管理虚拟机4.配置虚拟机1.配置国内源2.安装软件3.安装第三方源 5.配置用户1.创建…

redis 集群 1:李代桃僵 —— Sentinel

目前我们讲的 Redis 还只是主从方案&#xff0c;最终一致性。读者们可思考过&#xff0c;如果主节点凌晨 3 点突发宕机怎么办&#xff1f;就坐等运维从床上爬起来&#xff0c;然后手工进行从主切换&#xff0c;再通知所有的程序把地址统统改一遍重新上线么&#xff1f;毫无疑问…

使用 Splashtop Secure Workspace 改进安全访问

前言&#xff1a;Splashtop 首席执行官兼联合创始人 Mark Lee 我们在十多年前推出 Splashtop 远程访问和支持产品线时&#xff0c;专注于为用户提供高性能和卓越的用户体验&#xff0c;以便用户能够随处访问计算资源。如今&#xff0c;我们有25万企业客户和3000万个人用户&…

机器学习深度学习——卷积的多输入多输出通道

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——从全连接层到卷积 &#x1f4da;订阅专栏&#xff1a;机器学习&&深度学习 希望文章对你们有所帮…

C++三个线程依次打印abc

代码 #include<iostream> #include<thread> #include<mutex> #include<condition_variable> using namespace std; mutex mtx; condition_variable cv; int flag0; void A(){unique_lock<mutex>lk(mtx);int count0;while(count<10){while(fl…

Jmeter录制HTTPS脚本

Jmeter录制HTTPS脚本 文章目录 添加“HTTP代理服务器”设置浏览器代理证书导入存在问题 添加“HTTP代理服务器” 设置浏览器代理 保持端口一致 证书导入 点击一下启动让jmeter自动生成证书&#xff0c;放在bin目录下&#xff1a; 打开jmeter的SSL管理器选择刚刚生成的证书&…

Vue——formcreate表单设计器自定义组件实现(二)

前面我写过一个自定义电子签名的formcreate表单设计器组件&#xff0c;那时初识formcreate各种使用也颇为生疏&#xff0c;不过总算套出了一个组件不是。此次时隔半年又有机会接触formcreate&#xff0c;重新熟悉和领悟了一番各个方法和使用指南。趁热打铁将此次心得再次分享。…

THS4301 振荡问题排查及解决过程

项目背景简介: 本项目是基于一款微弱信号处理前级模拟电路设计方案。 问题描述: 在生产标定中,发现以前的程序在小量程标定后,切换到差分和单端后,两者的直流偏置不一样,且切换到差分输入时,能发现有振荡现象(有设备单端输入也有振荡); 排查分析过程: 1)首先可以…

tomcat上部署jpress

一.确保有jdk&#xff0c;tomcat和mysql环境 二.新建jpress数据库&#xff0c;新建jpress用户并赋予所有权限 三.将jpress的war上传到tomcat/apache-tomcat-8.5.70/webapps&#xff0c;具体根据你的实际tomcat安装路径为准&#xff0c;上传完成后他会自己解包 四.到浏览器完…

JAVA实现图书管理系统(思路,和完整代码)

因为文件过多每个文件之间的关系如下&#xff08;每个文件中都只有一个类&#xff09;&#xff1a; 因为JAVA属于面向对象编程的语言&#xff0c;所以我们想要实现图书管理系统就得分以下几步&#xff1a; 找出其中的所有的对象实现所有的对象完成对象之间的交互 在图书管理系…

【产品经理】高阶产品如何提出有效解决方案?(1方法论+2案例+1清单)

每一件事情总有它的解决方案&#xff0c;在工作中亦是如此&#xff0c;而有效的解决方案&#xff0c;一定是具有系统性的。 有效的解决方案&#xff0c;一定是系统性的解决方案。 什么是系统性解决方案&#xff1f; 从系统结构&#xff08;或连接关系&#xff09;入手&#x…

【C语言】初识C语言+进阶篇导读

✨个人主页&#xff1a; Anmia.&#x1f389;所属专栏&#xff1a; C Language &#x1f383;操作环境&#xff1a; Visual Studio 2019 版本 本篇目的是面向编程新手&#xff0c;没接触过编程的人。以及C进阶的导读。 内容是C语言重要知识点的简单解释&#xff0c;不做详解。给…

73. 矩阵置零

题目链接&#xff1a;力扣 解题思路&#xff1a; 方法一&#xff1a;比较容易想到的方向&#xff0c;使用两个数组row和col保存有0的行或者列&#xff0c;然后将有0的那一行或那一列的所有元素都设置为0 AC代码 class Solution {public void setZeroes(int[][] matrix) {in…

小尺寸、高效率的88W8997-A0-CBQ2E005-T无线互连芯片,NV24C64DWVLT3G 64Kb EEPROM存储器

88W8997-A0-CBQ2E005-T 是业界尺寸最小、能效最高的MU-MIMO无线互连组合芯片&#xff0c;面向企业级和消费级市场。88W8997是业界首款全面支持Bluetooth 4.2以及未来Bluetooth 5.0全套功能的28nm 2 x 2 802.11ac Wave-2组合芯片。该器件实现了高达867Mbps的峰值数据传送速率&am…

9-数据结构-栈(C语言版)

数据结构-栈&#xff08;C语言版&#xff09; 目录 数据结构-栈&#xff08;C语言版&#xff09; 1.栈的基础知识 1.入栈&#xff0c;出栈的排列组合 情景二&#xff1a;Catalan函数&#xff08;计算不同出栈的总数&#xff09; 2.栈的基本操作 1.顺序存储 (1)顺序栈-定义…

自学python,学了又忘,感觉学不好是为啥呢

一、前言 最近发现&#xff0c;身边很多的小伙伴学Python都会遇到一个问题&#xff0c;就是资料也看了很多&#xff0c;也花了很多时间去学习但还是很迷茫&#xff0c;时间长了又发现之前学的知识点很多都忘了&#xff0c;都萌生出了想半路放弃的想法。 其实造成这样情况根本的…

使用toad库进行机器学习评分卡全流程

1 加载数据 导入模块 import pandas as pd from sklearn.metrics import roc_auc_score,roc_curve,auc from sklearn.model_selection import train_test_split from sklearn.linear_model import LogisticRegression import numpy as np import math import xgboost as xgb …

搭建 elasticsearch8.8.2 伪集群 windows

下载windows 版本 elasticsearch8.8.2 以下链接为es 历史版本下载地址&#xff1a; Past Releases of Elastic Stack Software | Elastic windows 单节点建立方案&#xff1a; 下载安装包 elasticsearch-8.8.2-windows-x86_64.zip https://artifacts.elastic.co/download…

element-plus:el-date-picker日期只选择年月不要日

<el-date-picker v-model"value" type"month" format"YYYY-MM" value-format"YYYY-MM" />使用format属性将时间显示格式修改为YYYY–MM 年月格式 使用value-format将绑定值的格式修改为YYYY–MM年月格式

一台电脑给另外一台电脑共享网络

这里写自定义目录标题 有网的电脑上操作一根网线连接两台电脑没网的电脑上 有网的电脑上操作 右键->属性->共享 如同选择以太网&#xff0c;勾选。确认。 一根网线连接两台电脑 没网的电脑上 没网的电脑为mips&麒麟V10 新增个网络配置ww&#xff0c;设置如下。 …