单片机C语言实例:32、实用密码锁

2023-09-16 11:58:28

程序实例1:延时函数

#ifndef __DELAY_H__
#define __DELAY_H__
/*------------------------------------------------
 uS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
 长度如下 T=tx2+5 uS 
------------------------------------------------*/
void DelayUs2x(unsigned char t);
/*------------------------------------------------
 mS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void DelayMs(unsigned char t);

#endif

 

#include "delay.h"
/*------------------------------------------------
 uS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
 长度如下 T=tx2+5 uS 
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{   
	while(--t);
}
/*------------------------------------------------
 mS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void DelayMs(unsigned char t)
{
     
	while(t--)
	{
		//大致延时1mS
		DelayUs2x(245);
		DelayUs2x(245);
	}
}

程序实例2:1602驱动

#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include<intrins.h>

#ifndef __1602_H__
#define __1602_H__


 bit LCD_Check_Busy(void) ;

 void LCD_Write_Com(unsigned char com) ;

 void LCD_Write_Data(unsigned char Data) ;

 void LCD_Clear(void) ;

 void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) ;

 void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) ;

 void LCD_Init(void) ;
   
#endif
#include "1602.h"
#include "delay.h"

#define CHECK_BUSY

sbit RS = P2^4;   //定义端口 
sbit RW = P2^5;
sbit EN = P2^6;

#define RS_CLR RS=0 
#define RS_SET RS=1

#define RW_CLR RW=0 
#define RW_SET RW=1 

#define EN_CLR EN=0
#define EN_SET EN=1

#define DataPort P0

/*------------------------------------------------
              判忙函数
------------------------------------------------*/
bit LCD_Check_Busy(void) 
{ 
#ifdef CHECK_BUSY
	DataPort= 0xFF; 
	RS_CLR; 
	RW_SET; 
	EN_CLR; 
	_nop_(); 
	EN_SET;
	return (bit)(DataPort & 0x80);
#else
	return 0;
#endif
}

/*------------------------------------------------
              写入命令函数
------------------------------------------------*/
void LCD_Write_Com(unsigned char com) 
{  
	while(LCD_Check_Busy()); //忙则等待
	RS_CLR; 
	RW_CLR; 
	EN_SET; 
	DataPort= com; 
	_nop_(); 
	EN_CLR;
}
/*------------------------------------------------
              写入数据函数
------------------------------------------------*/
void LCD_Write_Data(unsigned char Data) 
{ 
	while(LCD_Check_Busy()); //忙则等待
	RS_SET; 
	RW_CLR; 
	EN_SET; 
	DataPort= Data; 
	_nop_();
	EN_CLR;
}


/*------------------------------------------------
                清屏函数
------------------------------------------------*/
void LCD_Clear(void) 
{ 
	LCD_Write_Com(0x01); 
	DelayMs(5);
}

/*------------------------------------------------
              写入字符串函数
------------------------------------------------*/
void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) 
{           
	while (*s) 
 	{     
		LCD_Write_Char(x,y,*s);     
		s ++;  x++;   
 	}
 }
 
/*------------------------------------------------
              写入字符函数
------------------------------------------------*/
void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) 
{     
	if (y == 0) 
 	{     
		LCD_Write_Com(0x80 + x);     
 	}    
	else 
 	{     
		LCD_Write_Com(0xC0 + x);     
 	}        
	LCD_Write_Data( Data);  
}

/*------------------------------------------------
              初始化函数
------------------------------------------------*/
void LCD_Init(void) 
{
	LCD_Write_Com(0x38);    /*显示模式设置*/ 
	DelayMs(5); 
	LCD_Write_Com(0x38); 
	DelayMs(5); 
	LCD_Write_Com(0x38); 
	DelayMs(5); 
	LCD_Write_Com(0x38);  
	LCD_Write_Com(0x08);    /*显示关闭*/ 
	LCD_Write_Com(0x01);    /*显示清屏*/ 
	LCD_Write_Com(0x06);    /*显示光标移动设置*/ 
	DelayMs(5); 
	LCD_Write_Com(0x0C);    /*显示开及光标设置*/
}

程序实例3:按键驱动

#ifndef __KEYBOARD_H__
#define __KEYBOARD_H__

/*------------------------------------------------
按键扫描函数,返回扫描键值
------------------------------------------------*/
unsigned char KeyScan(void);  //键盘扫描函数,使用行列反转扫描法

/*------------------------------------------------
按键值处理函数,返回扫键值
------------------------------------------------*/
unsigned char KeyPro(void);

#endif
#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include"keyboard.h"
#include"delay.h"

#define KeyPort P3

/*------------------------------------------------
按键扫描函数,返回扫描键值
------------------------------------------------*/
unsigned char KeyScan(void)  //键盘扫描函数,使用行列反转扫描法
{
	unsigned char cord_h,cord_l;//行列值中间变量
	KeyPort=0x0f;            //行线输出全为0
	cord_h=KeyPort&0x0f;     //读入列线值
	if(cord_h!=0x0f)    //先检测有无按键按下
	{
		DelayMs(10);        //去抖
		if((KeyPort&0x0f)!=0x0f)
		{
			cord_h=KeyPort&0x0f;  //读入列线值
			KeyPort=cord_h|0xf0;  //输出当前列线值
			cord_l=KeyPort&0xf0;  //读入行线值
	
			while((KeyPort&0xf0)!=0xf0);//等待松开并输出
	
			return(cord_h+cord_l);//键盘最后组合码值
		}
	}
	return(0xff);     //返回该值
}

/*------------------------------------------------
按键值处理函数,返回扫键值
------------------------------------------------*/
unsigned char KeyPro(void)
{
	switch(KeyScan())
	{
		case 0x7e:return 0;break;//0 按下相应的键显示相对应的码值
		case 0x7d:return 1;break;//1
		case 0x7b:return 2;break;//2
		case 0x77:return 3;break;//3
		case 0xbe:return 4;break;//4
		case 0xbd:return 5;break;//5
		case 0xbb:return 6;break;//6
		case 0xb7:return 7;break;//7
		case 0xde:return 8;break;//8
		case 0xdd:return 9;break;//9
		case 0xdb:return 10;break;//a
		case 0xd7:return 11;break;//b
		case 0xee:return 12;break;//c
		case 0xed:return 13;break;//d
		case 0xeb:return 14;break;//e
		case 0xe7:return 15;break;//f
		default:return 0xff;break;
	}
}

程序实例4:main文件

#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include<stdio.h>
#include"1602.h"
#include"delay.h"
#include"keyboard.h"


unsigned char code password[]={1,2,3,4,5,6,7,8};//可以更改此密码做多组测试
//定义密码,实际上密码需要存在eeprom中,可以通过程序更改。请用户自行添加


/*------------------------------------------------
                    主程序
------------------------------------------------*/
main()
{
	unsigned char num,i,j;                  
	unsigned char passwordtemp[16];        //最大输入16个
	unsigned char inputtimes;              //密码输入错误次数
	unsigned char passwordlength,PLEN;     //输入密码长度,实际密码长度
	bit Flag;
	
	PLEN=sizeof(password)/sizeof(password[0]);//用于计算出实际密码长度
	
	LCD_Init();         //初始化液晶屏
	DelayMs(10);        //延时用于稳定,可以去掉
	LCD_Clear();        //清屏
	LCD_Write_String(0,0,"  Welcome! ");    //写入第一行信息,主循环中不再更改此信息,所以在while之前写入
	LCD_Write_String(0,1,"Input password!");    //写入第二行信息,提示输入密码
	while (1)         //主循环
	{
		num=KeyPro();  //扫描键盘
		if(num!=0xff)  //如果扫描是按键有效值则进行处理
		{ 
			if(i==0)    //输入是第一个字符的时候需要把改行清空,方便观看密码
			LCD_Write_String(0,1,"                ");//清除该行
			if(i<16)
			{
				passwordtemp[i]=num;
				LCD_Write_Char(i,1,'*');//输入的密码用"*"代替
			}
			i++;   //输入数值累加
			if((15==num)|| (i==16))//输入按键值15或者密码输入到最大值16,表示输入结束,需要进行比对
			{
				passwordlength=i-1;  //计算输入密码长度
				i=0;  //计数器复位
				if(passwordlength==PLEN)//长度相等则比较,否则直接输出错误
				{
					Flag=1;//先把比较位置1
					for(j=0;j<PLEN;j++)//循环比较8个数值,如果有一个不等 则最终Flag值为0
					Flag=Flag&&(passwordtemp[j]==password[j]);//比较输入值和已有密码
				}
				if(Flag)//如果比较全部相同,标志位置1
				{
					LCD_Write_String(0,1,"                ");//清除该行
					LCD_Write_String(0,1,"Right Open!>>>>");//密码正确显示的信息
					inputtimes=0;//输入正确则次数清零,重新计数
					Flag=0;      //清除正确标志
				}
				else 
				{
					LCD_Write_String(0,1,"                ");//清除该行
					LCD_Write_String(0,1,"Wrong! Retry!");//密码错误,提示重新输入
					inputtimes++;//连续输入错误,则次数累加
					if(inputtimes==3)
					{
						LCD_Write_String(0,1,"                ");//清除该行
						LCD_Write_String(0,1,"Wrong 3 times!");//密码错误,提示重新输入
						while(1);//停止该位置,重启电源后才能输入,实际实用中则需要等到一定时间后才能再次输入。
					}
				}

			}
		}	
	}
}

更多推荐

leetcode21合并两个有序链表

题目:将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。示例1:输入:l1=[1,2,4],l2=[1,3,4]输出:[1,1,2,3,4,4]示例2:输入:l1=[],l2=[]输出:[]示例3:输入:l1=[],l2=[0]输出:[0]提示:两个链表的节点数目范围是[0,5

web端程序访问过慢时如何判断问题

当Web端程序访问过慢时,可以按照以下步骤进行问题判断和排查:1.确认问题:确认Web端程序访问真的过慢,可以通过以下方法进行测试:在不同浏览器和设备上测试访问速度,以排除个别设备或浏览器的问题。在不同时间段进行测试,以排除网络高峰期的影响。确认网络连接是否稳定,可以尝试在多个网络环境下进行测试。2.检查服务器性能:如

3D医学影像PACS系统源代码

一、系统概述3D医学影像PACS系统,它集影像存储服务器、影像诊断工作站及RIS报告系统于一身,主要有图像处理模块、影像数据管理模块、RIS报告模块、光盘存档模块、DICOM通讯模块、胶片打印输出等模块组成,具有完善的影像数据库管理功能,强大的图像后处理功能,提高了临床诊断准确率。二、三维影像重建支持三维影像处理功能;

代码签名:保护你的软件的安全性和完整性

代码签名是一种数字签名技术,用于保护软件的完整性和身份。它通过使用一个密钥对软件代码进行签名,确保代码在下载和安装过程中没有被篡改。代码签名证书是一种数字证书,用于证明代码签名者的身份和代码的完整性。以下是代码签名证书如何保护您的软件的详细说明:1,确保软件的完整性:代码签名证书可以确保您的软件在下载和安装过程中没有被

【cmake开发(5)】cmake 设置常规变量、环境变量、内置变量;cmake 带参数编译和 -D 选项; c++源码通过-D 选项的宏定义进行条件编译

文章目录一、CMake变量的定义1.1定义常规变量1.2打印变量1.3环境变量1.4持久缓存1.5持久缓存原理1.6内置变量二、带参数编译2.1我们可以看到了-D选项,一般配合option命令2.2c++源码通过-D选项的宏定义进行条件编译参考在【cmake开发(3)】中,我们设置了makeinstall安装目录。这就

「网页开发|后端开发|Flask」08 python接口开发快速入门:技术选型&写一个HelloWorld接口

本文主要介绍为网站搭建后端时的技术选型考虑,以及通过写一个简单的HelloWorld接口快速了解前端和后端交互的流程。文章目录本系列前文传送门一、场景说明二、后端语言技术选型三、后端框架技术选型Django特点Flask特点FastAPI特点Tarnado特点四、用Flask先来个最简单的HelloWorld五、在前端

静态代理和动态代理

一、静态代理代理模式(ProxyPattern)是一种结构型设计模式,它的概念很简单,它通过创建一个代理对象来控制对原始对象的访问。代理模式主要涉及两个角色:代理角色和真实角色。代理类负责代理真实类,为真实类提供控制访问的功能,真实类则完成具体的业务逻辑。这样,当我们不方便或者不能直接访问真实对象时,可以通过代理对象来

Mysql----锁

文章目录锁概述全局锁全局锁概述全局锁操作表级锁表级锁表锁表级锁元数据锁表级锁意向锁行级锁行级锁行锁行级锁间隙锁&临键锁锁概述是什么是计算机协调多个进程或线程并发访问某一资源的机制。意义在数据库中,数据是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发

大数据之-Flink学习笔记

FlinkApacheFlink—数据流上的有状态计算。ApacheFlink是一个框架和分布式处理引擎,用于对无界和有界数据流进行有状态计算处理。任何类型的数据都以事件流的形式生成。信用卡交易、传感器测量、机器日志或网站或移动应用程序2上的用户交互,所有这些数据都以流的形式生成。数据可以作为无界或有界流进行处理。无界

U盘格式化后数据能恢复吗?详细答案看这里!

“U盘格式化之后数据还可以恢复吗?这真的困扰了我好久!之前由于u盘中病毒,不得已将它格式化了,但是我还有好多视频、图片都保存在里面,这该怎么办呢?”小小的u盘,可是给我们带来了很多的便利的。在互联网时代,u盘的作用也是越来越大。但不否认的是,在使用u盘的过程中,我们也会遇到各种各样的问题,有时候我们不得已需要将u盘格式

基于PyTorch搭建FasterRCNN实现目标检测

基于PyTorch搭建FasterRCNN实现目标检测1.图像分类vs.目标检测图像分类是一个我们为输入图像分配类标签的问题。例如,给定猫的输入图像,图像分类算法的输出是标签“猫”。在目标检测中,我们不仅对输入图像中存在的对象感兴趣。我们还对它们在输入图像中的位置感兴趣。从这个意义上说,目标检测超越了图像分类。1.1图

热文推荐