当前位置: 首页 > news >正文

17 LCD1602模块——显示屏

一、51单片机模块

二、LCD1602模块

三、模块间的连接

单片机P2端口:P2_5~P2_7

单片机P0端口:P0_0~P0_7

四、LCD1602芯片

1、参数和引脚

这里只需要了解单片机的引脚功能,也可以大致看一眼,后面在编码显示功能的时候,也会做详细的说明。

2、LCD1602内部的控制指令

LCD1602 的读写操作、屏幕和光标的操作都是通过指令编程来实现的。

技巧:

最高位哪位是1——就是哪个指令,然后集体的看剩下的0和1情况

LCD1602 内部的控制器共有11条控制指令,如表所示:

  • 指令1:清显示,指令码 01H,光标复位到地址 00H 位置。

  • 指令2:光标复位,光标返回到地址00H。

  • 指令3:

    • I/D:光标和显示模式设置,光标移动方向,高电平右移,低电平左移;

    • S:屏幕上所有文字是否左移或者右移。高电平表示有效,低电平则无效。

  • 指令4:显示开关控制。

    • D:控制整体显示的开与关,高电平表示开显示,低电平表示关显示;

    • C:控制光标的开与关,高电平表示有光标,低电平表示无光标;

    • B:控制光标是否闪烁,高电平闪烁,低电平不闪烁。

  • 指令5:

    • S/C:高电平时移动显示的文字,低电平时移动光标;

    • R/L:高电平时右移,低电平时左移。

  • 指令6:功能设置命令 DL:高电平时为4位总线,低电平时为8位总线;

    • N:低电平时为单行显示,高电平时双行显示;

    • F:低电平时显示5x7的点阵字符,高电平时显示5x10的点阵字符。

  • 指令7:字符发生器RAM地址设置。

  • 指令8:DDRAM地址设置。

  • 指令9:读忙信号和光标地址

    • BF:为忙标志位,高电平表示忙,此时模块不能接收命令或者数据,如果为低电平表示不忙。

  • 指令10:写数据。

  • 指令11:读数据

3、基本操作时序

LCD1602 的基本的操作分为以下四种:

状态字读操作:输入 RS=0、RW=1、E=1;输出:D0~7 读出为状态字;

数据读出操作:输入 RS=1、RW=1、E=1;输出:D0~7 读出为数据;

指令写入操作:输入 RS=0、RW=0、E=上升沿; 输出:无;

数据写入操作:输入 RS=1、RW=0、E=上升沿; 输出:无。

4、LCD1602模块

(1)LCD1602.c

这里不用看,只是把全部的复制了一下。

可以在5里看详细的各个部分的介绍——因为新手本来就第一次接触,看不懂也没关系——只要能一步一步学下去就是成功——直接跳到5即可

#include <REGX52.H> //引脚配置: sbit LCD_RS=P2^6; sbit LCD_RW=P2^5; sbit LCD_EN=P2^7; #define LCD_DataPort P0 //函数定义: /** * @brief LCD1602延时函数,12MHz调用可延时1ms * @param 无 * @retval 无 */ void LCD_Delay() { 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_EN=1; LCD_Delay(); LCD_EN=0; LCD_Delay(); } /** * @brief LCD1602写数据 * @param Data 要写入的数据 * @retval 无 */ void LCD_WriteData(unsigned char Data) { LCD_RS=1; LCD_RW=0; LCD_DataPort=Data; LCD_EN=1; LCD_Delay(); LCD_EN=0; LCD_Delay(); } /** * @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 if(Line==2) { LCD_WriteCommand(0x80|(Column-1+0x40)); } } /** * @brief LCD1602初始化函数 * @param 无 * @retval 无 */ void LCD_Init() { LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵 LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关 LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动 LCD_WriteCommand(0x01);//光标复位,清屏 } /** * @brief 在LCD1602指定位置上显示一个字符 * @param Line 行位置,范围:1~2 * @param Column 列位置,范围:1~16 * @param Char 要显示的字符 * @retval 无 */ void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char) { LCD_SetCursor(Line,Column); LCD_WriteData(Char); } /** * @brief 在LCD1602指定位置开始显示所给字符串 * @param Line 起始行位置,范围:1~2 * @param Column 起始列位置,范围:1~16 * @param String 要显示的字符串 * @retval 无 */ void LCD_ShowString(unsigned char Line,unsigned char Column,char *String) { unsigned char i; LCD_SetCursor(Line,Column); for(i=0;String[i]!='\0';i++) { LCD_WriteData(String[i]); } } /** * @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; } /** * @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(Number/LCD_Pow(10,i-1)%10+'0'); } } /** * @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; } for(i=Length;i>0;i--) { LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0'); } } /** * @brief 在LCD1602指定位置开始以十六进制显示所给数字 * @param Line 起始行位置,范围:1~2 * @param Column 起始列位置,范围:1~16 * @param Number 要显示的数字,范围:0~0xFFFF * @param Length 要显示数字的长度,范围:1~4 * @retval 无 */ void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length) { unsigned char i,SingleNumber; LCD_SetCursor(Line,Column); for(i=Length;i>0;i--) { SingleNumber=Number/LCD_Pow(16,i-1)%16; if(SingleNumber<10) { LCD_WriteData(SingleNumber+'0'); } else { LCD_WriteData(SingleNumber-10+'A'); } } } /** * @brief 在LCD1602指定位置开始以二进制显示所给数字 * @param Line 起始行位置,范围:1~2 * @param Column 起始列位置,范围:1~16 * @param Number 要显示的数字,范围:0~1111 1111 1111 1111 * @param Length 要显示数字的长度,范围:1~16 * @retval 无 */ void LCD_ShowBinNum(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(Number/LCD_Pow(2,i-1)%2+'0'); } }

(2)LCD1602.h

#ifndef __LCD1602_H__ #define __LCD1602_H__ //用户调用函数: void LCD_Init(); void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char); void LCD_ShowString(unsigned char Line,unsigned char Column,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

5、LCD1602.c里的各个函数

(1)引脚配置

LCD1602模块与单片机的功能实现需要用到的引脚——显示屏与单片机的线路连接起来

P0取个别名——在显示屏模块的名字表示

LCD_等——地址

做完准备工作,开始编写函数

(2)延时函数——LCD_Delay

接收数据和数据发送——给出一段时间

//1毫秒的延时 void LCD_Delay() { unsigned char i, j; i = 2; j = 239; do { while (--j); } while (--i); }

(3)指令写入函数——LCD_WriteCommand

  • RS
    • 低电平时,选择命令
    • 高电平时,选择数据
  • RW
    • 低电平时,向LCD1602写入命令或数据
    • 高电平时,从LCD1602读取状态或数据
    • 不需要进行读取操作,可以直接将其接VSS。
  • E
    • 执行命令的使能引脚

写入的数据以函数的参数写入到函数中

这个参数赋值给LCD_DataPort(别名)——P0

详细步骤:

  1. RS——低电平(选择命令)
  2. RW——低电平(向LCD1602写入命令)
  3. 把需要写的命令以参数的形式赋值给LCD_DataPort(P0)
  4. EN——高电平(使能信号)
  5. 延时函数
  6. EN——低电平(使能信号)
  7. 延时函数
// 1602液晶写命令函数,Command就是要写入的命令 void LCD_WriteCommand(unsigned char Command) { LCD_RS=0; //选择写指令 LCD_RW=0; //选择写 LCD_DataPort=Command; //把指令送入P0 LCD_EN=1; //使能线电平变化上升沿,命令送入1602的8位数据口 LCD_Delay(); //延时一小会儿,让1602准备接收数据 LCD_EN=0; //使能线拉低 LCD_Delay(); //延时,让数据发送 }

(4)数据写入函数——LCD_WriteData

详细步骤:

  1. RS——高电平(选择数据)
  2. RW——低电平(向LCD1602写入数据)
  3. 把需要写的数据以参数的形式赋值给LCD_DataPort(P0)
  4. EN——高电平(使能信号)
  5. 延时函数
  6. EN——低电平(使能信号)
  7. 延时函数
// 1602液晶写数据函数,Data就是要写入的数据 void LCD_WriteData(unsigned char Data) { LCD_RS=1; //选择写数据 LCD_RW=0; //选择写 LCD_DataPort=Data; //把数据送入P0 LCD_EN=1; //使能线电平变化上升沿,命令送入1602的8位数据口 LCD_Delay(); //延时一小会儿,让1602准备接收数据 LCD_EN=0; //使能线拉低 LCD_Delay(); //延时,让数据发送 }

(5)设置光标位置函数——LCD_SetCursor

两个参数分别为:行位置、列位置

详细步骤:

  1. 如果Line的参数为1。那么0x80与列数-1按位或后的结果,再以参数的形式调用写命令函数
  2. 如果Line的参数为2。那么0x80与列数-1+0x40按位或后的结果,再以参数的形式调用写命令函数
// 光标定位函数 void LCD_SetCursor(unsigned char Line,unsigned char Column) { if(Line==1) { LCD_WriteCommand(0x80|(Column-1)); //LCD_WriteCommand(0x80+column); } else if(Line==2) { LCD_WriteCommand(0x80|(Column-1+0x40)); //LCD_WriteCommand(0x80+0x40+column); } }

(6)初始化函数——LCD_Init

往上去找四中的2和3——控制指令、操作时序

//参数传入单片机的P0地址——参数是传入数据 void LCD_Init() { LCD_WriteCommand(0x38); // 16*2显示,5*7点阵,8位数据口 // 显示模式设置 //——————————————————————————————指令六:置功能 LCD_WriteCommand(0x0c); // 显示开,及光标设置——不显示光标 //——————————————————————————————指令四:显示开关控制 LCD_WriteCommand(0x06); // 地址加1,当写入数据后光标右移 // 显示光标移动设置 //——————————————————————————————指令三:置输入模式 LCD_WriteCommand(0x01); // 清屏 //——————————————————————————————指令一:清显示 }

(7)指定位置上显示一个字符函数——LCD_ShowChar

三个参数分别为:行位置、列位置、要显示的字符

详细步骤:

  1. 调用设置光标位置函数
  2. 调用写数据函数
//两个函数的调用 //光标位置——(行、列)——Line、Column //写的数据——char void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char) { LCD_SetCursor(Line,Column); LCD_WriteData(Char); }

(8)指定位置开始显示所给字符串——LCD_ShowString

三个参数分别为:起始行位置、起始列位置、要显示的字符

详细步骤:

  1. 定义一个变量i
  2. 调用光标位置函数
  3. 字符以参数的形式用for循环——调用写数据函数
//指定位置开始显示——字符串 //两个函数的调用 //设置光标位置 //参数传入的字符串——以for循环的形式一个一个写数据——直到循环到字符串的结束符 void LCD_ShowString(unsigned char Line,unsigned char Column,char *String) { unsigned char i; LCD_SetCursor(Line,Column); for(i=0;String[i]!='\0';i++) { LCD_WriteData(String[i]); } }

(9)返回值=X的Y次方函数——LCD_Pow

//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; }

(10)指定位置开始显示所给数字——LCD_ShowNum

四个参数分别为:起始行位置、起始列位置、要显示的数字、要显示的数字长度

详细步骤:

  1. 定义一个变量i
  2. 调用设置光标位置函数
  3. for函数——根据长度判断循环次数
  4. 要显示的数字——根据占位数——的依次输出

这里打个比方

如果输入的数字是1,占位4个

i=4 1/(10*10*10)=0 则0%10=0

i=3 1/(10*10)=0 则0%10=0

i=2 1/(10)=0 则0%10=0

i=1 1/1=1 则1%10=1

说明:

%的两边必须是——整型——运算完自动转为成了整型

但是LCD_WriteData的参数是无符号字符型,所以需要转换数据类型——+'0'的目的就是这个。

//指定位置开始显示——数字 //三个函数的调用 //设置光标位置 //根据参数传入的长度控制for循环的次数——写数据(参数依次从最高位到最低位) 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(Number/LCD_Pow(10,i-1)%10+'0'); } }

(11)指定位置开始以有符号十进制显示所给数字——LCD_ShowSignedNum

四个参数分别为:起始行位置、起始列位置、要显示的数字、要显示的数字长度

//指定位置——以有符号十进制显示——数字 //如果Num>0 比如1 符号用+ 数据=1 输出+1 //如果Num<0 比如-1 符号用- 数据=-(-1)=1 输出-1 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; } for(i=Length;i>0;i--) { LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0'); } }

(12)指定位置开始以十六进制显示所给数字——LCD_ShowHexNum

四个参数分别为:起始行位置、起始列位置、要显示的数字、要显示的数字长度

//指定位置——十六进制显示——数字 void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length) { unsigned char i,SingleNumber; LCD_SetCursor(Line,Column); for(i=Length;i>0;i--) { SingleNumber=Number/LCD_Pow(16,i-1)%16; if(SingleNumber<10) { LCD_WriteData(SingleNumber+'0'); } else { LCD_WriteData(SingleNumber-10+'A'); } } }

(13)指定位置开始以二进制显示所给数字——LCD_ShowBinNum

四个参数分别为:起始行位置、起始列位置、要显示的数字、要显示的数字长度

//指定位置——二进制显示——数字 void LCD_ShowBinNum(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(Number/LCD_Pow(2,i-1)%2+'0'); } }

五、main.c

用具体的函数再完整的顺一遍程序运行的过程。

#include <REGX52.H> #include "LCD1602.h" //包含LCD1602头文件 #include "Delay.h" //包含Delay头文件 int Result=0; void main() { LCD_Init(); while(1) { Result++; //Result自增 Delay(1000); //延时1秒 LCD_ShowNum(1,1,Result,3); //在LCD的1行1列显示Result,长度为3位 } }

指定位置开始显示所给数字——参数为(一行、一列、数字、占位数)

  1. 设置全局变量——Result——初值为0
  2. while循环
  3. Result++
  4. 延时1秒
  5. 调用函数——LCD_ShowNum
  6. ③~⑤循环

六、现象

LCD显示屏,上机后从000~999循环——间隔时间为1秒

说明:

在main.c中的代码只写实现逻辑的代码

  • 在指定位置
  • 什么进制形式
  • 输出的数字或者字符
  • 占几位

其他的都是辅助逻辑实现的。

http://www.jsqmd.com/news/808082/

相关文章:

  • Gemini3.1Pro解决新媒体小编选题难痛点
  • 电磁干扰(EMI)分析与RS示波器解决方案
  • AI Agent系统集成:从OpenClaw到Hermes的平滑迁移与混合架构实践
  • 苏州豆包GEO优化公司TOP服务商精选优质榜单 - 一网推GEO招财兔
  • Cadence实战指南:从原理图到PCB的网表导入全流程与常见报错解析
  • 3.C语言笔记:指针数组、函数
  • vue常见基础面试题
  • Spring中的Full模式和Lite模式,90%的开发都没搞明白
  • Gemini3.1Pro:商业分析框架搭建神器
  • 2026 国内明渠流量计十大品牌排行榜完整版 - 陈工日常
  • 2026最新文昌财税公司TOP8口碑推荐,代理记账乱账整理注册公司代办机构优选指南 - 品牌智鉴榜
  • 新手必看!用MP2451设计一个±12V双电源,聊聊反相Buck-Boost的PCB布局避坑指南
  • 别再只调包了!深入Kaggle糖尿病数据集:用逻辑回归前你必须做的5项数据诊断
  • 英雄联盟智能助手Seraphine:免费开源的终极游戏辅助神器,轻松提升你的游戏水平
  • 爱校哥会议屏租赁的口碑评价 - myqiye
  • 济南晨星驾驶培训:摩托车驾照一站式拿证指南,这些坑千万别踩! - 品牌策略师
  • JMeter 性能测试实战效果与能力全景展示
  • Cursor2API:开源代理工具实现免费AI接口协议转换与功能增强
  • 2026年陕西资质代办避坑指南:内行人揭秘行业猫腻 - COINUP
  • 【必收藏】2026年大模型学习全指南|小白程序员入门捷径,抓住百万年薪红利
  • 分析化学考研辅导班推荐:专门针对性培训机构评测 - michalwang
  • 告别ST-LINK依赖!在STM32CubeIDE 1.7+版本中,用DAP-LINK调试STM32F4的保姆级教程
  • 2026年口碑好的GEO公司推荐机构,上海翼锦领先 - myqiye
  • Gemini3.1Pro轻松搞定文献综述难题
  • 2026年5月国内专业酿醋设备厂家核心产品优势技术全维度解析 - 奔跑123
  • 软考 系统架构设计师历年真题集萃(254)
  • 【Web】使用Vue3开发3D游戏(十一)渲染3D高斯泼溅效果
  • 羽毛球每天必练的基本功:拉吊四方球战术、吊杀结合战术
  • 2026年常州高分子材料管业深度选购指南:编织网管与电池防护配件源头工厂直供全景对标 - 优质企业观察收录
  • 人机生殖隔离