【51单片机】基于51单片机的时钟电子锁设计

注:此文原创,欢迎大家一起交流相关知识,如有需要引用需提前告知。

目录

1设计概述..... 2

1.1功能与设计内容... 2

1.2整体设计方案... 2

2功能实现..... 5

2.1硬件部分... 5

2.1.1硬件模块... 5

2.1.2硬件原理图... 10

2.2软件部分... 11

2.2.1软件模块... 11

2.2.2流程图... 11

2.2.3代码... 17

3所遇问题..... 18

3.1设计问题... 18

3.1.1键盘的利用... 18

3.1.2功能完善... 18

3.2调试问题... 19

3.2.1无法debugging. 19

3.2.2出现syntax error. 19

3.2.3函数未定义/函数参数表错误/函数返回值缺漏... 19

3.2.4数码管显示重影... 19

4收获..... 20

附录..... 22

附录A 头文件Initial.H代码... 22

附录B 源文件ElcLock.c代码... 22

 


 

1设计概述

1.1功能与设计内容

现在宿舍一般都有规定时间的门禁,比如晚上23:00关门,早上6:00开门,有时候宿舍管理员忘记或者早上起床晚了或者不想走出房间亲自开门,延迟开关门就会对学生的进出造成不便。所以设想制造一种电子密码锁,应用单片机相应资源,能够在满足基本定时开关门的要求之外扩展一些新功能。

所以针对这一想法,我对这样的时钟密码锁设计了如下功能。

总的说来,功能分为四个模式:

(1)  时钟模式

①24小时制时钟,显示实时时间,包括小时,分,秒信息;

②能够校准时间,通过按键控制小时,分,秒分别加一

(2)  设闹钟模式

①设置闹钟为某一个值,通过设置小时和分实现,且这个闹钟时间能够保存和显示;

②定时时间到,发光二极管亮起,蜂鸣器响应,表示门开启。

(3)  修改密码模式

①修改当前密码为一个新密码,可以是1-6位的任意整数。

注:只有当以原密码登陆后才能修改密码,避免任何人都能修改密码。

(4)  登录模式

①输入密码,完成输入后显示密码正确情况,发光二极管和蜂鸣器响应,实现没到定时时间可通过输入密码开锁的功能;

②输入正确密码后,可以选择继续修改原密码,也可以选择直接退出,后者情况下就不能继续修改密码了,避免一次输入正确密码后,其他人可以继续修改密码。

额外的,实现一键关门和管理功能,即查看上次密码开锁时间和历史开锁次数。

1.2整体设计方案

本设计使用用HL-1单片机实验板,结合Keil单片机软件开发系统,完成整个程序设计和仿真调试的过程。考虑到涉及到的功能有四个模式,且按键较多,所以用到HL-1实验板上的4*4矩阵键盘,而且使用其中的两个键作为模式控制字的模式选择位,对应如表1.1。

表1.1 时钟电子锁的四个模式

mode1

Mode2

模式

0

0

时钟模式

0

1

设闹钟模式

1

0

修改密码模式

1

1

登录模式

对于24小时制时钟的设计,对于晶振,采用了外部晶振HL-1实验板上的晶振资源,其频率为11.0592MHz。使用单片机的内部中断定时/计数器T0,在工作方式1下,设置计数初始值为4C00H,软件设计20次循环产生1秒信号。软件设置时分秒的变量,初始时刻为12:00:00,按照周期为1秒的时间增长。利用7段共阴极数码管资源显示时间。

由于要实现校准时间,设置闹钟等功能,必须要设计按键模块,则使用HL-1实验板的4*4矩阵键盘,软件实现键盘扫描,按键防抖等,按键按下返回相应返回值,子程序通过不同返回值进行不同的处理。

在时钟模式下,使用矩阵键盘三个按键分别实现时分秒的加一。闹钟模式下共用时分的加一键。利用数码管资源显示闹钟时间。

登录模式下,软件设计密码储存数组,输入数字的验证数组,以及储存输入数字的备用数组,采用矩阵键盘的一个键实现完成输入功能,当输入完成后进行软件设计对比数组进行密码验证,正确时按下确认键即可继续进入修改密码模式下修改密码,按下主模式mode1键直接返回时钟模式,不可修改密码。利用数码管资源显示密码输入界面。

验证密码后,响应模块利用HL-1实验板的LED流水灯资源和蜂鸣器资源对验证结果进行响应。正确时亮绿灯,错误时亮红灯,但是如果绿灯就是亮的(门开),则软件设计了不会亮红灯(关门)。对应的,也通过软件设计定时时间到,绿灯亮,蜂鸣器响5下。

修改密码时,利用按键资源,软件设计进行修改和返回,利用数码管资源显示修改界面。

另外,新增按键一键关门,即软件设计模式控制字为时钟模式下,开门状态为0。

为了实现管理功能,按下某个键查看上次开锁时间和历史开锁次数,主要通过软件设计储存数据的变量和按键响应的函数。历史开锁次数范围为0-99,到达100时清零。

矩阵键盘功能设计如图1.1:

 

 

图1.1 矩阵键盘功能设计图

数码管资源利用如图1.2:

 

 

图1.2 数码管功能设计图

 

 

2功能实现

2.1硬件部分

2.1.1硬件模块

硬件模块图如图2.1所示,51单片机(STC89C52)为主要控制器,与复位电路,晶振电路,电源电路等组成单片机的最小系统,另外通过I/O接口外接外设矩阵键盘,数码管模块和响应模块资源。单片机内部定时器与外部晶振完成时钟功能,其他功能通过I/O口完成控制和数据传送。

 

 

图2.1 硬件模块图

(1)  定时/计数器

①定时/计数器的控制

定时/计数器的控制,是通过特殊功能寄存器TMOD和TCON实现的。本设计选用T0计数器来对定时器模块进行设计。

  1. 工作方式控制寄存器TMOD

TMOD用于选择定时/计数器的工作模式和工作方式,其格式如表2.1所示。

表2.1 工作方式控制寄存器TMOD的格式

GATE

C/

M1

M0

GATE

C/

M1

M0

T1定时/计数器

T0定时/计数器

GATE是门控位,当GATE0时,仅用运行控制位TR0就能控制T0是否进行加一计数。即只需要TR0=1,T0就能启动计数。而如果GATE=1,还需要才能控制T0进行加一计数。

M1和M0是工作方式选择位,选择T0定时器工作在工作方式1时,M1=0, M0=1。

C/是工作模式选择位,如果该位取0,T0工作模式为定时器工作模式,计数器T0仅对单片机的时钟信号12分频后的脉冲信号进行加一计数。如果该位取1,T0工作在计数器工作模式下,这时T0对加在单片机T0和T1两个引脚上的外部脉冲信号进行加一计数。

在本设计中,晶振信号加在XTAL1和XTAL2引脚上,所以计数器T0是对单片机的时钟信号进行加一计数,所以最后可以确定TMOD=00000001B=01H。

  1. 定时/计数器控制寄存器TCON

TCON的格式如表2.2所示。

表2.2控制寄存器TCON的格式

TCON

TF1

TR1

TF0

TR0

IE1

IT1

IE0

IT0

位地址

8FH

8EH

8DH

8CH

8BH

8AH

89H

88H

TCON中TF1和TF0是计数溢出标志位。使用中断方式时,作为中断请求标志位,CPU进入中断服务后,该位由单片机内部硬件电路自动清0。

TR1和TR0是运行控制位,TR=1时,启动T0开始加一计数,可由软件置1和清0。

②定时/计数器定时常数的确定

51单片机内部计数器用作定时器时,对机器周期计数,每个机器周期的长度是12个振荡周期。HL-1实验板上的晶振频率为11.0592MHz,由于T0工作在工作方式1时是16位计数器,最大计数为65536。那么最大定时时间为

 

为了实现更精准的1s信号,取定时时间为50ms,利用软件循环20次,每循环20次循环计数变量清零,即能实现1s信号。那么计数范围为

 

则计数初值取为65536-46080=19456D=4C00H,所以进行T0初始赋值时,TH0=4CH, TL0=0。

(2)  矩阵键盘

①矩阵键盘原理

HL-1实验板上已有的4*4矩阵键盘原理图如图所示:

 

 

图2.1 矩阵键盘原理图

图2.1中,每条行线和列线的交叉处不直接连通,而是通过一个按键开关连接。当没有键闭合时,行线,列线之间是断开的。当键盘上某个键被按下时,对应的行列线短路,行线输入即为列线输出,且均为低电平。

②键盘扫描

在某一时刻只让一条行线对应P3.x为0,其余行线和列线均为1,那么当该行有按键被按下而闭合时,这一行线和相应列线电平均被拉低,P3口的8位数据高四位和第四位各有一个0。按照相应行列线为0,其余为1得到P3口的8位数据,逐列查找直到找到对应列线,那么说明这一行和找到的这一列交叉处的按键被按下,通过软件设计返回相应的P3口数据。如果这一行没有按键按下时,则按照相同的方法让下一行对应P3.x为0,逐列查找。这里采用的是循环扫描的扫描方式,对于本设计需要不断读取键盘状态比较有利,而且思考简单,设计容易。

如,当图2.1中的键盘进行扫描时:

  1. 扫描第0行

先置P3口8位数据为11111110B,则P3.0对应的第0行置为0,若此时有键按下,比如S0按下,那么读取P3口数据,P3=11101110B,没有键按下时仍是11111110B。

  1. 比较两种情况下的8位数据

本设计采用的方法是比较高四位,判断是否有0。其实按键与否的区别就是高四位是否有0,在判断时为了排除第四位的影响可让8位数据与低四位为0000的8位数据进行与操作&,那么低四位与操作之后均为0000。让高四位与1111进行与操作,则有按键按下时,结果中有一位为0,没有按键按下时,结果还为1111。那么总结可知,让读取的8位数据与11110000B进行与操作。

  1. 返回8位数据

在排除键抖动之后,确定的按键按下后,逐列查找,软件里依照不同的8位数据依次与读取的P3比对,比对正确的返回相应的键值。处理函数通过键值进行后续处理。

某一行(第0行)键盘扫描的流程如式(2.1)(未表现消除键抖动):

式(2.1)

③按键防抖

由于按键是机械弹性触点,在闭合或者是断开的过程中都有抖动过程,电平跳动,电压信号出现毛刺,因此需要消除抖动的影响以免键盘容易受外部干扰而给单片机发出错误信号。抖动时间一般为5~10ms,因此在判断有键按下时,先通过软件延时一段时间(10ms),再判断是否有键按下,如果仍能检测到按键按下,说明确定有一个键被按下;否则,按照键抖动处理。

(3)  数码管的显示

①LED数码管的显示原理

HL-1实验板使用的是两个3位7段共阴极数码管,所以在某段发光二极管上施加一定的正向电压时,该段笔画就亮,不加电压即暗。

 

 

图2.2 共阴极数码管电路图

如图2.2,若向各控制端a, b, c, …, g, dp顺次送入对应信号,显示器显示相应字型。本设计需要显示数字和少量字符串,所以列出部分字型以及所对应的控制码,如表2.3所示。

表2.3 共阴极7段LED数码管显示字型编码表

显示字符

段选码

显示字符

段选码

0

3FH

5

6DH

1

06H

6

7DH

2

5BH

7

07H

3

4FH

8

7FH

4

66H

9

6FH

段选码控制字符的选择,位选码用于控制哪一个数码管能够显示字符。对应的位选码位取0,相应的共阴极数码管可以正常工作。如图2.3所示,HL-1实验板上的数码管位选信号对应位选码的低六位,如果位选码为0FEH,那么第一个数码管可以正常工作。

 

 

图2.3 7段共阴极数码管

②数码管的动态显示

静态显示时,需要显示的字符各字段连续通电,所显示的字段连续发光,而且占用I/O资源较多。而时钟模式字符的显示需要实时变化,如果采用静态显示,需要重新设计数码管模块的电路,每一位数码管需要单独进行译码,设计比较复杂。

动态显示时所需字段不连续通电流,在需要多个字符同时显示时,则可以轮流给每个数码管通以电流,逐次显示字符。为了实现多字符同时显示,采用扫描方式。也就是在某一时刻只让某一个LED数码管显示相应字符。在这个时刻,首先P1作为段选控制I/O口输出相应字符段选码,锁存在74HC573-1的输出端,然后P1作为位选控制I/O口输出位选码,通过74HC573直接送给数码管位选信号端,使相应数码管显示字符。如此轮流,就能让每一位数码管都能显示响应字符,通过软件延时1ms,就能达到视觉稳定的效果,能够看到每位数码管都能同时显示不同字符。

相比于静态显示,动态显示占用I/O口资源少,电路简单,成本低,将更多的控制留给软件设计。

2.1.2硬件原理图

如图。

 

 

 

2.2软件部分

2.2.1软件模块

软件模块除了主程序和中断服务程序,还包括其他子程序模块。如图2.4所示。

 

 

图2.4 软件模块图

其中主程序中循环调用了键盘扫描程序和按键响应程序,当T0计数器中断溢出标志位TF0发出中断请求时,转而进入中断服务程序,执行完毕后继续执行主程序。

2.2.2流程图

(1)主程序流程图

 

 

图2.5 主程序流程图

(2)中断服务程序流程图

 

 

图2.6 中断服务程序流程图

(3)键盘扫描程序流程图

 

 

图2.7 键盘扫描程序流程图

(4)按键处理程序

 

图2.8 按键处理程序流程图

(5)数据调整程序

 

 

图2.9 数据调整程序流程图

(6)响应程序

 

 

图2.10 响应程序流程图

2.2.3代码

见附录A,B。

附录

附录A 头文件Initial.H代码

 1 //initial.H
 2 
 3 #ifndef initial_H
 4 #define initial_H
 5 
 6 sbit DU= P2^6;      //段选信号,控制数码管显示数字的控制数锁存
 7 sbit WE= P2^7;      //位选信号,控制数码管的选择 
 8 sbit point= P0^7;  //小数点的定义
 9 sbit FM= P2^3;    //蜂鸣器
10 
11 //独立键盘初始化
12 sbit key1=P3^4;
13 sbit key2=P3^5;
14 sbit key3=P3^6;
15 sbit key4=P3^7;
16 
17 //LED流水灯模块初始化
18 sbit led0=P1^0;
19 sbit led1=P1^1;
20 sbit led2=P1^2;
21 sbit led3=P1^3;
22 sbit led4=P1^4;
23 sbit led5=P1^5;
24 sbit led6=P1^6;
25 sbit led7=P1^7;
26 
27 
28 #endif

附录B 源文件ElcLock.c代码

   1 #include <reg52.h>
   2 #include <initial.H>
   3 
   4 #define uchar unsigned char
   5 #define uint unsigned int
   6 
   7 uchar i,num=0,numi=0;                                //定时器由50ms产生1s时钟信号时所用的循环变量
   8 int key=11;                                            //设置按键变量
   9 int mode1=0,mode2=0;                                //设定模式变量
  10 int ch;                                               //门是否应该开启的状态
  11 int close=0;                                        //关门信号
  12 int ok=0;                                           //确认键的状态
  13 int sure=0;                                         //账号和密码正确状态,用于修改密码等
  14 uchar sec=0,min=0,hour=12;                              //定义秒,分,时;设置时钟初值
  15 uchar alarmh=6,alarmm=0,ah1,ah2,am1,am2;            //定义设定时间的分,时
  16 uchar code table[]={0x3f, 0x06, 0x5b, 0x4f, 0x66,     //对应{0,1,2,3,4,5,6,7,8,9}
  17                     0x6d, 0x7d, 0x07, 0x7f, 0x6f};
  18 //显示上次开锁时间数组
  19 int showlast=0;
  20 int lasth=0,lastm=0;
  21 //历史开锁次数
  22 int opennum=0;
  23 //密码数组
  24 int pw[]={0,0,0,0,0,0};
  25 //验证数组        
  26 int id[]={1,1,1,1,1,1};
  27 int id1[]={1,1,1,1,1,1};
  28 //数码管上显示相应数组名的字符串     
  29 uchar code done[]={0x5e,0x5c,0x54,0xfb,0x80,0x80};
  30 uchar code yes[]={0x6e,0x7b,0xed,0x80,0x80,0x80};
  31 uchar code no[]={0x54,0xdc,0x80,0x80,0x80,0x80};
  32 uchar code login[]={0x38,0x5c,0x6f,0x06,0xd4,0x80};
  33 uchar code edit[]={0x79,0x5e,0x06,0xf8,0x80,0x80}; 
  34 
  35 int matrixkeyscan();        //扫描键盘
  36 void dealwithkey();            //处理按键(是主要部分)
  37 int check();                //检查门是否应该开启的状态
  38 void showtime(int s);        //显示实时时间和闹钟,参数:0-时间,1-时间
  39 void showpwid(int s);        //显示当前密码和输入密码,参数:0-密码,1-登录输入
  40 void delayms(uint xms);        //延时函数
  41 void response();            //响应门开启状态,LED和蜂鸣器
  42 void showstring(int s);        //显示字符串函数,参数指定不同字符串
  43 void init();                //定时器初始化
  44 
  45 void main()
  46 {
  47     init();
  48     while(1)
  49     {
  50          key=matrixkeyscan(); //获取按键
  51          dealwithkey();          //处理按键
  52     }
  53 }
  54 
  55 void T0_INT(void)  interrupt 1      //中断响应函数
  56 {
  57     i++;
  58     TR0=0;
  59     TH0=0x4c;
  60     TL0=0;
  61     if(i==20)                   //定时器定时50ms,则一个20次的循环可产生1s信号
  62     {
  63         i=0;
  64         sec++;
  65     }
  66     if(sec==60)
  67     {
  68         sec=0;
  69         min++;
  70     }
  71     if(min==60)
  72     {
  73         min=0;
  74         hour++;
  75     }
  76     if(hour==24)
  77         hour=0;
  78     TR0=1;    
  79 }
  80 
  81 int matrixkeyscan()
  82 {
  83     uchar temp,key;
  84     P3=0xfe;   //1111 1110
  85     temp=P3;
  86     temp=temp&0xf0;
  87     if(temp!=0xf0)
  88     {
  89       delayms(10);
  90         temp=P3;
  91         temp=temp&0xf0;
  92       if(temp!=0xf0)
  93       {
  94         temp=P3;
  95         switch(temp)
  96         {
  97           case 0xee:     //11101110
  98                key=0;
  99                break;
 100           case 0xde:    //11011110
 101                key=1;
 102                break;
 103           case 0xbe:
 104                key=2;
 105                break;
 106           case 0x7e:
 107                key=3;
 108                break;
 109          }
 110          while(temp!=0xf0)
 111          {
 112            temp=P3;
 113            temp=temp&0xf0;
 114          }
 115          return(key);
 116       }
 117     }
 118     P3=0xfd;
 119     temp=P3;
 120     temp=temp&0xf0;
 121     if(temp!=0xf0)
 122     {
 123       delayms(10);
 124       temp=P3;
 125       temp=temp&0xf0;
 126       if(temp!=0xf0)
 127       {
 128         temp=P3;
 129         switch(temp)
 130         {
 131           case 0xed:
 132                key=4;
 133                break;
 134           case 0xdd:
 135                key=5;
 136                break;
 137           case 0xbd:
 138                key=6;
 139                break;
 140           case 0x7d:
 141                key=7;
 142                break;
 143          }
 144          while(temp!=0xf0)
 145          {
 146            temp=P3;
 147            temp=temp&0xf0;
 148          }
 149          return(key);
 150       }
 151       }
 152     P3=0xfb;
 153     temp=P3;
 154     temp=temp&0xf0;
 155     if(temp!=0xf0)
 156     {
 157       delayms(10);
 158          temp=P3;
 159       temp=temp&0xf0;
 160       if(temp!=0xf0)
 161       {
 162         temp=P3;
 163         switch(temp)
 164         {
 165           case 0xeb:
 166                key=8;
 167                break;
 168           case 0xdb:
 169                key=9;
 170                break;
 171           case 0xbb:
 172                key=10;
 173                break;
 174           case 0x7b:
 175                key=11;
 176                break;
 177          }
 178          while(temp!=0xf0)
 179          {
 180            temp=P3;
 181            temp=temp&0xf0;
 182          }
 183         return(key);
 184       }
 185       }
 186     P3=0xf7;
 187     temp=P3;
 188     temp=temp&0xf0;
 189     if(temp!=0xf0)
 190     {
 191       delayms(10);
 192       temp=P3;
 193       temp=temp&0xf0;
 194       if(temp!=0xf0)
 195       {
 196         temp=P3;
 197         switch(temp)
 198         {
 199           case 0xe7:
 200                key=12;
 201                break;
 202           case 0xd7:
 203                key=13;
 204                break;
 205           case 0xb7:
 206                key=14;
 207                break;
 208           case 0x77:
 209                key=15;
 210                break;
 211          }
 212          while(temp!=0xf0)
 213          {
 214            temp=P3;
 215            temp=temp&0xf0;
 216          }
 217         return(key);
 218       }
 219     }
 220         return 16;
 221 }
 222 
 223 void dealwithkey()
 224 {
 225     switch(key)
 226     {
 227         case 0:
 228         {
 229             if((mode1==0)&&(mode2==0))   //时钟校准模式
 230             {
 231                 hour++;
 232                 while(key1==0);
 233                 if(hour==24)
 234                     hour=0;
 235             }
 236             else if((mode1==0)&&(mode2==1))        //时钟定时模式
 237             {
 238                 alarmh++;
 239                 while(key1==0);
 240                 if(alarmh==24)
 241                 alarmh=0;
 242             }
 243             else if((mode1==1)&&(mode2==0)&&(num<6)&&(ok==1))         //修改密码
 244             {
 245                 pw[num]=0;
 246                 num++;
 247             }
 248             else if((mode1==1)&&(mode2==1)&&(numi<6)&&(ok==1))         //输入验证密码
 249             {
 250                 id[numi]=0;
 251                 numi++;
 252             }
 253             break;
 254         }
 255         case 1:
 256         {
 257             if((mode1==0)&&(mode2==0))   //时钟校准模式
 258             {
 259                 min++;
 260                 while(key2==0);
 261                 if(min==60)
 262                 {
 263                     min=0;
 264                     hour++;
 265                     if(hour==24)
 266                         hour=0;
 267                 }
 268             }
 269             else if((mode1==0)&&(mode2==1))        //时钟定时模式
 270             {
 271                 alarmm++;
 272                 while(key2==0);
 273                 if(alarmm==60)
 274                 {
 275                     alarmm=0;
 276                     alarmh++;
 277                     if(alarmh==24)
 278                     alarmh=0;
 279                 }
 280             }
 281             else if((mode1==1)&&(mode2==0)&&(num<6)&&(ok==1))        //修改密码
 282             {
 283                 pw[num]=1;
 284                 num++;
 285             }
 286             else if((mode1==1)&&(mode2==1)&&(numi<6)&&(ok==1))         //输入验证密码
 287             {
 288                 id[numi]=1;
 289                 numi++;
 290             }
 291             break;
 292         }
 293         case 2:
 294         {
 295             if((mode1==0)&&(mode2==0))   //时钟校准模式
 296             {
 297                 sec++;
 298                 while(key3==0);
 299                 if(sec==60)
 300                 {
 301                     sec=0;
 302                     min++;
 303                     if(min==60)
 304                     {
 305                         min=0;
 306                         hour++;
 307                         if(hour==24)
 308                         hour=0;
 309                     }
 310                 }
 311             }
 312             else if((mode1==1)&&(mode2==0)&&(num<6)&&(ok==1))          //修改密码
 313             {
 314                 pw[num]=2;
 315                 num++;
 316             }
 317             else if((mode1==1)&&(mode2==1)&&(numi<6)&&(ok==1))         //输入验证密码
 318             {
 319                 id[numi]=2;
 320                 numi++;
 321             }
 322             break;
 323         }
 324         case 3:
 325         {
 326             if((mode1==1)&&(mode2==0)&&(num<6)&&(ok==1))             //修改密码
 327             {
 328                 pw[num]=3;
 329                 num++;
 330             }
 331             else if((mode1==1)&&(mode2==1)&&(numi<6)&&(ok==1))         //输入验证密码
 332             {
 333                 id[numi]=3;
 334                 numi++;
 335             }
 336             break;
 337         }
 338         case 4:
 339         {
 340             if((mode1==1)&&(mode2==0)&&(num<6)&&(ok==1))             //修改密码
 341             {
 342                 pw[num]=4;
 343                 num++;
 344             }
 345             else if((mode1==1)&&(mode2==1)&&(numi<6)&&(ok==1))         //输入验证密码
 346             {
 347                 id[numi]=4;
 348                 numi++;
 349             }
 350             break;
 351         }
 352         case 5:
 353         {
 354             if((mode1==1)&&(mode2==0)&&(num<6)&&(ok==1))             //修改密码
 355             {
 356                 pw[num]=5;
 357                 num++;
 358             }
 359             else if((mode1==1)&&(mode2==1)&&(numi<6)&&(ok==1))         //输入验证密码
 360             {
 361                 id[numi]=5;
 362                 numi++;
 363             }
 364             break;
 365         }
 366         case 6:
 367         {
 368             if((mode1==1)&&(mode2==0)&&(num<6)&&(ok==1))             //修改密码
 369             {
 370                 pw[num]=6;
 371                 num++;
 372             }
 373             else if((mode1==1)&&(mode2==1)&&(numi<6)&&(ok==1))         //输入验证密码
 374             {
 375                 id[numi]=6;
 376                 numi++;
 377             }
 378             break;
 379         }
 380         case 7:
 381         {
 382             if((mode1==1)&&(mode2==0)&&(num<6)&&(ok==1))             //修改密码
 383             {
 384                 pw[num]=7;
 385                 num++;
 386             }
 387             else if((mode1==1)&&(mode2==1)&&(numi<6)&&(ok==1))         //输入验证密码
 388             {
 389                 id[numi]=7;
 390                 numi++;
 391             }
 392             break;
 393         }
 394         case 8:
 395         {
 396             if((mode1==1)&&(mode2==0)&&(num<6)&&(ok==1))             //修改密码
 397             {
 398                 pw[num]=8;
 399                 num++;
 400             }
 401             else if((mode1==1)&&(mode2==1)&&(numi<6)&&(ok==1))         //输入验证密码
 402             {
 403                 id[numi]=8;
 404                 numi++;
 405             }
 406             break;
 407         }
 408         case 9:
 409         {
 410             if((mode1==1)&&(mode2==0)&&(num<6)&&(ok==1))             //修改密码
 411             {
 412                 pw[num]=9;
 413                 num++;
 414             }
 415             else if((mode1==1)&&(mode2==1)&&(numi<6)&&(ok==1))         //输入验证密码
 416             {
 417                 id[numi]=9;
 418                 numi++;
 419             }
 420             break;
 421         }
 422         case 10:   //时钟和密码模式的切换,0-时钟,1-密码
 423         {
 424             if(num!=6)
 425                 mode1=!mode1;
 426             break;
 427         }
 428         case 11:   //小模式的切换
 429         {
 430             if(num!=6)
 431                 mode2=!mode2;
 432             break;
 433         }
 434         case 12:                   //关门键
 435         {
 436             ch=0;                    //关门状态
 437             close=1;
 438             id[0]=1;                //验证密码还原
 439             id[1]=1;
 440             id[2]=1;
 441             id[3]=1;
 442             id[4]=1;
 443             id[5]=1;
 444             mode1=0;                //回时钟模式
 445             mode2=0;
 446             showlast=0;                
 447             break;
 448         }
 449         case 13:
 450         {
 451             showlast=!showlast;
 452             break;
 453         }
 454         case 14:
 455         {
 456             ok=1;                    //确认变量为1
 457             break;
 458         }
 459         case 15:
 460         {
 461             break;
 462         }
 463     }
 464     if((mode1==0)&&(mode2==0)&&(showlast==0))             //时钟模式下得显示
 465     {
 466         showtime(0); //显示x实时时间
 467         if((ch==0)&&(close==0))
 468             ch=check();                            //先检测门是否到了应该开启的状态
 469         response(); //闹钟响应
 470     }
 471     else if((mode1==0)&&(mode2!=0)&&(showlast==0))       //设置闹钟模式
 472     {
 473         showtime(1); //显示闹钟时间
 474         response(); //闹钟响应                  
 475     }
 476     else if((mode1!=0)&&(mode2==0)&&(showlast==0))             //修改密码模式
 477     {
 478         if((num==0)&&(ok==0))      //先显示edit,等待确认键按下
 479             showstring(5);        
 480         if((num==0)&&(ok==1)&&(sure==0))      //如果确认键按下但是没有先输入原密码,只会回到时钟界面
 481             {
 482                 mode1=0;
 483                 mode2=0;
 484                 ok=0;
 485             }
 486         if((num!=6)&&(ok==1)&&(sure==1))      //先输入了原密码,确认键也按下了,则可以显示编辑密码了
 487         {
 488             showpwid(0);                      //参数为0,显示密码
 489             if(key==15)                          //按下15键表示输入完毕,剩下密码位全部置0
 490                 for(;num<6;num++)
 491                     pw[num]=0;
 492         }
 493         else if(num==6)
 494         {
 495             id1[0]=pw[0];                      //把密码赋给验证数组id[],配合登陆时的赋值让登陆时不会显示当前密码
 496             id1[1]=pw[1];
 497             id1[2]=pw[2];
 498             id1[3]=pw[3];
 499             id1[4]=pw[4];
 500             id1[5]=pw[5];
 501             sure=0;
 502             if(ok==1)                          //按下确认键,显示输入完毕
 503             {
 504                 showstring(1);
 505                 key=matrixkeyscan();
 506                 if((key==14)||(key==10))      //按下主模式键或确认键都能回到时钟界面
 507                 {
 508                     mode1=0;
 509                     mode2=0;
 510                     num=0;
 511                     ok=0;
 512                 }
 513             }
 514         }    
 515     }
 516     else if((mode1!=0)&&(mode2==1)&&(showlast==0))              //登陆模式
 517     {
 518         if((numi==0)&&(ok==0))
 519             showstring(4);                      //显示login
 520         if((numi!=6)&&(ok==1))                  //按下确认键后才能显示输入的数字
 521         {
 522             showpwid(1);
 523             if(key==15)                          //按下15键表示输入完毕,剩下位补0
 524                 for(;numi<6;numi++)
 525                     id[numi]=0;
 526         }
 527         else if(numi==6)                      
 528         {
 529             id1[0]=id[0];                      //输入的数字赋给id1[],用于验证密码
 530             id1[1]=id[1];
 531             id1[2]=id[2];
 532             id1[3]=id[3];
 533             id1[4]=id[4];
 534             id1[5]=id[5];
 535             if(ok==1)
 536             {
 537                 ch=check();            //判断密码是否正确
 538                 if(ch)
 539                 {
 540                     showstring(2);       //正确显示yes
 541                     sure=1;   //账号密码都对了,可以修改密码了
 542                 }
 543                 else
 544                     showstring(3);       //错误显示no
 545                 key=matrixkeyscan();
 546                 if(key==10)                //按下主模式键回到时钟界面,进入edit界面可以修改密码
 547                 {
 548                     if(sure==1)
 549                     {
 550                         lasth=hour;
 551                          lastm=min;
 552                         opennum++;                        //上次开锁时间和历史开锁次数
 553                         if(opennum==99)
 554                             opennum=0;
 555                     }
 556                     mode1=0;
 557                     mode2=0;
 558                     numi=0;
 559                     ok=0;
 560                     sure=0;
 561                 }
 562                 if(key==14)                //按下确认键回到时钟界面,进入edit界面也不能输入密码
 563                 {                        //管理员登陆后必须按下这个键,否则其他人进入edit界面
 564                     mode1=0;            //也能修改密码
 565                     mode2=0;
 566                     numi=0;
 567                     ok=0;
 568                     if(sure==1)
 569                     {
 570                         lasth=hour;
 571                          lastm=min;
 572                         opennum++;                        //上次开锁时间和历史开锁次数
 573                         if(opennum==99)
 574                             opennum=0;
 575                     }
 576                 }
 577             }
 578         }    
 579     }
 580     else if(showlast==1)
 581     {
 582         /*秒个位的计算与显示*/
 583             DU=1;                        //开锁次数显示
 584             P0=table[opennum%10];
 585             DU=0;
 586             P0=0xff;
 587             WE=1;
 588             P0=0xdf;
 589             WE=0;
 590             delayms(1);
 591             /*秒十位的计算与显示*/
 592             DU=1;
 593             P0=table[opennum/10];
 594             DU=0;
 595             P0=0xff;
 596             WE=1;
 597             P0=0xef;
 598             WE=0;
 599             delayms(1);
 600             /*分个位的计算与显示*/
 601             am2=lastm%10;
 602             DU=1;
 603             P0=table[am2];
 604             point=1;         //小数点亮
 605             DU=0;
 606             P0=0xff;
 607             WE=1;
 608             P0=0xf7;    
 609             WE=0;
 610             delayms(1);
 611             /*分十位的计算与显示*/
 612             am1=lastm/10;
 613             DU=1;
 614             P0=table[am1];
 615             DU=0;
 616             P0=0xff;
 617             WE=1;
 618             P0=0xfb;
 619             WE=0;
 620             delayms(1);
 621             /*时个位的计算与显示*/
 622             ah2=lasth%10;
 623             DU=1;
 624             P0=table[ah2];
 625             point=1;        //小数点亮
 626             DU=0;
 627             P0=0xff;
 628             WE=1;
 629             P0=0xfd;    
 630             WE=0;
 631             delayms(1);
 632             /*时十位的计算与显示*/
 633             ah1=lasth/10;
 634             DU=1;
 635             P0=table[ah1];
 636             DU=0;
 637             P0=0xff;
 638             WE=1;
 639             P0=0xfe;
 640             WE=0;
 641             delayms(1);
 642     }
 643 }
 644 void Showtime(int s)
 645 {
 646     switch(s)
 647     {
 648         case 0:                            //参数0:显示实时时间
 649         {
 650             uint h1,h2,m1,m2,s1,s2;
 651             /*秒个位的计算与显示*/
 652             s2=sec%10;
 653             DU=1;
 654             P0=table[s2];
 655             DU=0;
 656             P0=0xff;
 657             WE=1;
 658             P0=0xdf;
 659             WE=0;
 660             delayms(1);
 661             /*秒十位的计算与显示*/
 662             s1=sec/10;
 663             DU=1;
 664             P0=table[s1];
 665             DU=0;
 666             P0=0xff;
 667             WE=1;
 668             P0=0xef;
 669             WE=0;
 670             delayms(1);
 671             /*分个位的计算与显示*/
 672             m2=min%10;
 673             DU=1;
 674             P0=table[m2];
 675             point=1;         //小数点亮
 676             DU=0;
 677             P0=0xff;
 678             WE=1;
 679             P0=0xf7;    
 680             WE=0;
 681             delayms(1);
 682             /*分十位的计算与显示*/
 683             m1=min/10;
 684             DU=1;
 685             P0=table[m1];
 686             DU=0;
 687             P0=0xff;
 688             WE=1;
 689             P0=0xfb;
 690             WE=0;
 691             delayms(1);
 692             /*时个位的计算与显示*/
 693             h2=hour%10;
 694             DU=1;
 695             P0=table[h2];
 696             point=1;        //小数点亮
 697             DU=0;
 698             P0=0xff;
 699             WE=1;
 700             P0=0xfd;    
 701             WE=0;
 702             delayms(1);
 703             /*时十位的计算与显示*/
 704             h1=hour/10;
 705             DU=1;
 706             P0=table[h1];
 707             DU=0;
 708             P0=0xff;
 709             WE=1;
 710             P0=0xfe;
 711             WE=0;
 712             delayms(1);
 713             break;
 714         }
 715         case 1:                              //参数1:显示闹钟时间
 716         {
 717             /*秒个位的计算与显示*/
 718             DU=1;
 719             P0=table[0];
 720             DU=0;
 721             P0=0xff;
 722             WE=1;
 723             P0=0xdf;
 724             WE=0;
 725             delayms(1);
 726             /*秒十位的计算与显示*/
 727             DU=1;
 728             P0=table[0];
 729             DU=0;
 730             P0=0xff;
 731             WE=1;
 732             P0=0xef;
 733             WE=0;
 734             delayms(1);
 735             /*分个位的计算与显示*/
 736             am2=alarmm%10;
 737             DU=1;
 738             P0=table[am2];
 739             point=1;         //小数点亮
 740             DU=0;
 741             P0=0xff;
 742             WE=1;
 743             P0=0xf7;    
 744             WE=0;
 745             delayms(1);
 746             /*分十位的计算与显示*/
 747             am1=alarmm/10;
 748             DU=1;
 749             P0=table[am1];
 750             DU=0;
 751             P0=0xff;
 752             WE=1;
 753             P0=0xfb;
 754             WE=0;
 755             delayms(1);
 756             /*时个位的计算与显示*/
 757             ah2=alarmh%10;
 758             DU=1;
 759             P0=table[ah2];
 760             point=1;        //小数点亮
 761             DU=0;
 762             P0=0xff;
 763             WE=1;
 764             P0=0xfd;    
 765             WE=0;
 766             delayms(1);
 767             /*时十位的计算与显示*/
 768             ah1=alarmh/10;
 769             DU=1;
 770             P0=table[ah1];
 771             DU=0;
 772             P0=0xff;
 773             WE=1;
 774             P0=0xfe;
 775             WE=0;
 776             delayms(1);
 777             break;
 778         }
 779     }
 780 }
 781 void delayms(uint xms)                     //延时xms,用于数码管动态显示
 782 {
 783     uint i,j;
 784     for(i=xms; i>0; i--)
 785         for(j=110; j>0; j--);
 786 }
 787 void response()                             
 788 {
 789 //    ch=check();                            //先检测门是否到了应该开启的状态                                                    
 790     if(ch)                                //
 791     {
 792         led2=0;               //绿灯亮
 793         led0=1;               //红灯灭
 794          if((alarmh==hour)&&(alarmm==min)&&(sec<10)&&(sec%2))       //小时,分钟符合,则响5下蜂鸣器
 795             FM=0;
 796         else
 797             FM=1;
 798     }
 799     else                                //
 800     {
 801         led2=1;               //绿灯灭
 802         led0=0;               //红灯亮
 803         FM=1;
 804     }
 805 }
 806 
 807 void showstring(int s)
 808 {
 809     switch(s)
 810     {
 811          case 1:                    //参数1:显示done
 812         {
 813             DU=1;
 814             P0=done[5];
 815             DU=0;
 816             P0=0xff;
 817             WE=1;
 818             P0=0xdf;
 819             WE=0;
 820             delayms(1);
 821 
 822             DU=1;
 823             P0=done[4];
 824             DU=0;
 825             P0=0xff;
 826             WE=1;
 827             P0=0xef;
 828             WE=0;
 829             delayms(1);
 830 
 831             DU=1;
 832             P0=done[3];
 833             DU=0;
 834             P0=0xff;
 835             WE=1;
 836             P0=0xf7;    
 837             WE=0;
 838             delayms(1);
 839 
 840             DU=1;
 841             P0=done[2];
 842             DU=0;
 843             P0=0xff;
 844             WE=1;
 845             P0=0xfb;
 846             WE=0;
 847             delayms(1);
 848 
 849             DU=1;
 850             P0=done[1];
 851             DU=0;
 852             P0=0xff;
 853             WE=1;
 854             P0=0xfd;    
 855             WE=0;
 856             delayms(1);
 857 
 858             DU=1;
 859             P0=done[0];
 860             DU=0;
 861             P0=0xff;
 862             WE=1;
 863             P0=0xfe;
 864             WE=0;
 865             delayms(1);
 866              break;
 867         }
 868         case 2:                   //参数2:显示yes
 869         {
 870             DU=1;
 871             P0=yes[5];
 872             DU=0;
 873             P0=0xff;
 874             WE=1;
 875             P0=0xdf;
 876             WE=0;
 877             delayms(1);
 878 
 879             DU=1;
 880             P0=yes[4];
 881             DU=0;
 882             P0=0xff;
 883             WE=1;
 884             P0=0xef;
 885             WE=0;
 886             delayms(1);
 887 
 888             DU=1;
 889             P0=yes[3];
 890             DU=0;
 891             P0=0xff;
 892             WE=1;
 893             P0=0xf7;    
 894             WE=0;
 895             delayms(1);
 896 
 897             DU=1;
 898             P0=yes[2];
 899             DU=0;
 900             P0=0xff;
 901             WE=1;
 902             P0=0xfb;
 903             WE=0;
 904             delayms(1);
 905 
 906             DU=1;
 907             P0=yes[1];
 908             DU=0;
 909             P0=0xff;
 910             WE=1;
 911             P0=0xfd;    
 912             WE=0;
 913             delayms(1);
 914 
 915             DU=1;
 916             P0=yes[0];
 917             DU=0;
 918             P0=0xff;
 919             WE=1;
 920             P0=0xfe;
 921             WE=0;
 922             delayms(1);
 923              break;
 924         }
 925         case 3:                     //参数3:显示no
 926         {
 927             DU=1;
 928             P0=no[5];
 929             DU=0;
 930             P0=0xff;
 931             WE=1;
 932             P0=0xdf;
 933             WE=0;
 934             delayms(1);
 935 
 936             DU=1;
 937             P0=no[4];
 938             DU=0;
 939             P0=0xff;
 940             WE=1;
 941             P0=0xef;
 942             WE=0;
 943             delayms(1);
 944 
 945             DU=1;
 946             P0=no[3];
 947             DU=0;
 948             P0=0xff;
 949             WE=1;
 950             P0=0xf7;    
 951             WE=0;
 952             delayms(1);
 953 
 954             DU=1;
 955             P0=no[2];
 956             DU=0;
 957             P0=0xff;
 958             WE=1;
 959             P0=0xfb;
 960             WE=0;
 961             delayms(1);
 962 
 963             DU=1;
 964             P0=no[1];
 965             DU=0;
 966             P0=0xff;
 967             WE=1;
 968             P0=0xfd;    
 969             WE=0;
 970             delayms(1);
 971 
 972             DU=1;
 973             P0=no[0];
 974             DU=0;
 975             P0=0xff;
 976             WE=1;
 977             P0=0xfe;
 978             WE=0;
 979             delayms(1);
 980              break;
 981         }
 982         case 4:                      //参数4,显示login
 983         {
 984              DU=1;
 985             P0=login[5];
 986             DU=0;
 987             P0=0xff;
 988             WE=1;
 989             P0=0xdf;
 990             WE=0;
 991             delayms(1);
 992 
 993             DU=1;
 994             P0=login[4];
 995             DU=0;
 996             P0=0xff;
 997             WE=1;
 998             P0=0xef;
 999             WE=0;
1000             delayms(1);
1001 
1002             DU=1;
1003             P0=login[3];
1004             DU=0;
1005             P0=0xff;
1006             WE=1;
1007             P0=0xf7;    
1008             WE=0;
1009             delayms(1);
1010 
1011             DU=1;
1012             P0=login[2];
1013             DU=0;
1014             P0=0xff;
1015             WE=1;
1016             P0=0xfb;
1017             WE=0;
1018             delayms(1);
1019 
1020             DU=1;
1021             P0=login[1];
1022             DU=0;
1023             P0=0xff;
1024             WE=1;
1025             P0=0xfd;    
1026             WE=0;
1027             delayms(1);
1028 
1029             DU=1;
1030             P0=login[0];
1031             DU=0;
1032             P0=0xff;
1033             WE=1;
1034             P0=0xfe;
1035             WE=0;
1036             delayms(1);
1037              break;    
1038         }
1039         case 5:                       //参数5:显示edit
1040         {
1041              DU=1;
1042             P0=edit[5];
1043             DU=0;
1044             P0=0xff;
1045             WE=1;
1046             P0=0xdf;
1047             WE=0;
1048             delayms(1);
1049 
1050             DU=1;
1051             P0=edit[4];
1052             DU=0;
1053             P0=0xff;
1054             WE=1;
1055             P0=0xef;
1056             WE=0;
1057             delayms(1);
1058 
1059             DU=1;
1060             P0=edit[3];
1061             DU=0;
1062             P0=0xff;
1063             WE=1;
1064             P0=0xf7;    
1065             WE=0;
1066             delayms(1);
1067 
1068             DU=1;
1069             P0=edit[2];
1070             DU=0;
1071             P0=0xff;
1072             WE=1;
1073             P0=0xfb;
1074             WE=0;
1075             delayms(1);
1076 
1077             DU=1;
1078             P0=edit[1];
1079             DU=0;
1080             P0=0xff;
1081             WE=1;
1082             P0=0xfd;    
1083             WE=0;
1084             delayms(1);
1085 
1086             DU=1;
1087             P0=edit[0];
1088             DU=0;
1089             P0=0xff;
1090             WE=1;
1091             P0=0xfe;
1092             WE=0;
1093             delayms(1);
1094              break;
1095         }
1096     }
1097 }
1098 int check()
1099 {
1100     if(alarmh==hour&&alarmm==min)       //满足定时要求时,不管密码验证状态,ch=1
1101             return 1;
1102     else                            //不满足定时要求时,密码验证正确,ch=1
1103     {
1104         if(pw[0]!=id1[0])
1105             return 0;
1106         else if(pw[1]!=id1[1])
1107             return 0;
1108         else if(pw[2]!=id1[2])
1109             return 0;
1110         else if(pw[3]!=id1[3])
1111             return 0;
1112         else if(pw[4]!=id1[4])
1113             return 0;
1114         else if(pw[5]!=id1[5])
1115             return 0;    
1116         else
1117             return 1;
1118     }
1119 }
1120 void init()                         //定时器初始化
1121 {
1122     DU=0;
1123     WE=0;
1124     TMOD=0x01;                     //定时器T0工作方式为1
1125     TH0=0x4c;                     //计数初值为4C00H,19456D,可计数65536-19456=46080次
1126     TL0=0;                         //由于晶振为11.0592MHz,则每次中断可定时46080*12/11.0592*1μs=50ms
1127     ET0=1;
1128     TR0=1;
1129     EA=1;
1130 }
1131 void showpwid(int s)
1132 {
1133     uint p0,p1,p2,p3,p4,p5;
1134     uint i0,i1,i2,i3,i4,i5;
1135     switch(s)
1136     {
1137         case 0:                        //参数0:显示密码
1138         {
1139             /*6位的计算与显示*/
1140             p5=pw[5];
1141             DU=1;
1142             P0=table[p5];
1143             DU=0;
1144             P0=0xff;
1145             WE=1;
1146             P0=0xdf;
1147             WE=0;
1148             delayms(1);
1149             /*5位的计算与显示*/
1150             p4=pw[4];
1151             DU=1;
1152             P0=table[p4];
1153             DU=0;
1154             P0=0xff;
1155             WE=1;
1156             P0=0xef;
1157             WE=0;
1158             delayms(1);
1159             /*4位的计算与显示*/
1160             p3=pw[3];
1161             DU=1;
1162             P0=table[p3];
1163             DU=0;
1164             P0=0xff;
1165             WE=1;
1166             P0=0xf7;    
1167             WE=0;
1168             delayms(1);
1169             /*3位的计算与显示*/
1170             p2=pw[2];
1171             DU=1;
1172             P0=table[p2];
1173             DU=0;
1174             P0=0xff;
1175             WE=1;
1176             P0=0xfb;
1177             WE=0;
1178             delayms(1);
1179             /*2位的计算与显示*/
1180             p1=pw[1];
1181             DU=1;
1182             P0=table[p1];
1183             DU=0;
1184             P0=0xff;
1185             WE=1;
1186             P0=0xfd;    
1187             WE=0;
1188             delayms(1);
1189             /*1位的计算与显示*/
1190             p0=pw[0];
1191             DU=1;
1192             P0=table[p0];
1193             DU=0;
1194             P0=0xff;
1195             WE=1;
1196             P0=0xfe;
1197             WE=0;
1198             delayms(1);
1199              break;
1200         }
1201         case 1:                           //参数1:显示输入数字
1202         {
1203             /*6位的计算与显示*/
1204             i5=id[5];
1205             DU=1;
1206             P0=table[i5];
1207             DU=0;
1208             P0=0xff;
1209             WE=1;
1210             P0=0xdf;
1211             WE=0;
1212             delayms(1);
1213             /*5位的计算与显示*/
1214             i4=id[4];
1215             DU=1;
1216             P0=table[i4];
1217             DU=0;
1218             P0=0xff;
1219             WE=1;
1220             P0=0xef;
1221             WE=0;
1222             delayms(1);
1223             /*4位的计算与显示*/
1224             i3=id[3];
1225             DU=1;
1226             P0=table[i3];
1227             DU=0;
1228             P0=0xff;
1229             WE=1;
1230             P0=0xf7;    
1231             WE=0;
1232             delayms(1);
1233             /*3位的计算与显示*/
1234             i2=id[2];
1235             DU=1;
1236             P0=table[i2];
1237             DU=0;
1238             P0=0xff;
1239             WE=1;
1240             P0=0xfb;
1241             WE=0;
1242             delayms(1);
1243             /*2位的计算与显示*/
1244             i1=id[1];
1245             DU=1;
1246             P0=table[i1];
1247             DU=0;
1248             P0=0xff;
1249             WE=1;
1250             P0=0xfd;    
1251             WE=0;
1252             delayms(1);
1253             /*1位的计算与显示*/
1254             i0=id[0];
1255             DU=1;                     
1256             P0=table[i0];
1257             DU=0;
1258             P0=0xff;
1259             WE=1;
1260             P0=0xfe;
1261             WE=0;
1262             delayms(1);
1263             break;
1264         }
1265     }
1266 }

 

转载于:https://www.cnblogs.com/delmorezhu/p/7828447.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值