门禁电子密码锁说明书
更新时间:2023-12-13 20:54:01 阅读量: 教育文库 文档下载
《微机原理及接口技术》
课程设计说明书
课题:门禁电子密码锁 专业:通信工程 班级:**** 姓名:****** 学号: 指导老师:
1
目录
一、设计任务 ............................................................................................................................ 3 1、设计题目 .......................................................................................................................... 3 2、设计目的 .......................................................................................................................... 3 3、设计任务 .......................................................................................................................... 3 4、设计基本要求 .................................................................................................................. 3 二、总体方案设计与论证 ........................................................................................................ 4 1、总体方案设计 .................................................................................................................. 4 2、按键消抖方案设计与论证 .............................................................................................. 4 3、按键检测方案设计与论证 .............................................................................................. 5 4、数码管显示方案设计 ...................................................................................................... 5 三、总框图及总体软件设计说明 ............................................................................................ 5 1、系统总框图 ...................................................................................................................... 5 2、硬件模块功能说明 .......................................................................................................... 5 3、软件设计说明 .................................................................................................................. 6 四、局部程序设计说明 ............................................................................................................ 7 1、按键检测程序 .................................................................................................................. 7 2、拆字程序 .......................................................................................................................... 8 3、显示程序 ........................................................................................................................ 10 4、核对密码程序 ................................................................................................................ 11 5、中断服务程序 ................................................................................................................ 14 五、系统资源分配 .................................................................................................................. 15 六、系统功能与操作说明 ...................................................................................................... 16 七、调试记录及调试结果 ...................................................................................................... 17 八、课程设计总结 .................................................................................................................. 17 附录 .......................................................................................................................................... 18
2
一、 设计任务
1、 设计题目:门禁电子密码锁 2、 设计目的:通过小型微机应用产品的设计与调试过程,运用《微机原理
及接口技术》课程所学的基本知识,在设计中加以应用,进而得到理解、巩固和提高发展,通过实践的过程学习掌握分析与解决实际问题的方法与手段,提高设计、编程与调试的实际动手能力,作为工程技术工作的一次基本训练。 3、 设计任务:设计一个以单片机为核心的门禁密码锁。具有密码开锁,不
同权限的密码修改、密码输入安全设置、开门时段管理等功能。编程并在单片机实验板上模拟调试实现。
4、设计基本要求:
1、开机进行接口部件及数码显示器、指示灯、讯响器等自检。 2、密码分为管理员密码和用户密码:管理员密码为8位0~9的数字,而用户密码为6位0~9的数字。
3、设置“0”~“9”的数字键及“ESC”和“ENT”等功能键。对按键输入信号须进行软件消抖处理。 4、工作模式:
(1)常态:数码管显示时钟。
(2)开锁模式:需输入6位数字为0~9的密码进行开锁。密码数字可以由管理员事先设置保存共普通用户使用。
(3)管理员操作模式:需输入8位0~9的密码,可以进行修改用户密码、修改管理员密码、修改进门时段等功能。
5、常态下,八位LED 7段数码管显示时钟信息可包括小时、分钟、秒钟。 6、只要按下0~9的数字键则转入开锁状态,每按一个数字键使数码管从左到右逐次显示“—”。
7、如果输入的密码为6位则和用户密码进行匹配,匹配一致则开锁,如果输入的密码为8位则和管理员密码进行匹配,匹配一致则进入管理员操作模式。
8、在密码输入状态下,输入满6位或8位密码数据后,按“ENT”键才能进行密码匹配,如果没满6位或8位数字密码,按“ENT”则不作响应。 9、输入的用户密码如果匹配则相应指示灯亮并且电动开门电磁铁线圈通电1S开门后返回常态;如果输入不正确,则提示“E”,3S后返回常态,等待下一轮的密码输入。
3
10、开锁模式下可以按“ESC”键取消开锁模式返回常态。
11、管理员操作模式下,管理员可以选择功能,01功能代表设置用户密码、02功能代表重置管理员密码、03功能代表设置进门时间、04功能设置实时钟。利用ESC键返回常态。
12、管理员操作模式下,01功能可以设置用户密码,输入新密码时需要进行确认。
功能扩展提示:(选做)
1、管理员操作模式下,02功能重置管理员密码;
2、管理员操作模式下,03功能可以设置进门的开始时间和结束时间。只有在进门时间段输入用户密码才能开锁。如果开始时间和结束时间均设置为00:00,则为全天可以按密码开门;
3、管理员操作模式下,04功能实时钟的设置,利用数字3和数字4按键实现对时和分钟的调校,按键操作时实现快调功能;
4、如果在开锁模式下12S后没有按键操作则进入常态;
5、如果在开锁状态下用户密码输入十次均错误则报警锁键15分钟; 6、其他功能扩展。
二、 总体方案设计与论证
1、总体方案设计:
以微处理器AT90C51为核心,利用P0,P1和P2.4、P2.5、P2.6、P2.7这些I/O口实现数据的传送;利用I2C总线通信协议和24C02芯片进行密码的核对和修改;4×4矩阵键盘用于密码的输入与修改以及时钟值的修改;数码管用于显示时间和密码输入和修改状态;密码输入正确后通过P2.4口控制继电器工作打开门;P1口用与读入按键状态来判断是否有按键按下然后执行相应的按键功能;P0口控制数码管的段码输出,P2.5,P2.6,P2.7连接到74ls138译码器来控制数码管的位选码输出。
2、按键消抖方案设计与论证: 2.1、软件延时消抖法
软件延时消抖通过调用延时子程序来判断按键是否是抖动,若是抖动,则延时后按键状态和无按键按下时状态一样,若不是抖动,则按键状态和无按键按下时状态不一样,确定为按键按下。 2.2、滚动滤波法消抖
滚动滤波法通过采集按键最近的5次状态来判断是否有抖动,用5个连续的存数单元分别存按键最近的5次状态,再用2个单元来存放稳定时的状态值,每次扫描按键时把上一次的状态值都存入后一个单元,然后把当前按键的状态值存入第一个单元,这样依次进行下去,若不是抖动,则5个单元的值都相等,若是抖动,则5个单元的值不全相等;之后把5个单元相等时的值存
4
入其中一个稳定状态存储单元,另一个则是存上一次的稳定值,当上一次稳定值是无按键按下时的值,当前稳定值不等于无按键按下时的值时,则判定为按键按下。
软件延时会有一个等待按键释放的过程,因此按下按键数码管会灭一小段时间,结果不太理想,但滚动滤波法只判断按键按下的那个状态(下降沿),因此不会出现数码管灭的情况,因此采用滚动滤波法。
3、按键扫描方案设计与论证: 3.1、逐行(列)扫描法
逐行扫描法把行(列)线其中一位置为0,然后观察列(行)线电平变化,若为0了,则把行首值+列值得到键值确定哪颗按键按下,若没变化在把后一行(列)线置为0,依次扫描过去。 3.2、线反转法
线反转法先把行线设为输入,列线设为输出且输出0,然后读取行线的状态值暂存寄存器,然后行列线互换,列先设为输入,行线设为输出,读取列线的值之后和之前行线的值相或得到每个键的状态值,查表找出哪颗键被按下即可。
逐行(列)扫描法比较麻烦,因此采用线反转法。
4、数码管显示方案设计:
数码管显示数字时是把每个数字的段码送到数码管段选口,然后选通数码管位选码,则数码管就显示对应的数字,每个数字的段码采用查表的方式查找,把每个数字的段码都写在一个数组,通过数组下标查找到对应段码送出去显示。输入密码时数码管要显示输入的状态‘-’,采用一个数组存储‘-’,初始数组内容全0,数码管全灭,每输入一个密码,该数组对应位置就存入‘-’的段码,然后通过缓冲单元输出到数码管。
三、 总框图及总体软件设计说明
1、 系统总框图: 键盘
图1
继电器 单片机 24C02 数码管 2、硬件模块功能说明
键盘模块:键盘共16个按键,10个是0~9数字键,1个返回键(ESC),1个确认件(ENT),1个设置用户密码键,1个设置管理员密码键,1个调整时钟
5
键。当数字键是输入对应的0~9数字的,返回键是取消所有调整返回到常态显示时间的,确认键是对用户或管理员的操作进行确认的,管理员模式下修改密码按键才有效,调时钟按键按下则暂停时钟走时进行时间修改。
按键的分配如图: 注:
1 2 3 U U:设置用户密码;
A:设置管理员密码; ESC:返回;
A 5 6 4 ENT:确认;
无 9 8 7 调时 0 ENT ESC 图2
数码管模块:常态下显示时间值,开锁模式下显示输入的密码状态,以‘-’来显示,管理员模式下全部显示’-’,调整时间时显示所调整的时间值。
继电器模块:当用户密码输入正确时由单片机发出指令让继电器工作打开门。 24C02模块:保存用户密码和管理员密码,与单片机通过I2C总线协议进行通信,I2C通信只有一根数据线SDA和一根时钟线SCL,通信前由单片机发出一个起始信号,之后在时钟线SCL高电平期间把数据线SDA上的数据发送给24C02,在时钟线高电平期间数据先上的数据必须保持,SCL为低电平是SDA上的数据才能发生改变,当发送完一个字节后从器件24C02会向单片机发送一个应答信号,单片机接收到应答信号后可以发出终止信号终止通信。
3、软件设计说明 主程序:
主程序是整个程序的主体,可以对各个子程序进行调用,协调各个子程序之间的联系,控制着整个系统的工作流程。系统上电后进入主程序,先对系统各个模块自检,后对系统初始化,之后就循环进行主流程工作。 主程序流程图: 拆字
开始 开机自检 初始化 按键检测 6
控制工作
图3
显示 核对密码 四、 局部程序设计说明
1、 按键检测程序 代码如下: void sm_key() {
int i=0,j; uchar a,b,c,k; key=0x0f; lb[4]=lb[3]; lb[3]=lb[2]; lb[2]=lb[1]; lb[1]=lb[0]; lb[0]=key; //滚动滤波存储 for(j=0;j<4;j++) { if(lb[j]!=lb[j+1]) //还要有两个单元不相等则退出函数 return; k=lb[j+1]; } pd[1]=pd[0]; pd[0]=k; //稳定状态的值存入pd[1]和pd[0] if((pd[1]==0x0f)&&(pd[0]!=0x0f)) //pd[1]是0x0f,pd[0]不是0x0f则按下 { key=0x0f; a=key&0x0f; key=0xf0; b=key&0xf0; c=a|b;//线反转后键状态值存入c while(c!=key_code[i]) i++; //查找第几个按键按下 keyvalue=i; if(y==0) {
seg=sdm[keyvalue]; //按键对应段码送出显示 x++;//记录按键按下次数 return; }
switch(keyvalue)//执行相应按键功能 {
case(0):k0(); break; case(1):k1(); break; case(2):k2(); break;
7
case(3):k3(); break; case(4):k4(); break; case(5):k5(); break; case(6):k6(); break; case(7):k7(); break; case(8):k8(); break; case(9):k9(); break; case(10):k10(); break; //case(11):k11(); break; case(12):k12(); break; case(13):k13(); break; case(14):k14(); break; case(15):k15(); break; } } }
程序开始先进行滚动存储,lb[5]这个数组用来存储最近5次按键状态值的,接着判断这5个单元内容是否相等,如果不等则退出该函数,相等则接着判断是否是按下,若pd[1]为0x0f且pd[0]不为0x0f则是按键按下,然后查表找到与当前按下的键状态值相等的位置,记录得到键值,执行对应键功能。 程序流程如图:
开始
否
按键是否按下 是 查找按键
返回
图4
2、 拆字程序 代码如下: void cz() {
if(y==1&&(ms==0||ms==4)) //常态和继电器工作下拆时间单元
8
执行键功能
{
seg_disp[0]=sdm[clk_value[0]/10]; seg_disp[1]=sdm[clk_value[0]]; seg_disp[2]=0x40;
seg_disp[3]=sdm[clk_value[1]/10]; seg_disp[4]=sdm[clk_value[1]]; seg_disp[5]=0x40;
seg_disp[6]=sdm[clk_value[2]/10]; seg_disp[7]=sdm[clk_value[2]]; }
if(y==2||y==3) //开锁模式和管理员模式把jm_disp[8]的内容给缓冲单元 {
seg_disp[0]=jm_disp[0]; seg_disp[1]=jm_disp[1]; seg_disp[2]=jm_disp[2]; seg_disp[3]=jm_disp[3]; seg_disp[4]=jm_disp[4]; seg_disp[5]=jm_disp[5]; seg_disp[6]=jm_disp[6]; seg_disp[7]=jm_disp[7]; } }
拆字程序在常态不做任何调整下和打开门时把时间值存储数组里面的内容拆到数码管显示缓冲单元里面暂存,当处于开锁模式或管理员模式下则把jm_disp[8]数组里面的内容一一对应赋给数码管显示缓冲单元,开锁模式下,每输入一个密码,jm_disp[8]单元里面就回存一个‘-’的段码,在界面上显示出密码输入的位数,管理员模式下,jm_disp[8]里面全部存一个相同的段码,让数码管显示当前是管理员操作界面。 程序流程如图: 否 是 否 是
开始 y=1? Y=2或y=3? 时间拆字 界面显示拆字 返回 9
图5
3、 显示程序 代码如下: void disp() {
int i; for(i=0;i<8;i++) //8个数码管逐个点亮 { switch(i) //送出位选码 { case(0):LSA=0; LSB=0; LSC=0; break; case(1):LSA=1; LSB=0; LSC=0; break; case(2):LSA=0; LSB=1; LSC=0; break; case(3):LSA=1; LSB=1; LSC=0; break; case(4):LSA=0; LSB=0; LSC=1; break; case(5):LSA=1; LSB=0; LSC=1; break; case(6):LSA=0; LSB=1; LSC=1; break; case(7):LSA=1; LSB=1; LSC=1; break; } if(y==0) { seg=0xff;//刚启动时数码管段码全1逐个检测数码管 Delay1ms(500); //亮0.5秒 } else { seg=seg_disp[i]; //数码管显示缓冲单元的段码点亮数码管 Delay1ms(1); } seg=0x00; //消除窜显 } }
刚启动系统时,显示程序逐个检测数码管,把数码管8段全部点亮,自检完成后,显示程序把数码管显示缓冲单元里的内容送出到数码管段码口点亮数码管,使之显示相应的数据,该程序里是8个数码管逐个点亮过去,每显示完一个数码管都会灭掉数码管,等下一次循环在点亮下一个数码管,目的是为了消除数码管之间的窜扰显示。 程序流程如图:
10
开始
送位控码
刚启动? 否 是
送全1段码 送正常段码
缓冲区地址加1
用for循环通过变量是
i来判断
是否到最高位
否 是
返回
图6
4、 核对密码程序 代码如下: void open_lock() {
uint i,i1; uchar j;
if((y==2&&w==1)&&v<8) {
mima[v]=keyvalue; //开锁模式下把输入的密码逐个存入输入缓冲单元 jm_disp[v]=0x40;//界面显示‘-’ w=0; v=v+1; //指向下一位数码管 }
if((ent==1)&&((lock==6)||(lock==8)))//进行密码的核对 {
for(i=0;i 11 { j=0x00; tmima[i]=At24c02Read(j); //从24C02读取用户密码存入读取缓冲单 //元 } else { j=0x06; tmima[i]=At24c02Read(j); //从24C02读取管理员密码存入读取缓冲 //单元 } j=j+1; } for(i=0;i 12 mima[i]=0x00; } } lock=0; } ent=0;//密码没输完,确认标志重新清零 } 程序流程如图: 否 是 否 密码存入缓冲单元 是 否 错误提示 是 否 是 开始 密码输入完成? 是用户密码? 读取正确用户密码 读取正确管理员密码 核对用户密码 核对管理员密码 密码正确? 继电器工作(开门) 错误提示 密码正确? 进入管理员模式 返回 13 图7 核对密码程序先判断密码是否输入完成,用户密码6位,管理员密码8位,若输入完成则判断是用户密码还是管理员密码,然后从24C02读取所存的正确密码进行核对,若密码是6位则进行用户密码的核对,若是8位则进行管理员密码的核对,用户密码正确则继电器工作开门,管理员密码正确则进入管理员模式,管理员模式下可进行用户密码和管理员密码的修改,若密码输入错误则数码管提示错误信息‘E’,3s后返回常态。 5、 中断服务程序 代码如下: void time0() interrupt 1 { n1=n1-1; if(n1==0) //是否满1s? { n1=16; //n1重装初值 clk_value[2]=clk_value[2]+1; //秒单元加1 if(y==2) //开锁模式下长时间不输密码则开始计数 count=count+1; if(clk_value[2]==60) //满1分? { clk_value[2]=0; //秒单元清零 clk_value[1]=clk_value[1]+1; //分单元加1 if(clk_value[1]==60) //满1小时? { clk_value[1]=0; //分单元清零 clk_value[0]=clk_value[0]+1; //时单元加1 if(clk_value[0]==24) //满一天? { clk_value[0]=0; //时单元清零 } } } } } T0计数中断一次时间还达不到1s,通过n1变量循环控制达到1s后再执行中断服务程序,秒单元加1,满60s后分单元又加1,满60小时时单元加1,满24小时时单元清零。 程序流程如图: 开始 14 否 是 否 是 否 否 图8 五、 系统资源分配 表1: 硬件资源分配 名称 P0口 P1口 P2.4口 P2.5、P2.6、P2.7口 P2.0口 P2.1口 表2: 满1秒? 秒单元加1 满1分? 分单元加1 满1小时? 是 时单元加1 满1天? 是 时单元清零 返回 功能 数码管段码控制 键盘接口 驱动继电器 138译码器输入端,输出端控制数码管位选 I2C通信24C02时钟线(SCL) I2C通信24C02数据线(SDA) 15 seg_disp[5]=jm_disp[5]; seg_disp[6]=jm_disp[6]; seg_disp[7]=jm_disp[7]; } } /**************** 控制函数 ****************/ void control() { if(count==6) //6秒内没继续输入密码,返回常态 { int i; y=1; v=0; lock=0; for(i=0;i<8;i++) { jm_disp[i]=0x00; mima[i]=0x00; } } if(ms==4) n2=n2-1; //控制继电器工作1s if(n2==0) { OP=1; n2=50; ms=0; //关闭继电器 } } /****************** 1毫秒延时函数 ********************/ void Delay1ms(int c) { unsigned char a, b; for (;c>0;c--) { for (b=38;b>0;b--) { for (a=13;a>0;a--); } } } /******************* 开机自检函数 *******************/ void check() { c_led(); //自检led disp(); //自检数码管 while(x<16) { 21 } sm_key(); //按键检测 } Delay1ms(500); seg=0x00; OP=0; //自检继电器 Delay1ms(500); OP=1; y=1; //自检完成,进入常态 /**************** 开机自检led子函数 ******************/ void c_led() { unsigned char b; int bb=0; b=0x01; while(bb<8) //逐个移动点亮led { P0=b; Delay1ms(500); b=b<<1; bb++; } } /**************** 按键检测函数 *****************/ void sm_key() { int i=0,j; uchar a,b,c,k; key=0x0f; lb[4]=lb[3]; lb[3]=lb[2]; lb[2]=lb[1]; lb[1]=lb[0]; lb[0]=key; //滚动滤波存储 for(j=0;j<4;j++) { if(lb[j]!=lb[j+1]) return; //5次值不等,退出函数 k=lb[j+1]; //相等,当前稳定值暂存k } pd[1]=pd[0]; //前一次稳定值存入pd[1] pd[0]=k; 当前稳定值存入pd[0] if((pd[1]==0x0f)&&(pd[0]!=0x0f)) //pd[1]为0x0f且pd[0]不为0x0f则按键按下 { 22 key=0x0f; a=key&0x0f; key=0xf0; b=key&0xf0; c=a|b; //线反转后得到按键状态值 while(c!=key_code[i]) i++; //查找第几个按键按下 keyvalue=i; //得到键值 if(y==0) //刚启动模式下检测键盘 { seg=sdm[keyvalue]; x++; return; } switch(keyvalue) //查找按键功能 { case(0):k0(); break; case(1):k1(); break; case(2):k2(); break; case(3):k3(); break; case(4):k4(); break; case(5):k5(); break; case(6):k6(); break; case(7):k7(); break; case(8):k8(); break; case(9):k9(); break; case(10):k10(); break; //case(11):k11(); break; case(12):k12(); break; case(13):k13(); break; case(14):k14(); break; case(15):k15(); break; } } } /**************** k0按键功能函数 ******************/ void k0() { if((ms==2&&y==3)&&v<6) { mima[v]=0x01; jm_disp[v]=0x40; v=v+1; } if((ms==3&&y==3)&&v<8) { mima[v]=0x01; 23 jm_disp[v]=0x40; v=v+1; } if((y==1||y==2)&&(ms==0&&lock<8)) { y=2; w=1; keyvalue=keyvalue+1; lock=lock+1; count=0; } if((ms==1&&y==1)&&v<8) { keyvalue=keyvalue+1; seg_disp[v]=sdm[keyvalue]; if(v==1||v==4) v=v+2; else v=v+1; } } /**************** k1按键功能函数 ******************/ void k1() { if((ms==2&&y==3)&&v<6) { mima[v]=0x02; jm_disp[v]=0x40; v=v+1; } if((ms==3&&y==3)&&v<8) { mima[v]=0x02; jm_disp[v]=0x40; v=v+1; } if((y==1||y==2)&&(ms==0&&lock<8)) { y=2; w=1; keyvalue=keyvalue+1; lock=lock+1; count=0; } if((ms==1&&y==1)&&v<8) { keyvalue=keyvalue+1; seg_disp[v]=sdm[keyvalue]; 24 if(v==1||v==4) v=v+2; else v=v+1; } } /**************** k2按键功能函数 ******************/ void k2() { if((ms==2&&y==3)&&v<6) { mima[v]=0x03; jm_disp[v]=0x40; v=v+1; } if((ms==3&&y==3)&&v<8) { mima[v]=0x03; jm_disp[v]=0x40; v=v+1; } if((y==1||y==2)&&(ms==0&&lock<8)) { y=2; w=1; keyvalue=keyvalue+1; lock=lock+1; count=0; } if((ms==1&&y==1)&&v<8) { if(v==0) return; keyvalue=keyvalue+1; seg_disp[v]=sdm[keyvalue]; if(v==1||v==4) v=v+2; else v=v+1; } } /**************** k3按键功能函数 ******************/ void k3() //修改用户密码按键 { if(y==3&&ms!=3) //管理员模式下修改用户密码 ms=2; 25 } /**************** k4按键功能函数 ******************/ void k4() { if((ms==2&&y==3)&&v<6) { mima[v]=0x04; jm_disp[v]=0x40; v=v+1; } if((ms==3&&y==3)&&v<8) { mima[v]=0x04; jm_disp[v]=0x40; v=v+1; } if((y==1||y==2)&&(ms==0&&lock<8)) { y=2; w=1; lock=lock+1; count=0; } if((ms==1&&y==1)&&v<8) { if((seg_disp[0]!=sdm[2]&&v==1)||v>1) { seg_disp[v]=sdm[keyvalue]; if(v==1||v==4) v=v+2; else v=v+1; } } } /**************** k5按键功能函数 ******************/ void k5() { if((ms==2&&y==3)&&v<6) { mima[v]=0x05; jm_disp[v]=0x40; v=v+1; } if((ms==3&&y==3)&&v<8) 26 { mima[v]=0x01; jm_disp[v]=0x40; v=v+1; } if((y==1||y==2)&&(ms==0&&lock<8)) { y=2; w=1; lock=lock+1; count=0; } if((ms==1&&y==1)&&v<8) { if(v>=3||(v==1&&seg_disp[0]!=sdm[2])) { seg_disp[v]=sdm[keyvalue]; if(v==1||v==4) v=v+2; else v=v+1; } } } /**************** k6按键功能函数 ******************/ void k6() { if((ms==2&&y==3)&&v<6) { mima[v]=0x06; jm_disp[v]=0x40; v=v+1; } if((ms==3&&y==3)&&v<8) { mima[v]=0x01; jm_disp[v]=0x40; v=v+1; } if((y==1||y==2)&&(ms==0&&lock<8)) { y=2; w=1; lock=lock+1; count=0; } if((ms==1&&y==1)&&v<8) { 27 if((v==4||v==7)||(v==1&&seg_disp[0]!=sdm[2])) { seg_disp[v]=sdm[keyvalue]; if(v==1||v==4) v=v+2; else v=v+1; } } } /**************** k7按键功能函数 ******************/ void k7() //修改管理员密码按键 { if(y==3&&ms!=2) ms=3; } //管理员模式下修改管理员密码 /**************** k8按键功能函数 ******************/ void k8() { if((ms==2&&y==3)&&v<6) { mima[v]=0x07; jm_disp[v]=0x40; v=v+1; } if((ms==3&&y==3)&&v<8) { mima[v]=0x07; jm_disp[v]=0x40; v=v+1; } if((y==1||y==2)&&(ms==0&&lock<8)) { y=2; w=1; keyvalue=keyvalue-1; lock=lock+1; count=0; } if((ms==1&&y==1)&&v<8) { if((v==4||v==7)||(v==1&&seg_disp[0]!=sdm[2])) { keyvalue=keyvalue-1; seg_disp[v]=sdm[keyvalue]; if(v==1||v==4) 28 v=v+2; else v=v+1; } } } /**************** k9按键功能函数 ******************/ void k9() { if((ms==2&&y==3)&&v<6) { mima[v]=0x08; jm_disp[v]=0x40; v=v+1; } if((ms==3&&y==3)&&v<8) { mima[v]=0x08; jm_disp[v]=0x40; v=v+1; } if((y==1||y==2)&&(ms==0&&lock<8)) { y=2; w=1; keyvalue=keyvalue-1; lock=lock+1; count=0; } if((ms==1&&y==1)&&v<8) { if((v==4||v==7)||(v==1&&seg_disp[0]!=sdm[2])) { keyvalue=keyvalue-1; seg_disp[v]=sdm[keyvalue]; if(v==1||v==4) v=v+2; else v=v+1; } } } /**************** k10按键功能函数 ******************/ void k10() { if((ms==2&&y==3)&&v<6) 29 { mima[v]=0x09; jm_disp[v]=0x40; v=v+1; } if((ms==3&&y==3)&&v<8) { mima[v]=0x09; jm_disp[v]=0x40; v=v+1; } if((y==1||y==2)&&(ms==0&&lock<8)) { y=2; w=1; keyvalue=keyvalue-1; lock=lock+1; count=0; } if((ms==1&&y==1)&&v<8) { if((v==4||v==7)||(v==1&&seg_disp[0]!=sdm[2])) { keyvalue=keyvalue-1; seg_disp[v]=sdm[keyvalue]; if(v==1||v==4) v=v+2; else v=v+1; } } } /**************** k11按键功能函数 ******************/ /*void k11() { }*/ /**************** k12按键功能函数 ******************/ void k12() //返回按键 { int i; lock=0; v=0; y=1; if(ms==1) { ms=0; TR0=1; } else 30 ms=0; for(i=0;i<8;i++) { jm_disp[i]=0x00; mima[i]=0x00; } } /**************** k13按键功能函数 ******************/ void k13() { if((ms==2&&y==3)&&v<6) { mima[v]=0x00; jm_disp[v]=0x40; v=v+1; } if((ms==3&&y==3)&&v<8) { mima[v]=0x00; jm_disp[v]=0x40; v=v+1; } if((y==1||y==2)&&(ms==0&&lock<8)) { y=2; w=1; keyvalue=keyvalue-13; lock=lock+1; count=0; } if((ms==1&&y==1)&&v<8) { keyvalue=keyvalue-13; seg_disp[v]=sdm[keyvalue]; if(v==1||v==4) v=v+2; else v=v+1; } } /**************** k14按键功能函数 ******************/ void k14() //确定按键 { uint i,p,t=0,r=0; uchar j; if((ms==2&&y==3)&&v==6) 31 { j=0x00; for(i=0;i<6;i++) { At24c02Write(j,mima[i]); j=j+1; } for(i=0;i<8;i++) jm_disp[i]=0x00; v=0; ms=0; y=1; } if((ms==3&&y==3)&&v==8) { j=0x06; for(i=0;i<8;i++) { At24c02Write(j,mima[i]); j=j+1; } for(i=0;i<8;i++) jm_disp[i]=0x00; v=0; ms=0; y=1; } if((y==2)&&(w==0)) ent=1; if(ms==1&&y==1) { for(i=0;i<8;i++) { for(p=0;p<16;p++) { if(seg_disp[i]==sdm[p]) { if((i==0||i==3)||i==6) clk_value[t]=p*10; if((i==1||i==4)||i==7) { clk_value[t]=clk_value[t]+p; t=t+1; } } } } TR0=1; ms=0; v=0; 32 } } /**************** k15按键功能函数 ******************/ void k15() //设置时间按键 { if(ms==0&&y==1) { TR0=0; ms=1; } } /***************** 核对密码函数 *****************/ void open_lock() { uint i,i1; uchar j; if((y==2&&w==1)) { if(v<8) { mima[v]=keyvalue; jm_disp[v]=0x40; w=0; v=v+1; } } if((ent==1)&&((lock==6)||(lock==8))) { for(i=0;i 33 { seg=0x79; LSA=1; LSB=1; LSC=1; Delay1ms(3000); y=1; ent=0; v=0; lock=0; for(i1=0;i1<8;i1++) { jm_disp[i1]=0x00; mima[i1]=0x00; } return; } } if(lock==6) { OP=0; ms=4; y=1; v=0; lock=0; for(i1=0;i1<8;i1++) { jm_disp[i1]=0x00; mima[i1]=0x00; } } else { y=3; v=0; lock=0; for(i=0;i<8;i++) { jm_disp[i]=0x08; mima[i]=0x00; } } lock=0; } ent=0; } /******************** 24c02写数据函数 *********************/ void At24c02Write(unsigned char addr,unsigned char dat) { I2C_Start(); I2C_SendByte(0xa0, 1); //发送写器件地址 I2C_SendByte(addr, 1); //发送要写入内存地址 I2C_SendByte(dat, 0); //发送数据 I2C_Stop(); } 34 /******************** 24c02读数据函数 *********************/ unsigned char At24c02Read(unsigned char addr) { unsigned char num; I2C_Start(); } I2C_SendByte(0xa0, 1); //发送写器件地址 I2C_SendByte(addr, 1); //发送要读取的地址 I2C_Start(); I2C_SendByte(0xa1, 1); //发送读器件地址 num=I2C_ReadByte(); //读取数据 I2C_Stop(); return num; 35 //“e_lock.h”头文件 #ifndef __e_lock_H_ #define __e_lock_H_ sbit LSA=P2^5; sbit LSB=P2^6; sbit LSC=P2^7; sbit OP=P2^4; #define seg P0 //数码管段码接口 #define key P1 //按键接口 void c_led(); //开机自检led子函数 void check(); //开机自检函数 void sys_start(); //初始化函数 void sm_key(); //按键检测 void cz(); //拆字函数 void disp(); //显示数码管函数 void open_lock(); //核对密码函数 void Delay1ms(int c); //1ms延时函数 void control(); void k0(); void k1(); void k2(); void k3(); void k4(); void k5(); void k6(); void k7(); void k8(); void k9(); void k10(); //void k11(); void k12(); void k13(); void k14(); void k15(); void At24c02Write(unsigned char addr,unsigned char dat); //24c02写数据函数 unsigned char At24c02Read(unsigned char addr); //24c02读数据函数 36 #endif //I2C.c文件 #include void I2C_Delay10us() { uchar a, b; for(b=1; b>0; b--) { for(a=2; a>0; a--); } } void I2C_Start() { I2C_SDA = 1; I2C_Delay10us(); I2C_SCL = 1; I2C_Delay10us();//建立时间是I2C_SDA保持时间>4.7us I2C_SDA = 0; I2C_Delay10us();//保持时间是>4us I2C_SCL = 0; I2C_Delay10us(); } void I2C_Stop() { I2C_SDA = 0; I2C_Delay10us(); I2C_SCL = 1; I2C_Delay10us();//建立时间大于4.7us I2C_SDA = 1; I2C_Delay10us(); } uchar I2C_SendByte(uchar dat, uchar ack) { uchar a = 0,b = 0;//最大255,一个机器周期为1us,最大延时255us。 37 for(a=0; a<8; a++)//要发送8位,从最高位开始 { I2C_SDA = dat >> 7; //起始信号之后I2C_SCL=0,所以可以直接改变I2C_SDA信号 dat = dat << 1; I2C_Delay10us(); I2C_SCL = 1; } I2C_Delay10us();//建立时间>4.7us I2C_SCL = 0; I2C_Delay10us();//时间大于4us I2C_SDA = 1; I2C_Delay10us(); I2C_SCL = 1; while(I2C_SDA && (ack == 1))//等待应答,也就是等待从设备把I2C_SDA拉低 { b++; if(b > 200) //如果超过200us没有应答发送失败,或者为非应答,表示接收结束 { I2C_SCL = 0; I2C_Delay10us(); return 0; } } I2C_SCL = 0; I2C_Delay10us(); return 1; } uchar I2C_ReadByte() { uchar a = 0,dat = 0; I2C_SDA = 1; //起始和发送一个字节之后I2C_SCL都是0 I2C_Delay10us(); for(a=0; a<8; a++)//接收8个字节 { I2C_SCL = 1; I2C_Delay10us(); dat <<= 1; dat |= I2C_SDA; I2C_Delay10us(); I2C_SCL = 0; 38 I2C_Delay10us(); } return dat; } //”I2C.h”头文件 #ifndef __I2C_H_ #define __I2C_H_ #ifndef uchar #define uchar unsigned char #endif #ifndef uint #define uint unsigned int #endif sbit I2C_SCL = P2^1; sbit I2C_SDA = P2^0; void I2C_Delay10us(); void I2C_Start(); void I2C_Stop(); uchar I2C_SendByte(uchar dat, uchar ack); uchar I2C_ReadByte(); #endif 39 系统原理图: 40
正在阅读:
门禁电子密码锁说明书12-13
2017年电大流通概论形成性考核册答案-05-20
关于三月三的优美散文03-21
教师座谈会发言稿(优秀7篇)03-22
文言文宾语前置类型10-30
每日生活语录11-20
张抗抗散文读后感03-21
张晓风经典散文11-21
- exercise2
- 铅锌矿详查地质设计 - 图文
- 厨余垃圾、餐厨垃圾堆肥系统设计方案
- 陈明珠开题报告
- 化工原理精选例题
- 政府形象宣传册营销案例
- 小学一至三年级语文阅读专项练习题
- 2014.民诉 期末考试 复习题
- 巅峰智业 - 做好顶层设计对建设城市的重要意义
- (三起)冀教版三年级英语上册Unit4 Lesson24练习题及答案
- 2017年实心轮胎现状及发展趋势分析(目录)
- 基于GIS的农用地定级技术研究定稿
- 2017-2022年中国医疗保健市场调查与市场前景预测报告(目录) - 图文
- 作业
- OFDM技术仿真(MATLAB代码) - 图文
- Android工程师笔试题及答案
- 生命密码联合密码
- 空间地上权若干法律问题探究
- 江苏学业水平测试《机械基础》模拟试题
- 选课走班实施方案
- 密码锁
- 门禁
- 说明书
- 电子
- 新版《现代汉语词典》成语释义变化
- 雷锋简介及图片后的故事
- 农村初中开展数学高效课堂之浅见
- 11-12学年下学期电教中心工作总结
- 小学生文明礼仪教育教案 - (8个)校本34
- 做人口诀
- 人教版一年级下册多音字练习及多音字综合
- 2016年高考生物备考对策全国新课标卷生物试题命题特点
- 陈蛮庄煤矿大倾角采煤工作面管理规定
- 20.五节 遗传与环境 导学案
- 金匮背诵原文条目
- 业主委员会备案申请表
- 福建省小学语文四年级学业质量监测试题(样卷二)
- 重庆市主城区农村居民点分布特征分析 - 图文
- 小学儿童的人际关系
- 语文整合课,让智慧携笑声飞扬农村中学
- 博雅西苑小区3#住宅楼施工组织设计
- 2018年电大液压气动技术试题及答案全参考(3) - 图文
- 中国首战即是决战 - 图文
- 用意象分析的方法开展高中古典诗词群文阅读