51单片机应用开发---LCD1602显示应用

news2024/11/15 15:08:17

实现目标

1、了解LCD1602液晶屏;

2、掌握驱动程序的编写;

3. 具体目标:在屏幕上显示字符。


一、LCD1206概述

1.1  定义

LCD1602(Liquid Crystal Display)液晶显示屏是一种字符型液晶显示模块,可以显示ASCII码的标准字符和其它的一些内置特殊字符,还可以有8个自定义字符(如汉字)。

显示容量:  16—表示每行显示16个字符;02—表示显示两行。

1.2 实物与管脚

(1)实物 

          

 (2)管脚定义

1.3 内部结构框图

屏幕: 16*2

字模库:类似于数码管的数码表

DDRAM (data display RAM):前16列与屏幕一一对应的

AC: address counter

显示流程:在数据显示区写入相应的值(ASCII码),之后通过字模库找到对应的字符,将其显示到屏幕上。

1.显示原理

如上图,每个字符由 5X8 点阵组成(也可选用 5X10),想要实现显示,只需如下图:

例:以 5X7 点阵为例, 显示字符 A

0 代表灭,1 代表亮
只需将想要显示的字符的对应位置1,就能显示该字符
在这里插入图片描述

LCD1602 固化了字模寄存器,即 CGROM 和 CGRAM,存储了192个常用字符的字模。

(1) 在哪个位置显示?

LCD1602 实际有80个字节的DDRAM(数据显示区),只不过 LCD1602 只有 16X2 个位置,后面很多位置显示不出来,可以使用 指令5  “光标或显示移动指令”   使字符慢慢移动到可见的显示范围内,看到字符的移动效果。

 

          LCD1602可以显示16*2个字符且通过D0-D7八个引脚传输数据八位数据,每一个显示的位置都对应上图的一个地址。例如我想在第一行的第三个位置显示,那么就可以锁定上表中的“02”,换算成二进制就是0000 0010。听上去很简单,但是LCD1602有个特点就是写入显示地址时要求最高位 D7 恒定为高电平。所以我们想显示真实的地址应该为1000 0010

(2)具体显示什么?

 在LCD1602的手册中给出了这样一个表格(CGRAM+CGROM(字模库)),我们想显示表格中的字符只需获取某个字符的高位和低位即可。 例如:要显示A,则索引码为0100 0001      该表 行是低四位,列是高四位。十六进制为0X41,刚好对应 ‘A’  的ASCLL码 65  .

1.4  LCD1602指令集

常用指令:

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

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

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

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

0x01 :清屏。

 1.5 LCD1602操作流程

(1) 初始化

发送指令0x38 //八位数据接口,两行显示,5*7点阵

发送指令0x0C //显示开,光标关,闪烁关

发送指令0x06 //数据读写操作后,光标自动加一,画面不动

发送指令0x01 //清屏

(2) 显示字符

发送指令  0x80 | AC  //设置光标位置(之所以要将AC与0x80进行或运算,是因为DDRAM地址设置指令的DB7为1,故发送指令的最高位要为1)
【将光标设置在一行一列输入1000 0000,1为设置,剩下为00H】

LCD_WriteCommand(0x80|(Column-1));
【将光标设置在二行一列输入1100 0000,1为设置,剩下为40H(二进制100 0000转化为十进制为64,十六进制40转化为十进制也是64)】

LCD_WriteCommand(0x80|(Column-1)+0x40);

发送数据 //发送要显示的字符数据

1.6 时序结构

写数据/指令(对于LCD来说,一般不需要进行读操作)

写数据:先将RS置1,再将R/W置0,之后将数据写入对应I0口,将 E 置1,则此时数据有效;写数据完成后;E置0 。写指令同理

驱动编写:

(1) 管脚定义

#include "LCD1602.h"
#include <REGX52.H>
//管脚定义
sbit LCD_RW=P2^5;
sbit LCD_RS=P2^6;
sbit LCD_E =P2^7;
#define LCD_DataPort P0

(2)写命令

/**
  * @brief  LCD1602延时函数,12MHz调用可延时1ms
  * @param  无
  * @retval 无
  */
void LCD_Delay()		//@12.000MHz 1ms
{
	unsigned char i, j;

	i = 2;
	j = 239;
	do
	{
		while (--j);
	} while (--i);
}

/**
  * @brief  LCD1602写命令
  * @param  Command 要写入的命令
  * @retval 无
  */
void LCD_WriteCommand(unsigned char Command)
{
	LCD_RS=0;
	LCD_RW=0;
	LCD_DataPort=Command;
	LCD_E=1;
	LCD_Delay();
	LCD_E=0;
	LCD_Delay();
}

 (3)写数据

/**
  * @brief  LCD1602写数据
  * @param  Data 要写入的数据
  * @retval 无
  */
void LCD_WriteData(unsigned char Data)
{
	LCD_RS=1;
	LCD_RW=0;
	LCD_DataPort=Data;
	LCD_E=1;
	LCD_Delay();
	LCD_E=0;
	LCD_Delay();
}

(4)LCD1602初始化

/**
  * @brief  LCD1602初始化函数
  * @param  无
  * @retval 无
  */
void LCD_Init(void)
{
	LCD_WriteCommand(0x38);
	LCD_WriteCommand(0x0C);
	LCD_WriteCommand(0x06);
	LCD_WriteCommand(0x01);
}

 (5)设置光标位置

/**
  * @brief  LCD1602设置光标位置
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @retval 无
  */
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
	if(Line==1)
	{
		LCD_WriteCommand(0x80|(Column-1));
	}
	else
	{
		LCD_WriteCommand(0x80|(Column-1)+0x40);
	}
}

 (6)显示一个字符

/**
  * @brief  在LCD1602指定位置上显示一个字符
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @param  Char 要显示的字符
  * @retval 无
  */
void LCD_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char)
{
	LCD_SetCursor(Line,Column);
	LCD_WriteData(Char);
}

 (7)显示字符串

/**
  * @brief  在LCD1602指定位置开始显示所给字符串
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  String 要显示的字符串
  * @retval 无
  */
void LCD_ShowString(unsigned char Line,unsigned char Column,unsigned char *String)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=0;String[i]!='\0';i++)
	{
		LCD_WriteData(String[i]);
	}
}

(8)X的Y次方

/**
  * @brief  返回值=X的Y次方
  */
int LCD_Pow(int X,int Y)
{
	unsigned char i;
	int Result=1;
	for(i=0;i<Y;i++)
	{
		Result*=X;
	}
	return Result;
}

  (9)显示数字

/**
  * @brief  在LCD1602指定位置开始显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~65535
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData('0'+Number/LCD_Pow(10,i-1)%10);
	}
}

 (10)显示有符号数字

/**
  * @brief  在LCD1602指定位置开始以有符号十进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:-32768~32767
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
	unsigned char i;
	unsigned int Number1;
	LCD_SetCursor(Line,Column);
	if(Number>=0)
	{
		LCD_WriteData('+');
		Number1=Number;
	}
	else
	{
		LCD_WriteData('-');
		Number1=-Number;//int型-32768~32767
	}
	for(i=Length;i>0;i--)
	{
		LCD_WriteData('0'+Number1/LCD_Pow(10,i-1)%10);
	}
}

二、原理图设计

  

三、程序设计

3.1  LCD1602.h  文件

#ifndef __LCD1602_H__
#define __LCD1602_H__

void LCD_Init(void);
void LCD_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,unsigned char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);

#endif

 3.2  LCD1602.c  文件

   将前面的各项驱动程序模块添加到LCD1602.c文件中。

 3.3  测试程序

#include <REGX52.H>
#include "LCD1602.h"
 
void Delay500ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	i = 4;
	j = 129;
	k = 119;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}
 
void main()
{
	LCD_Init();
	LCD_ShowString(1,16,"day day up!");
	while(1)
	{//指令集0x18:画面向左平移一个字符位,但光标不动。移屏
		LCD_WriteCommand(0x18);
		Delay500ms();
	}
}

四、实验效果

五、仿真实现


总结

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

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

相关文章

如何修改npm包

前言 开发中遇到一个问题&#xff0c;配置 Element Plus 自定义主题时&#xff0c;添加了 ElementPlusResolver({ importStyle: "sass" }) 后&#xff0c;控制台出现报错&#xff0c;这是因为 Dart Sass 2.0 不再支持使用 !global 来声明新变量&#xff0c;虽然当前…

【原创】java+ssm+mysql校园疫情防控管理系统设计与实现

个人主页&#xff1a;程序猿小小杨 个人简介&#xff1a;从事开发多年&#xff0c;Java、Php、Python、前端开发均有涉猎 博客内容&#xff1a;Java项目实战、项目演示、技术分享 文末有作者名片&#xff0c;希望和大家一起共同进步&#xff0c;你只管努力&#xff0c;剩下的交…

Python模拟键盘输入,解放双手

文章目录 Python模拟键盘输入&#xff0c;解放双手一、引言二、pyautogui库的详细介绍1、安装与配置2、键盘输入函数3、特殊按键和组合键 三、实用示例1、自动填写表单2、自动发送邮件3、自动化数据录入 四、总结 Python模拟键盘输入&#xff0c;解放双手 一、引言 在自动化办…

人工智能时代下对人的价值反思?

一、员工价值物化 在现代企业的运作中&#xff0c;资本管理层之间的权力博弈与资源争夺有时呈现出了激烈的内斗态势。这种冲突不仅仅局限于单一部门内部&#xff0c;而是波及到跨部门乃至不同业务小组间的战略部署与资源配置上。各部门经理们既要竭力确保自身团队的利益最大化…

【Qt实现虚拟键盘】

Qt实现虚拟键盘 &#x1f31f;项目分析&#x1f31f;实现方式&#x1f31f;开发流程 &#x1f31f;项目分析 需求&#xff1a;为Linux环境下提供可便捷使用的虚拟键盘OS环境&#xff1a;Windows 7/11、CentOS 7开发语言&#xff1a;Qt/C IDE&#xff1a;QtCreator 、Qt5.14.2功…

APT 参与者将恶意软件嵌入 macOS Flutter 应用程序中

发现了一些恶意软件样本&#xff0c;这些样本据信与朝鲜民主主义人民共和国 (DPRK)&#xff08;又称北朝鲜&#xff09;有关&#xff0c;这些样本使用 Flutter 构建&#xff0c;Flutter 的设计可以对恶意代码进行混淆。JTL 深入研究了恶意代码的工作原理&#xff0c;以帮助保护…

双十一抢券风波:大学生300元提6000元电动车遭拒,谁该负责?

双十一购物狂欢节&#xff0c;本应是消费者享受优惠、商家提升销量的双赢时刻&#xff0c;但在河南郑州&#xff0c;发生了一起哭笑不得的抢券风波。一名大学生在双十一期间&#xff0c;通过某平台抢到了原价6099元电动车的直降优惠&#xff0c;只需支付300元就能将车骑回家。然…

三周精通FastAPI:37 包含 WSGI - Flask,Django,Pyramid 以及其它

官方文档&#xff1a;https://fastapi.tiangolo.com/zh/advanced/wsgi/ 包含 WSGI - Flask&#xff0c;Django&#xff0c;其它 您可以挂载多个 WSGI 应用&#xff0c;正如您在 Sub Applications - Mounts, Behind a Proxy 中所看到的那样。 为此, 您可以使用 WSGIMiddlewar…

【汇编语言】包含多个段的程序(二)—— 将数据、代码、栈放入不同的段

文章目录 前言1. 存在的两个问题2. 解决办法3. 示例代码3.1 程序说明3.1.1 定义多个段的方法3.1.2 对段地址的引用3.1.3 各种段完全是我们的安排 4. 总结结语 前言 &#x1f4cc; 汇编语言是很多相关课程&#xff08;如数据结构、操作系统、微机原理&#xff09;的重要基础。但…

初识Linux · 共享内存

目录 理解共享内存 Shared memmory code 理解共享内存 前文介绍的管道方式的通信&#xff0c;本文介绍的是进程通信的另外一种方式&#xff0c;即共享内存。但是这种通信方式的特点是只能本地通信&#xff0c;并且不像管道那样有保护机制&#xff0c;这里是没有的。 我们通…

【竞技宝】CS2-上海majorRMR:美洲区最后门票争夺战

北京时间2024年11月15日&#xff0c;上海major美洲区RMR正在如火如荼的进行之中。昨日一共进行了三场2-1组的比赛以及三场1-2组的比赛&#xff0c;决出三个正赛参赛名额的同时也确定了今日2-2组的参赛队伍&#xff0c;那么昨日的比赛战果如何呢&#xff1f;接下来小宝就为大家带…

实战:深入探讨 MySQL 和 SQL Server 全文索引的使用及其弊端

在数据库中处理大量文本数据时,包含搜索(例如查找包含特定单词的文本)往往是必需的。然而,直接使用 LIKE %text% 的方式在大数据量中进行模糊查询会造成性能瓶颈。为了解决这一问题,MySQL 和 SQL Server 提供了全文索引(Full-Text Indexing)功能,可以显著加速文本数据的…

蓝桥杯——数组

1、移动数组元素 package day3;import java.util.Arrays;public class Demo1 {public static void main(String[] args) {int[] arr {1,2,3,4,5,6};int k 2;int[] arr_new f(arr,k);for (int i : arr_new) {System.out.print(i",");}//或System.out.println();St…

人体存在感应器设置时间开启感应人存在开灯,失效

环境&#xff1a; 领普人体存在感应器 问题描述&#xff1a; 人体存在感应器设置时间开启感应人存在开灯,失效&#xff0c;设置下午5点&#xff0c;如果有人在5点前一直在这个区域&#xff0c;这个时候到了5点&#xff0c;就触发不了感应自动打开灯光。 解决方案&#xff1a…

常用命令之LinuxOracleHivePython

1. 用户改密 passwd app_adm chage -l app_adm passwd -x 90 app_adm -> 执行操作后&#xff0c;app_adm用户的密码时间改为90天有效期--查看该euser用户过期信息使用chage命令 --chage的参数包括 ---m 密码可更改的最小天数。为零时代表任何时候都可以更改密码。 ---M 密码…

基于yolov8、yolov5的车型检测识别系统(含UI界面、训练好的模型、Python代码、数据集)

摘要&#xff1a;车型识别在交通管理、智能监控和车辆管理中起着至关重要的作用&#xff0c;不仅能帮助相关部门快速识别车辆类型&#xff0c;还为自动化交通监控提供了可靠的数据支撑。本文介绍了一款基于YOLOv8、YOLOv5等深度学习框架的车型识别模型&#xff0c;该模型使用了…

解决因为TortoiseSVN未安装cmmand line client tools组件,导致idea无法使用svn更新、提交代码

一.错误信息 1.更新代码时&#xff1a;SVN: 更新错误 找不到要更新的版本管理目录。 2.提交代码&#xff1a;检测不到任何更新&#xff08;实际上有代码修改&#xff09;。 3.Cannot run program "svn"。 二.原因分析 在电脑上新安装的的客户端TortoiseSVN、ide…

高效稳定!新加坡服务器托管方案助力企业全球化布局

在全球化的商业环境中&#xff0c;企业对于高效、稳定的服务器托管方案的需求日益迫切。作为亚洲的服务器托管中心&#xff0c;新加坡凭借其独特的地理位置、稳定的政治环境、先进的科技设施以及开放的市场政策&#xff0c;为企业提供了理想的服务器托管解决方案&#xff0c;助…

NVR管理平台EasyNVR多品牌NVR管理工具/设备:为什么IPC白天图像正常,夜视漆黑?

在安防监控系统中&#xff0c;IPC&#xff08;网络摄像机&#xff09;扮演着至关重要的角色。然而&#xff0c;有时用户可能会遇到这样的问题&#xff1a;IPC在白天时图像清晰正常&#xff0c;但到了夜晚却变得漆黑一片&#xff0c;无法看清监控画面。 为什么IPC白天图像正常&a…

安卓aab包的安装教程,附带adb环境的配置

一、ADB环境配置 安装aab包的前提是需要有adb环境&#xff0c;下面先介绍adb环境的配置 ADB通常位于/platform-tools/。 在Windows上&#xff0c;你可以通过以下步骤添加到环境变量&#xff1a; 右键点击“我的电脑”或“此电脑”&#xff0c;选择“属性”。 点击“高级系…