一、基本组成:

单片机小系统+4*4矩阵键盘+1602显示+DC电机

基本电路:

键盘和和显示

键盘接P1口,液晶的电源的开、关通过P2.7口控制

电机(控制口P2.4)

小系统就不贴上来了吧。。。

二、基本功能描述:

1.验证密码、修改密码

a)锁的初始密码是123456(密码最长为10位,最短为1位)。

2.恢复初始密码

a)系统可以恢复初始密码,否则一旦忘记密码而又不能恢复初始密码,该锁就永远打不开。但是又不能让用户自行修改密码,否则其他人也可以恢复该初始密码,使得锁的安全性大大下降。

3.使系统进入低功耗状态

a)在实际使用中,锁只有在开门时才被使用。因而在大多数的时间里,应该让锁进入休眠状态、以降低功耗,这使系统进入掉电状态,可以大大降低系统功耗。

b)同时将LCD背光灯关闭

4.DC电机模拟开锁动作。

a)DC电机启动时解除开锁把手的锁定,允许通过把手开锁。DC电机不直接开锁,使得DC电机的功率不用太大,系统的组成和维护将变得简单,功耗也降了下来。

三、密码锁特点说明:

1.0 输入将被以字符形式输入,最长为10位。

超过10位时系统将自动截取前10位、但不作密码长度溢出提示。

2.0 开锁10秒后不允许更改密码、并提示修改超时_进入初始态,需要重新输入密码方可再次修改密码。

3.0 系统未使用存储器存储密码故掉电后密码自动恢复为初始密码。

4.0 若2分钟内无任何操作,系统自动进入省电模式运行,同时关闭液晶显示,以节省电力。

5.0 输入密码正确后、电机允许开锁时间为5秒, 5秒后需要再次输入密码才可以再次开锁。

6.0 修改密码键和恢复初始密码键最好置于室内。

这是Proteus仿真结果:

输入密码123456:

显示结果:

密码正确时电机启动、电机将持续5秒:

这是键盘:

开锁键是接INT0引脚接的一个独立按键,用于唤醒CPU工作、进而开启整个系统

密码正确时可以修改密码:

再次输入新密码,两次输入相同时、更改有效

当然你可以随时放弃修改密码

改进:

1.0 密码锁的秘密没有存储,因而在掉电时最新的密码将丢失,重新上电后密码将恢复成为初始密码。这使得每次换电池或停电后密码都得恢复一次,给使用带来不便,但是为了要存储一个最多只有十几字节的密码就增加一个存储器、似乎不是很值,最好是所选的单片机自带这样的存储器(容量很小、如32B)。当然如果电源来自市电的话,就不会经常掉电了。

2.0 系统的最好再增加电源监测的设计,在电池电力不够时发出提示。这时还可以增加备用电池,这样就可以保证系统不会掉电。但是这些都要依赖于成本。

3.0 液晶的显示最好采用中文。通过对1602的CGRAM的操作可以实现中文显示,使得用户界面更好。

主函数:

确认键操作:

确认函数_ confirm()操作:

0_将 '\0' 置于输入table_input[]结尾

(table_input[]的长度返回值在length里面)

根据操作标识选择任务:

1_确认密码:判定输入密码正确与否

2_修改密码:确认第一次输入并保存

要求第二次输入

比较两次输入是否相同

根据比较结果选择任务:

修改失败,进入输入密码态

修改成功,将输入复制到table_password[]

确认函数_confirm()相关标识位目录:

flag_display;//根据其值可以确定显示信息

flag_confirm;//确认键根据此标识判定任务,默认为0_即为确定密码状态

flag_allow;//允许修改密码标识,在密码比较正确时置1

flag_amend;//第一/二次输入新密码标识

flag_M;//允许电机开锁标识

相关变量

sbit M=P3^6;//电机控制口

flag_confirm;//操作任务标识位

flag_compare;//比较输入与密码|相等时返回1,否则返回0

static flag_amend;//修改密码时的标识

第一次输入前=1,输入后置2

第二次输入前=2,输入后置0

flag_display=0;//确认键操作的返回值根据返回值可以确定显示信息

flag_allow;//允许改密码标识,在密码比较正确时置1,不正确时置0

process_char()函数::_M;//DC电机控制口

process_char()函数::_length;//跟踪记录输入table_input[11]的字符长度( <=10 )

lcd_display()函数中标识位flag_display的值与意义:

=0:不显示|不刷新显示

=1:密码错误

=2:密码正确

=3:请输入新密码

=4:请再次输入新密码

=5:密码修改成功

=6:密码修改失败

=7:显示输入密码状态_The password!

=8:放弃修改密码

=9:已开锁

流图不怎么清晰、不过下一篇就是程序了,可以从程序推出流图。

程序比较多,所以写成了几个文件,同时应用了相当多的标识位来进行信号传递。

我觉得边看程序边画它的流程图会更好地帮助我们读程序。

1.0  main.c文件

#include

#include

#include"mydefine_2.h"

static void delay(unsigned int N)//N ms延时_12MHz/准确性高

{

unsigned int i=0,j=0;

for(i=1;i<=N;i++)

for(j=1;j<=355;j++) ;

}

void clock()

{

key_clock=0;

delay(15);

key_clock=1;

}

void init()

{

key_LCD=0;

init_1602();

TMOD=0x01;

TH0=0x3C;//=(65535-5000)/256

TL0=0xAF;//(65535-5000)%256

EA=1;

ET0=1;

TR0=0;

EA=1;//外部中断0唤醒CPU(空闲方式)

EX0=1;

IT0=1;

command(0x80);

lcd_display(7);

}

void main()

{

init();

while(1)

{

temp=keyboard_matrix();//扫描输入

if(temp)//有按键输入信息

{

clock();//按键声

TR0=0;//关闭计时

timer=0;

receive(temp);//输入的字符串长度为length( <= 10)

if(i!=length)//输入时显示"*"

{

command(0xC0+length);//为显示密码输入设定位置

display('*');

i=length;

}

switch(temp)//根据按键号调用任务

{

//修改密码

case 12: if((flag_allow) && (flag_amend==0))//输入密码正确的条件下可以更改

{

table_input[0]='\0';

flag_display=3;//请输入新密码

flag_confirm=1;//确认键进入确认修改密码功能

flag_amend=1;//每次按下修改键时都是第一次输入新密码

length=0;    //重按修改键时也是第一次输入新密码

i=0;

}

else

{

flag_confirm=0;//恢复初始态

flag_amend=0;

lcd_display(1);//密码不正确

delay(500);

flag_display=7;

length=0;

i=0;

}

break;

case 11: //取消

command(0xC0+length);//擦出显示

display(' ');//显示后光标_显示地址又加了1

command(0xC0+length);//重置光标_显示地址|实为将光标拉回来

i=0;

if(length > 0)

{

length--;//input[]位置后退一位

}

break;

case 10: confirm();//确定

i=0;

break;

case 13: //修改密码的过程中取消修改密码|将系统置于初始态即可

if((flag_amend==1) || (flag_amend==2))

{

flag_amend=0;

flag_confirm=0;

lcd_display(8);

delay(500);

flag_display=7;

length=0;

i=0;

}

break;

}

lcd_display(flag_display);

}

else

{

TR0=1;//开始计时等待

}

DC_Moter();

resume_password();

if(flag_clear)//恢复密码和开锁键_外部中断有效时重新计时

{

flag_clear=0;

timer=0;

}

if(timer==100)//10秒后不允许更改密码

{

flag_allow=0;

flag_amend=0;

flag_confirm=0;

length=0;

i=0;

lcd_display(7);//显示初始态,以提示修改超时

}

if(timer==1200)//≈2分钟后休眠|空闲方式

{

TR0=0;

timer=0;

clear_system();//恢复初始态

i=0;

key_clock=0;

delay(250);

key_clock=1;

PCON|=0x01;

lcd_display(7);//唤醒CPU后显示初始态

}

}

}

void int0() interrupt 0

{

key_LCD=0;//开液晶电源

key_clock=0;

delay(250);

key_clock=1;

flag_clear=1;

}

void Timer0() interrupt 1 //50ms

{

TH0=0x3C;//(65535-50000)/256

TL0=0xAF;//(65535-50000)%256

timer++;

}

2.0  负责实现具体操作的 process_char.c 文件

#include

#include

#include"mydefine.h"

sbit key_self=P2^1;//独立按键,用于恢复初始密码

sbit key_LED=P2^0;

sbit key_M=P2^4;//DC电机控制口

sbit key_LCD=P2^7;//液晶电源控制口

extern bit flag_clear;//恢复密码和开锁键_外部中断的有效标识

extern unsigned int timer;//定时器0计数时段标记_50ms一次定时中断

extern unsigned char length=0;//跟踪记录输入table_input[11]的字符长度( <=10 )

extern unsigned char flag_display=0;//根据其值可以确定显示信息

extern unsigned char flag_confirm=0;//确认键根据此标识判定任务,默认为0_即为确定密码状态

extern unsigned char flag_allow=0;//允许修改密码标识,在密码比较正确时置1

extern unsigned char flag_amend=0;//第一/二次输入新密码标识

unsigned char flag_M=0;//允许电机开锁标识

extern void command(unsigned char command);

extern void display(unsigned char date);

//向I2C地址为address处写入数据date

extern void write_I2C(unsigned char address,unsigned char date);

//读出I2C地址为address处的数据

extern unsigned char read_I2C(unsigned char address);

static void delay(unsigned int N)//N ms延时/准确性高

{

unsigned int i=0,j=0;

for(i=1;i<=N;i++)

for(j=1;j<=355;j++) ;

}

//休眠前清除table_input中的值

extern void clear_system()

{

table_input[0]='\0';//恢复初始态

length=0;

flag_allow=0;

flag_confirm=0;

flag_amend=0;

flag_clear=0;

key_LCD=1;//关液晶电源

}

//接收键盘输入|以字符形式存入table_input[11]

extern void receive(unsigned char temp)

{

//按键在松手时读取按键号,故不会重复读取按键值

if(temp && length<=9)//如此,则无按键时执行效率高

{

switch(temp)

{

case 1:

case 2:

case 3:

case 4:

case 5:

case 6:

case 7:

case 8:

case 9: table_input[length++]=temp+48;//以字符形式存入table_input[11]

break;

case 14: table_input[length++]=48;//字符0

}

}

}

//根据任务选择显示信息

extern void lcd_display(unsigned char temp)

{

unsigned char i=0,*p=NULL;

if(temp)

{

switch(temp)//选择显示信息

{

case 1: p=table_error;//密码不正确

break;

case 2: p=table_pass;//密码正确

break;

case 3: p=table_new;//请输入新密码

break;

case 4: p=table_again;//请再次输入新密码

break;

case 5: p=table_changed;//密码修改成功

break;

case 6: p=table_fail;//密码修改失败

break;

case 7: p=table_enter;//显示输入密码:The password!

break;

case 8: p=table_abandon;//放弃修改密码

break;

case 9: p=table_close;//锁闭

break;

case 10: p=table_resume;//锁闭

break;

}

command(0x01);

delay(1);

command(0x80);

while(*p!='\0')

{

display(*(p++));

}

flag_display=0;//显示后清0,避免重复显示

}

}

//确认

extern void confirm(void)

{

unsigned char flag_compare=0;//用于记录比较输入与密码的结果|相等时返回1,否则返回0

unsigned char flag_compare_2=0;//用于记录对两次输入的新密码的比较结果|相等时返回1,否则返回0

unsigned char i=0;

if(length > 0)//输入不为空

{

table_input[length]='\0';

length=0;//输入字符串长度清0

if(flag_confirm)//修改密码

{

switch(flag_amend)

{

case 1: strcpy(table_newpassword,table_input);//第一次输入新密码

table_input[1]='\0';//避免第一次输入的内容在放弃修改时再次被利用

flag_amend=2;

flag_display=4;//请再次输入密码

break;

case 2: flag_compare_2=strcmp(table_input,table_newpassword);//第二次输入新密码

flag_amend=0;//清0,允许再次修改

flag_confirm=0;//进入初始之确认密码状态

if(!flag_compare_2)//两次输入相同==0

{

strcpy(table_password,table_input);

table_input[1]='\0';//避免修改完成后再次被利用,造成重复修改,同时避免刚修改了就是pass状态

lcd_display(5);//修改成功

delay(500);

flag_display=7;

}

else

{

lcd_display(6);//修改失败

delay(500);

flag_display=7;

}

break;

}

}

else//验证密码

{

flag_compare=strcmp(table_input,table_password);

if(!flag_compare)//密码正确==0

{

flag_allow=1;//允许修改密码

flag_M=1;//允许开锁

flag_display=2;//密码正确信息:Pass!

table_input[1]='\0';//改变输入,使不致出乱

}

else//密码错误

{

flag_allow=0;//不允许修改密码

lcd_display(1);//密码错误信息:Error!

delay(500);

flag_display=7;

}

}

}

}

//电机控制

extern void DC_Moter()

{

if(flag_M)//允许开锁

{

flag_M=0;

key_M=0;//开锁

key_LED=0;

delay(1250);

key_M=1;

key_LED=1;

timer=0;

lcd_display(7);//进入初始态

}

}

//恢复初始密码

extern void resume_password()

{

if(!key_self)//==0

{

delay(3);

if(!key_self)//==0

{

while(!key_self) ;//==0

strcpy(table_password,table_original);

flag_clear=1;

lcd_display(10);

delay(500);

lcd_display(7);

}

}

}

确认函数_ confirm()操作:

0_将 '\0' 置于输入table_input[]结尾

(table_input[]的长度返回值在length里面)

根据操作标识选择任务:

1_确认密码:判定输入密码正确与否

2_修改密码:确认第一次输入并保存

要求第二次输入

比较两次输入是否相同

根据比较结果选择任务:

修改失败,进入输入密码态

修改成功,将输入复制到table_password[]

确认函数_confirm()相关标识位目录:

flag_display;//根据其值可以确定显示信息

flag_confirm;//确认键根据此标识判定任务,默认为0_即为确定密码状态

flag_allow;//允许修改密码标识,在密码比较正确时置1

flag_amend;//第一/二次输入新密码标识

flag_M;//允许电机开锁标识

相关变量

sbit M=P3^6;//电机控制口

flag_confirm;//操作任务标识位

flag_compare;//比较输入与密码|相等时返回1,否则返回0

static flag_amend;//修改密码时的标识

第一次输入前=1,输入后置2

第二次输入前=2,输入后置0

flag_display=0;//确认键操作的返回值根据返回值可以确定显示信息

flag_allow;//允许改密码标识,在密码比较正确时置1,不正确时置0

process_char()函数::_M;//DC电机控制口

process_char()函数::_length;//跟踪记录输入table_input[11]的字符长度( <=10 )

lcd_display()函数中标识位flag_display的值与意义:

=0:不显示|不刷新显示

=1:密码错误

=2:密码正确

=3:请输入新密码

=4:请再次输入新密码

=5:密码修改成功

=6:密码修改失败

=7:显示输入密码状态_The password!

=8:放弃修改密码

=9:已开锁

3.0  定义各个数组的头文件mydefine.h

extern unsigned char table_input[11]={0};  //接收键盘输入

unsigned char table_password[11]="123456";  //密文

unsigned char table_newpassword[11]="456";  //接收新密码

unsigned char code table_original[11]="123456"; //初始密码

//显示信息

unsigned char code table_pass[]="Pass!";  //成功进入

unsigned char code table_error[]="Operate Error!";  //密码错误信息

unsigned char code table_enter[]="The password:";  //输入密码

unsigned char code table_new[]="New password:";  //输入新密码

unsigned char code table_again[]="Enter again:";  //再次输入新密码

unsigned char code table_changed[]="Changed!";  //密码修改成功

unsigned char code table_fail[]="Fail changce!";  //密码修改失败

unsigned char code table_abandon[]="Abandon changce!";//放弃修改密码

unsigned char code table_close[]="Locked!";//锁闭

unsigned char code table_resume[]="Resumed!";//恢复初始密码

4.0  头文件mydefine_2.h

定义了各个外部文件向主函数用到的操作函数和外部变量

#ifndef _mydefine_2_h_

#define _mydefine_2_h_

sbit key_LED=P2^0;

sbit key_clock=P3^3;//蜂鸣器

sbit key_LCD=P2^7;//液晶电源控制口

extern bit flag_clear=0;//恢复密码和开锁键_外部中断的有效标识

extern unsigned int timer=0;//定时器0计数时段标记_50ms一次定时中断

static unsigned char i=0;//显示*用变量

unsigned char temp=0;//用于接收键盘输入(按键在松手时读取按键号)

extern unsigned int table_input[11];//接收输入

extern unsigned char flag_allow;//允许改密码标识,在密码比较正确时置1

extern unsigned char flag_confirm;//确认键根据此标识判定任务,默认为0_即为确定密码状态

extern unsigned char flag_display;//确认键操作的返回值,根据返回值可以确定显示信息

extern unsigned char flag_amend;//第一/二次输入新密码标识

extern unsigned char length;//输入input的字符长度(length <= 16)

//1602液晶:extern_1602.c *****************************************************************

extern void init_1602();

extern void command(unsigned char command);

extern void display(unsigned char date);

//键盘:extern_keyboard_no_T0_2.c *********************************************************

//矩阵键盘.无按键动作时其返回值num_key=0,否则返回按键号num_key

extern unsigned char keyboard_matrix();//(在松手时读取按键号****检测高四位)

//密码处理:process_char.c ****************************************************************

//电机控制

extern void DC_Moter();

//接收键盘输入|以bit形式存入input__返回值为输入的字符串长度length(length <= 10)

extern void receive(unsigned char temp);//涉及文件间变量length

//确认按键操作

extern void confirm(void);//涉及跨文件调用的变量flag_confirm,flag_allow,flag_amend

//根据任务选择显示信息

extern void lcd_display(unsigned char flag_display);//涉及跨文件调用的变量flag_display

extern void clear_system();//恢复初始态

extern void resume_password();//恢复初始密码

//****************************************************************************************

#endif

键盘和1602显示的程序见其他文章。

c语言编写单片机密码锁程序,51单片机密码锁制作的程序和流程图(很详细)相关推荐

  1. 用c语言编写热敏电阻温度计,基于51单片机的热敏电阻温度计的设计.doc

    摘 要 随着科学技术的不断进步与发展,热敏电阻温度计已开始逐渐替代传统的玻璃水银体温计.温度控制系统在国内各行各业的应用虽然已经十分广泛,传统的温度控制方式,主要缺点是温度波动范围大,不能满足高精度, ...

  2. 51单片机c语言编写计算器仿真,基于51单片机的计算器设计c程序代码加proteus仿真...

    可实现加减乘除各类运算,带有清零复位功能 仿真原理图如下(proteus仿真工程文件可到本帖附件中下载) 0.png (24.71 KB, 下载次数: 9) 2019-1-10 04:05 上传 程序 ...

  3. c语言单片机定时器的应用程序,51单片机定时器中断程序(C语言)

    51c程序 51单片机定时器中断程序(C语言) 用C语言实现的,先要定义好定时器的初值 不管你使用多大的晶振,使用51单片机,一般都是12分频出来,也就可以得出一个机器周期 机器周期=12/n(n指晶 ...

  4. 8255A红绿灯c语言程序,51单片机外接8255A做成的交通灯程序及PROTEUS仿真结果(附对应C语言程序).doc...

    51单片机外接8255A做成的交通灯程序及PROTEUS仿真结果(附对应C语言程序) 51单片机外接8255A做成的交通灯程序及PROTEUS仿真结果(附对应C语言程序)2010-04-21 22:0 ...

  5. c51c语言编程的音乐程序,51单片机唱歌C51音乐程序.doc

    51单片机唱歌C51音乐程序 51单片机唱歌 C51音乐程序 unsigned char n 0; //n为节拍常数变量 unsigned char code music_tab[] 0x18, 0x ...

  6. 单片机位寻址举例_单片机学习:51单片机寻址方式详解

    51单片机是对所有兼容Intel 8031指令系统的单片机的统称.该系列单片机的始祖是Intel 8031单片机,后来随着Flash rom 技术的发展,8031单片机取得了长足的发展,成为了应用最广 ...

  7. C51汇编语言寻址方式,单片机学习:51单片机寻址方式详解

    原标题:单片机学习:51单片机寻址方式详解 51单片机是对所有兼容Intel 8031指令系统的单片机的统称.该系列单片机的始祖是Intel 8031单片机,后来随着Flash rom 技术的发展,8 ...

  8. 从51单片机白痴到51单片机高手的快速成长

    从51单片机白痴到51单片机高手的快速成长 推荐一个不错的51单片机学习视频教程(高清晰版本)电驴下载   也可以用迅雷下载 飞龙教程------51单片机 需要更多单片信息请与我联系 飞龙QQ:90 ...

  9. 单片机 中断秒表 c语言程序,51单片机c语言的秒表设计.doc

    51单片机c语言的秒表设计.doc 课程设计报告 基于AT89C51单片机的秒表设计 院 系 电子信息工程学院 专 业 电子信息工程 1 姓 名 摘 要 本设计是设计一个单片机控制的多功能秒表系统. ...

  10. 单片机学习笔记————51单片机实现在数码管中实现iphone4S开机密码锁的程序

    一.使用proteus绘制简单的电路图,用于后续仿真 二.编写程序 /***************************************************************** ...

最新文章

  1. 扩增子项目动辄几百上千样品,如何写好实验设计——样品和组命名规则
  2. Altium Designer快捷键失效恢复方法
  3. Dubbo监控中心Windows安装
  4. 浮动导航栏php源码,JQuery 浮动导航栏实现代码
  5. 装机人员工具_海鲜真空贴体包装机你了解的多吗
  6. DataGridView控件
  7. AFNetWorking 对汉字部分UTF-8编码
  8. 字符动图_图解redis五种数据结构底层实现(动图哦)
  9. sublime press key “escape” can't type anything
  10. 红米7android9miui11,红米Note7Pro MIUI11安卓9 解账户锁 可登小米账号 永不反锁 完美ROOT 解锁包...
  11. linux终端安装搜狗输入法rpm,Linux下deb包安装工具(附带安装搜狗输入法)
  12. 第六周作业1——利用哈夫曼编码英文字母表
  13. OracleEBSAPP-XLA-95103错误(EventIDcannothaveaNULLvalue.)
  14. ubutun 滑动 触控板_Ubuntu下触控板手势调节软件xSwipe
  15. mysql 查看校对集_mysql 查看字符集和校对规则
  16. win10-2016企业版长期服务版激活
  17. arduino智能浇花系统_基于Arduino的远程自动浇花系统设计
  18. 栈(简单介绍及其应用)
  19. 【转】HTML5斯诺克桌球俱乐部【译】
  20. 管理用户账号和组账号

热门文章

  1. java idle 机制_Flink中Idle停滞流机制(源码分析)
  2. qcloud php开发,GitHub - QcloudApi/qcloudapi-sdk-php
  3. (GIS可视化)热力图
  4. TP5序列化和反序列化报错!缓存溢出
  5. 七夕送你最特别的礼物 限时竞拍咯~
  6. (很详细的)数据库Transact-SQL语句:数据查询(基本查询、嵌套查询、连接查询)
  7. RPC框架pigeon源码分析
  8. CSS实现导航条图片的翻转菜单
  9. IBDP1 经济好学吗?学习建议分享
  10. 计算机时区找不到北京,emwin7时区/em 怎么没有北京时间了-win7时区,win7系统怎么添加北京时区...