基于51单片机LCD1602的简易矩阵键盘密码锁

写在前面

初次开始写博客,表达方面也许会有很多不足,希望自己能通过这种方式巩固自己的学习和锻炼表达能力,同时也是对于自己学习的记录。

一、功能介绍

  1. 四位密码锁,密码可更改,输入仅四次以内有效
  2. 矩阵键盘定义为1-16,顺序为从左上到右下,1-10号为密码输入键位,对键码取余,输入10时为0, 定义11号键码为确认键,12号键码为取消/结束键
  3. 输入密码可通过取消键随时清零,同时显示清空,输入结束按下确认键后,密码正确则显示"Right","Welcome back!", 停滞一秒后进入下一显示界面;密码错误显示"Error","Input again."
  4. 密码正确后的下一显示界面可以自由发挥

二、程序设计 

1、延时函数

1.1、实现功能

输入参数为延时时间长度,单位为毫秒,用于短暂延时

1.2、设计原理

从STC-ISP 中生成的延时1ms的代码修改得到的延时任意时间的函数

1.3、代码实现

/**
  * @brief 延时函数
  * @param  延迟的时间xms
  * @retval 无
  */

void Delay(unsigned int xms)		//@12.000MHz
{
	unsigned char i, j;
  while(xms)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
	
}

2、矩阵键盘函数

2.1、实现功能

将矩阵键盘从左上到右下编为1-16,当按下其中一个按键,松开的一瞬间程序返回该按键对应的键码,如果按下不放,程序将停在此函数;没有按下的时候函数返回值为0.

2.2、设计原理

通过STC89C52开发板原理图我们可以看出,矩阵键盘由八个I/O口驱动,由于51单片机的按键都是按下检测为低电平,松开检测为高电平,所以检测按键按下的方式为:

  1. 先将P17 – P10都置1
  2. 置零第一列, 即P13 = 0,扫描P17 – P14, 若P17 = 0,则S1按下,P16 = 0,则S5按下,以此类推,检测第一列是否有按键按下
  3. 继续以同样的方式检测后三列,即可判断哪个按键按下,返回相应的键码即可

2.3、代码实现

函数说明和定义变量

/**
  * @brief 矩阵键盘读取按键键码
  * @param  无
  * @retval KeyNumber
  如果按键按下不放,程序会停留在此函数,松手一瞬间返回按键键码,没有按键按下时返回0
  */

unsigned char MatrixKey()
{
	unsigned char KeyNumber = 0;

扫描第一列的代码如下

	P1 = 0xFF;
	P1_3 = 0;
	if(P1_7 == 0){Delay(20);while(!P1_7);Delay(20);KeyNumber = 1;}
	if(P1_6 == 0){Delay(20);while(!P1_6);Delay(20);KeyNumber = 5;}
	if(P1_5 == 0){Delay(20);while(!P1_5);Delay(20);KeyNumber = 9;}
	if(P1_4 == 0){Delay(20);while(!P1_4);Delay(20);KeyNumber = 13;}
	

 完整代码就是在函数体里用上面这种格式写四次扫描,简单但冗长就不贴在这里了

3、LCD1602功能函数

LCD1602功能函数有初始化、显示字符、显示无符号/有符号数字、显示字符串等等

函数声明模块

#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

本次用到的LCD1602显示函数有LCD_Init、LCD_ShowString、LCD_ShowNum

代码实现段

/**
  * @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  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  在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');
	}
}

4、主函数设计

4.1、实现功能

接收按键按下函数返回的键码,对其进行判断,未松开不执行后面的程序,松开后判断四次以内按下密码是否正确,11 号键为确认键,12号为取消/结束键

4.2、设计原理

定义Count用于计数,keyNum用于接收按键返回键码

unsigned int PassWord,Count,KEYPASS = 120;
unsigned char keyNum;

 LCD1602初始化显示初始界面

LCD_Init(); // LCD初始化
Delay(100);
LCD_ShowString(1,1,"PassWord:");

while(1)结构使得程序不停止一直执行

返回按键键码在10以内,且输入在四次以内,对每一次按下的键码进行左移位操作形成四位密码

    			if(keyNum <= 10) //定义1-10号为密码输入键
				{
					if(Count<4)   //只允许输入四次有效
					{
						PassWord = 10*PassWord;  //密码位数左移一位
						PassWord += keyNum%10;   //获取一位密码
					}
					Count++;                     //计数输入次数

接下来就是关于密码正确与否的相关设计比较简单下面附完整代码

4.3、代码实现

#include <REGX52.H>
#include"LCD1602.h"
#include"Delay.h"
#include"MatrixKey.h"

unsigned int PassWord,Count,KEYPASS = 120;
unsigned char keyNum;

void main()
{
	
	LCD_Init(); // LCD初始化
	Delay(100);
	LCD_ShowString(1,1,"PassWord:");
	while(1)
	{
		keyNum = MatrixKey();  //接收返回的按键键码
		if(keyNum)             //判断是否有非取消键按下,没有按键按下执行显示键码;按键按下未松开不执行;
		{
			if(keyNum != 12)    //定义12号键为取消&退出键
			{
				if(keyNum <= 10) //定义1-10号为密码输入键
				{
					if(Count<4)   //只允许输入四次有效
					{
						PassWord = 10*PassWord;  //密码位数左移一位
						PassWord += keyNum%10;   //获取一位密码
					}
					Count++;                     //计数输入次数
				}
				LCD_ShowNum(2,1,PassWord,4);     //显示当前输入的密码
				
				if(keyNum == 11)      //定义11号键为确认键
				{
					Delay(200);
					if(PassWord == KEYPASS)    //密码正确
					{
						LCD_ShowString(1,11,"Right");
						Delay(200);
						LCD_ShowString(2,1,"Welcome back!");
						Delay(1000);
						LCD_Init();
						LCD_ShowString(1,1,"11.27    Sunday");
						LCD_ShowString(2,1,"I love you.");
					}
					else                       //密码错误
					{
						LCD_ShowString(1,11,"Error");
						PassWord = 0;
						Count = 0;
						Delay(500);
						LCD_ShowString(2,1,"Input again");
						Delay(1000);
						LCD_Init();           	 //初始化LCD
						LCD_ShowString(1,1,"PassWord:");
					}
				}
			}				
			else                //按下取消键
			{
				Count = 0;
				PassWord = 0;
				LCD_Init();      //初始化LCD
				LCD_ShowString(1,1,"PassWord:");
			}	
		}	
	}
}

三、结果展示

初始界面

 密码错误

 密码正确

 

1秒后跳转

 用来给对象表白了hhh

物联沃分享整理
物联沃-IOTWORD物联网 » 基于51单片机LCD1602的简易矩阵键盘密码锁

发表评论