单片机接口与技术 实验03 显示器与按键

这篇具有很好参考价值的文章主要介绍了单片机接口与技术 实验03 显示器与按键。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

前言:

1、实验目的:

2、实验内容:

第一版:lcd1602显示器:

代码

电路图

第二版(提高版):

代码:

lcd1602.h

lcd1602.c

main.c

电路图:

电路图详解:

代码详解:

lcd1602.h

lcd1602.c

lcd1602命令字

重点:

        首先是初始化

        显示字符串

        设置光标位置

        设置屏幕闪烁和光标屏幕移动

        关于宏

main.c

总结


前言:

本次实验,第一版过于简单,所以简略带过,详解在第二版当中,弄懂了第二版,第一版完全就是小卡拉米。其实对于lcd操作的核心就是对lcd指令的封装,本文会很好的体现。

1、实验目的:

(1)学习lcd 1602的编程与使用;

(2)机械式复位开关button软件消抖的方法。

2、实验内容:

第一版:lcd1602显示器:

先显示开机画面,:在1602显示器上,分两行分别居中显示字符“  AHAU  CHINA  ” 和 "  I LOVE YOU  "。然后从右向左移动直至消失。其中1602的rs、rw、en引脚分别使用单片机的P2.0、P2.1、P2.2引脚。

要求:将两行字符存储在数组中。

将lcd1602的基本操作函数都写到一个头文件中,供主函数文件调用。

在主函数文件中,只处理与显示内容有关的业务。

代码

批注:第一版代码过于简单,所以没保存,但是提高版是在第一版的基础上扩展的,所以第二版的代码,可以向下兼容第一版的代码,核心是函数封装调用。

单片机接口与技术 实验03 显示器与按键,微机原理1-4班,单片机,计算机外设,嵌入式硬件,51单片机,proteus

单片机接口与技术 实验03 显示器与按键,微机原理1-4班,单片机,计算机外设,嵌入式硬件,51单片机,proteus

电路图

单片机接口与技术 实验03 显示器与按键,微机原理1-4班,单片机,计算机外设,嵌入式硬件,51单片机,proteus

第二版(提高版):

两行逐个显示,两行字符全部出现后整体静态显示1秒左右,然后闪烁3次,最后从右向左移动直至消失。

 按键button与lcd1602:第一行居中显示:“a:?”,其中?为a的值,随按键变化。

其中无符号字节型变量a初值为0,其值实时显示在lcd 1602上。当复位开关S1(设置)按下时,a的值闪烁显示;S2(增加)每按一次,a增1;直至a增为 9,再按一次S2,a 归 0;S3(减少)按键每按一次,a 自减 1; 如此反复,并将 a 的值实时送至lcd 1602以闪烁的形式显示出来“a:?”,其中?为a的值,并闪烁显示。当按下S4(确认)时,a的值确定并不再闪烁。

其中S1、S2、S3、S4均为复位开关(button),即轻按接通、释放后自动复位断开。S1、S2、S3、S4与单片机的接口请遵照学习板电路的设置(见学习板电路原理图)。 

代码:

lcd1602.h
#ifndef LCD1602_H
#define LCD1602_H

#include <reg52.h>
#include "intrins.h"

/** LCD的所有操作都是基于指令的,关于LCD的功能函数的封装
  * 都是基于写入指令和写入数据两个操作实现的。
  * 即,下面的功能宏和函数都是对LCD指令的封装所以源文件不
  * 进行繁琐的注释,封装的功能在头文件都注释好了,详细可
  * 参见LCD1602的指令表。
  */

#define out P0		// 数据 to LCD
typedef unsigned int uint;
typedef unsigned char uchar;

sbit LCD_RS = P1^0; // 寄存器选择
sbit LCD_RW = P1^1; // 读/写
sbit LCD_EN = P1^2; // 使能

void Delay(uint t);	// 延迟函数

// 定义LCD1602基本操作函数
void LCD_CheckBusy(void);		// 检查忙标志位
void LCD_WriteCmd(uchar cmd);	// 写入命令
void LCD_WriteData(uchar dat);	// 写入数据
void LCD_Initial(void);			// 初始化LCD

void LCD_ShowString(uchar *s, uint t);			// 在LCD显示字符串
void LCD_SetCursor(uchar line, uchar column); 	// 设置光标位置
void LCD_ScreenFlicker(uchar num, uint t);		// 屏幕闪烁

// 光标/屏幕 左/右移 延迟
void LCD_CorS_Shift_LorR(uchar key, uchar disp, uint t); 

#define LCD_CSL(DISP) LCD_CorS_Shift_LorR(0, DISP, 0)			// 光标左移
#define LCD_CSR(DISP) LCD_CorS_Shift_LorR(1, DISP, 0)			// 光标右移
#define LCD_SSL(DISP, TIME) LCD_CorS_Shift_LorR(2, DISP, TIME)	// 屏幕左移
#define LCD_SSR(DISP, TIME) LCD_CorS_Shift_LorR(3, DISP, TIME)	// 屏幕右移

#define LCD_ShowMove_ON() LCD_WriteCmd(0x07)		// 打开屏幕随光标移动
#define LCD_ShowMove_OFF() LCD_WriteCmd(0x06)		// 关闭屏幕随光标移动
#define LCD_CursorFlicker_ON() LCD_WriteCmd(0x0f)	// 打开光标闪烁
#define LCD_CursorFlicker_OFF() LCD_WriteCmd(0x0c)	// 关闭光标闪烁

#define LCD_Clear() LCD_WriteCmd(0x01)	// 清屏

#endif
lcd1602.c
#include "lcd1602.h"

void Delay(uint t)
{
	uchar i = 240;
	for (; t > 0; t--)
	{
		while (--i);
		i = 249;
		while (--i);
		i = 250;
	}
}

void LCD_CheckBusy(void)
{
	uchar dt;
	do
	{
		dt = 0xff;
		LCD_EN = 0;
		LCD_RS = 0;
		LCD_RW = 1;
		LCD_EN = 1;
		dt = out;
	}
	while (dt & 0x80);
	LCD_EN = 0;
}

void LCD_WriteCmd(uchar cmd)
{
	LCD_CheckBusy();
	LCD_EN = 0;
	LCD_RS = 0;
	LCD_RW = 0;
	out = cmd;
	LCD_EN = 1;
	_nop_();
	LCD_EN = 0;
	Delay(1);
}	

void LCD_WriteData(uchar dat)
{
	LCD_CheckBusy();
	LCD_EN = 0;
	LCD_RS = 1;
	LCD_RW = 0;
	out = dat;
	LCD_EN = 1;
	_nop_();
	LCD_EN = 0;
	Delay(1);
}	

void LCD_Initial(void)
{
	LCD_WriteCmd(0x38); // 命令6
	LCD_WriteCmd(0x0c); // 命令4
	LCD_ShowMove_OFF(); // 命令3 : LCD_WriteCmd(0x06)
	LCD_Clear(); 		// 命令1      
	Delay(1);
}

void LCD_ShowString(uchar *s, uint t)
{
	while (*s > 0)
	{
		LCD_WriteData(*s++);
		Delay(t);
	}
}

void LCD_SetCursor(uchar line,uchar column)
{
	if (--column > 40 || --line > 2) return;
	LCD_WriteCmd((line ? 0x40 : 0) + 0x80 | column);
}

void LCD_ScreenFlicker(uchar num, uint t)
{
	t >>= 1;
	while (num--)
	{
		LCD_WriteCmd(0x08);
		Delay(t);
		LCD_WriteCmd(0x0c);
		Delay(t);
	}
}

void LCD_CorS_Shift_LorR(uchar key, uchar disp, uint t)
{
	if (key > 3) return;
	// 00:光标左移 01:光标右移 10:屏幕左移 11:屏幕右移
	do {
		LCD_WriteCmd(0x10 + (key << 2));
		Delay(t);
	} while (--disp);
}
main.c
#include "lcd1602.h"

void main(void)
{
	char number[2] = {48, 0};		// 让number可以顺利打印
	uchar key, sure = 0, enter = 0; // 一些标志
	LCD_Initial();					// 初始化

	// 开机界面
	LCD_SetCursor(1, 17);			// 设置光标在显示屏之外
	LCD_ShowString("AHAU CHINA", 10);
	LCD_SetCursor(2, 17);
	LCD_ShowMove_ON();				// 一边输出第二行子一边移动屏幕
	LCD_ShowString("I LOVE YOU", 100);
	LCD_ShowMove_OFF();				// 恢复状态(输出字符不移动屏幕)
	LCD_SSL(3, 100);				// 字体移动居中
	LCD_ScreenFlicker(3, 500);		// 闪烁三次,周期约1秒
	LCD_SSL(13, 100);				// 移动出屏幕
	Delay(100);
	LCD_Clear();
	Delay(100);

	// 初始化状态
	LCD_SetCursor(1, 7);
	LCD_ShowString("a:", 100);
	LCD_ShowString(number, 0);
	LCD_CSL(1);
	LCD_CursorFlicker_ON(); // 打开光标闪烁
	
	while (1)
	{
		key = P3 >> 4;
		switch (key)
		{
			case 0x0e: 				// s4
				Delay(10);			// 去抖
				if (!enter && key == P3 >> 4)
				{	// 锁定当前数字 关闭光标闪烁
					enter = 1;
					sure = 1;
					LCD_CursorFlicker_OFF();
				}
				break;
			case 0x0d: 				// s3
				Delay(10);
				if (!enter && !sure && key == P3 >> 4)
				{	// 数字0-9循环减1
					enter = 1;
					number[0] += number[0] == 48 ? 9 : -1;
					LCD_ShowString(number, 0);
					LCD_CSL(1);
				}
				break;
			case 0x0b: 				// s2
				Delay(10);
				if (!enter && !sure && key == P3 >> 4)
				{	// 数字0-9循环加1
					enter = 1;
					number[0] += number[0] == 57 ? -9 : 1;
					LCD_ShowString(number, 0);
					LCD_CSL(1);
				}
				break;
			case 0x07: 				// s1
				Delay(100);
				if (!enter && key == P3 >> 4)
				{	// 将a的值清零
					enter = 1;
					sure = 0;
					LCD_CursorFlicker_ON();
					number[0] = 48;
					LCD_ShowString(number, 0);
					LCD_CSL(1);
				}
				break;
			case 0x0F:
				// 解除按键锁定 每次按下将按键锁定,防止频繁触发按键效果
				enter = 0;
		}
	}
}

电路图:

单片机接口与技术 实验03 显示器与按键,微机原理1-4班,单片机,计算机外设,嵌入式硬件,51单片机,proteus

电路图详解:

        左半部分主要是AT89C52单片机的时序电路、复位电路,固定套路没什么好说的。

        与第一版不同的是,为了与电路版相符合,将RS、RW、EN三个引脚从P2口切换到了P1口,负责控制lcd状态。

        为了让电路图清晰,将排阻和lcd的使能电路单独拿出来放在上方。P0口作为lcd的数据端口,右边添加了4个按键对应题目中的功能。

        注意单片机不宜供电负荷太大,所以与单片机连接的元器件都采用排阻外部供电的方式再与单片机连接。

代码详解:

        代码详解主要针代码实现思路,如何实现都是次要的,重要的是编程思维和思路。头文件可以快速了解使用方法,主要是方法的定义,mian文件主要是对头文件的调用,源文件就是通过包装指令写入实现功能。

lcd1602.h

        首先得包含单片机的寄存器头文件和汇编命令头文件。

        第一部分,将三个最重要的操作lcd的引脚用sbit封装好,加上一个常用的延迟函数。至于对uint和uchar使用宏定义还是typedef看个人习惯,我是感觉没啥差别。

单片机接口与技术 实验03 显示器与按键,微机原理1-4班,单片机,计算机外设,嵌入式硬件,51单片机,proteus

        第二部分,是操作lcd最核心的三个函数,所有lcd的复杂操作,的相关的函数功能都是基于写入命令和写入数据函数的封装。

单片机接口与技术 实验03 显示器与按键,微机原理1-4班,单片机,计算机外设,嵌入式硬件,51单片机,proteus

        第三部分,便是基于写入命令和写入数据,针对于常用或者接下来要用到的复杂操作进行封装。分别是:初始化lcd、显示字符串、设置光标位置、光标和屏幕的移动、屏幕闪烁(这个为了达成题目要求)。

单片机接口与技术 实验03 显示器与按键,微机原理1-4班,单片机,计算机外设,嵌入式硬件,51单片机,proteus

        第四部分使用宏函数进一步进行封装放在源文件当中结合实现原理讲解更好。

lcd1602.c

        延迟函数大约是1ms,看自己习惯去写把,非工业级不要求精确,能用就行。

单片机接口与技术 实验03 显示器与按键,微机原理1-4班,单片机,计算机外设,嵌入式硬件,51单片机,proteus

        查忙,写命令,写数据的函数都是固定的,明白原理就行。

lcd1602命令字

        单片机接口与技术 实验03 显示器与按键,微机原理1-4班,单片机,计算机外设,嵌入式硬件,51单片机,proteus

单片机接口与技术 实验03 显示器与按键,微机原理1-4班,单片机,计算机外设,嵌入式硬件,51单片机,proteus

重点:

        我放出了lcd1602的指令表,接下来的所有操作都是基于这张表的。

        首先是初始化

        可以看到初始化就是写入四条命令
        1.命令6:8位数据接口,两行显示,5*7点阵。

        2.命令4:打开显示屏,无光标

        3.命令3:设置指针自增,屏幕不跟随

        4.命令1:清屏

        总结下来就是根据自己想要的效果打开屏幕,设置lcd的一些初始状态,因为我需要开机画面所以初始化不带光标,如果开机就是输入,那也可以初始化带光标。根据实际情况进行操作。

单片机接口与技术 实验03 显示器与按键,微机原理1-4班,单片机,计算机外设,嵌入式硬件,51单片机,proteus

        显示字符串

        非常简单啊,就是像lcd中逐条写入数据

单片机接口与技术 实验03 显示器与按键,微机原理1-4班,单片机,计算机外设,嵌入式硬件,51单片机,proteus

        设置光标位置

        设置光标位置是为了配合显示字符串使用的。lcd有80字节的数据存储器,地址为00H-27HH和40H-67H,配合指令就可以将光标移动到指令位置,写入数据。

单片机接口与技术 实验03 显示器与按键,微机原理1-4班,单片机,计算机外设,嵌入式硬件,51单片机,proteus

        设置屏幕闪烁和光标屏幕移动

        现在在来看,屏幕闪烁就是命令4控制屏幕打开关闭加上延迟函数。

        而屏幕和光标的移动就是将命令5进行了封装,加上循环。

单片机接口与技术 实验03 显示器与按键,微机原理1-4班,单片机,计算机外设,嵌入式硬件,51单片机,proteus

        关于宏

        有了前面的铺垫,再来讲为什么要用宏对上面的指令进行二次封装。首先要明确的是,对lcd的所有操作都是基于写入命令和写入数据来实现的。而所有复杂的功能也都是写入不同指令来完成的。那这样其实我们完全不需要其他函数了,一个写入命令一个查忙一个写入数据,仨函数就能完成所有的操作了。

        对此我想说的是,我们学汇编做什么呢,汇编有那么多指令,而机器语言只有0和1两个数组成,何必使用汇编助记符。

        所以那么多指令,加上其他元器件指令数不清,全部记下来效率太低了,将相同操作逻辑的指令抽象成函数,再将函数复杂的功能分离成简单的接口,这便是面向对象的思想。

单片机接口与技术 实验03 显示器与按键,微机原理1-4班,单片机,计算机外设,嵌入式硬件,51单片机,proteus

        对指令5加循环的封装,第一个参数起作用的只有0123,但是0123不好记,而且可能会无传其他参数,将他们通过宏封装成4个固定的函数,可以解决这个问题,而通常光标移动不需要延迟,但是屏幕移动需要延迟,变将常用的封装。

        有人觉得将屏幕和光标分开成两个函数更好,但是题目的运行逻辑是相同的,分开反而会造成代码冗余,浪费存储空间。

        而对于一些调整lcd状态的命令,通过宏封装起来,增强可读性,也方便了自己的代码编写。

main.c

        关于main函数,其实就是对上面封装方法的调用,和一些编程的技巧。初始化没什么好说的,按照题目要求调整即可。

        需要注意的就是需要通过延迟函数进行消抖操作,防止抖动造成的按键按压,鼠标爱好者应该对此有所了解,追求极致的dpi和=,按键灵敏度就会造成消抖太短,或是有些鼠标直接没有消抖,就会出现一种情况,拿着鼠标往桌上敲一下,按键触发,敲一下,触发。

        第二点就是,我们可以通过一个标志变量来优化程序逻辑,比如通过sure来锁定加减按键,被锁定后,再次加减,无效。我通过enter来锁定,防止按下后一直频繁触发按键功能。

        也有其他思路,比如存储上一次按下的按键,当释放时按键生效,也可以通过enter关键字来实现按键之间的组合和冲突,实现复杂逻辑,或者按键按下一定时间后触发连击效果等等。

总结

        主要分享单片机编程的思路,针对lcd,其实就是对写入命令进行封装。二次封装的原因同为什么不用机器语言编程而使用汇编语言助记符时同样的,封装还可以减少代码体积,增强可读性等等。还分享了一些编程时候的技巧和编程思想。文章来源地址https://www.toymoban.com/news/detail-713823.html

到了这里,关于单片机接口与技术 实验03 显示器与按键的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 单片机C51液晶显示器LM016L的操作方法

    注:这里上面的应该为:sbit en=P2^2; P需要大写,刚开始截图的时候未注意到,抱歉。 以上就是今天要讲的内容,本文简单介绍了单片机中液晶显示器LM016L的使用,还有许多的命令没有提到,大家可以再参考书籍或其他博客等进行拓展。 最后:希望大家学习进步!事业有成!

    2024年02月01日
    浏览(46)
  • STM32单片机三线制PT100温度采集控制系统LCD12864显示器

    功能介绍:    

    2024年02月15日
    浏览(61)
  • 初学51单片机(STC89C52)一个倒计时显示器和大家分享

      想要实现倒计时显示器,首先得确定从哪个时间开始倒计时,这就需要写出一个计数的程序来,通过按键来控制需要的数,从而开始倒计时。我的开发板上用的Key2,Key3,Key4,Key5这四个键,分别对应着加1,减1,乘2,开始计时四个功能。   通过加一,减一,乘2三个操作,

    2024年02月10日
    浏览(58)
  • 【TB作品】MSP430单片机 Proteus仿真 DS18B20温度 LCD1602显示器 温度读取与显示

    效果图如下: 首先,让我们先来说说DS18B20集成电路。 • DS18B20是一款采用OneWire通讯协议的集成电路,因此只需要一条线就可以与微控制器通讯。它不需要额外的电源,但是也有外部电源输入端口。 • OneWire设备具有64位的ROM代码。如我们之前所说,这64位的前8位是家族代码,中间

    2024年02月08日
    浏览(69)
  • 基于51单片机 + MQ-3酒精传感器 + ADC0832模数转换器 + LCD1602液晶显示器的酒精检测系统

    废话不多说,直接上东西。本文是基于51单片机的酒精检测系统设计,用的元器件有:51单片机、MQ-3酒精传感器、ADC0832模数转换器、 LCD1602液晶显示器、喇叭等元器件。 1、MQ-3 酒精检测传感器,用于检测酒精浓度。当然采集到的数据是模拟的还需要通过ADC0832模数转换器将其转

    2024年02月12日
    浏览(59)
  • 单片机实验——键盘与显示实验

    利用独立键盘和4位一体七段LED数码管,分别完成以下实验内容: 1.使用4位一体七段LED数码管的个位,设计一台仅有个位的秒表,要求: 1)每一秒钟到,数码管自动加 1 并显示。(提示:可用静态显示方式,时间累计用延时实现) 2.使用4位一体七段LED数码管的4个位,设计一

    2024年02月11日
    浏览(32)
  • 51单片机 | LCD1602 液晶显示实验

      在前面章节,我们已经学习过几种显示装置,例如静态数码管、动态数码管、 8*8LED 点阵、串口通信。使用它们可以直观显示一些字符数据,但是它们也有各种局限性,比如显示字符数据太少,硬件设计复杂、代码编写难度大等。这一章就来介绍一种非常简单且常用的显

    2023年04月11日
    浏览(64)
  • 51单片机 | LED点阵实验 | 点亮一个点 | 显示数字 | 显示图像

      开发板上使用了 64 个红色 LED 按照行列排布组成的 8*8 LED 点阵。下面介绍 LED 点阵的使用。    LED 点阵 是由发光二极管排列组成的显示器件,在我们日常生活的电器中随处可见,被广泛应用于汽车报站器,广告屏等。如下所示:   通常应用较多的是 8*8 点阵,然后使

    2023年04月08日
    浏览(43)
  • 【51单片机】LCD1602 液晶显示实验指导书

             来介绍一种非常简单且常用的显示装置——LCD1602 液晶显示器,使用它可以显示更多的字符数字。这将有助于我们清晰的观察程序的运行结果,更加方便我们的后续调试和开发。         我们的开发板上集成了一个 LCD1602 液晶显示器接口,将LCD1602 液晶对应插

    2024年02月01日
    浏览(63)
  • 【小实验】C51单片机 DS18B20温度显示实验

         利用单总线技术和数码管动态显示的原理,要求实现DS18B20温度采集并显示,能够设定温度值上限值27.5度,当超出上限值LED灯闪烁。    实验前可先用protues绘制出原理图:   代码仅供参考,希望大家能够在此基础上优化代码,而不是ctrl+c,ctrl+v。 谢谢!!!        

    2024年02月12日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包