173 2438 5004
KEROS加密芯片——品牌直销 | 免费样品 | 技术支持
当前位置:网站首页 > 资讯中心 正文 资讯中心

单片机电子密码锁带空闲模式

htxw 2023-03-15 资讯中心 32 ℃

空闲模式和掉电模式下,8051单片机内部状态有何异同

空闲模式,功耗降低一大半,掉电功耗几乎为0,都可通过中断唤醒。

空闲模式,代码不再执行,只有定时器工作,能通过定时器中断唤醒。

掉电模式,只能通过外部中断唤醒。

跪求单片机电子密码锁设计

TLOW EQU 00H

THIGH EQU 0EEH

COUN0 EQU 200 ;5ms * 200 = 1S

COUN1 EQU 3FH ;密码的位数

D_TIME EQU 3EH ;设置密码时的时间限制

SEC EQU 3DH ;秒单元

PASS_OLD EQU 30H

PASS_NEW EQU 40H

SDA EQU P3.4 ;24C01的串行数据线

SCLK24 EQU P3.3 ;24C01的串行时钟线

;20H.0 为时间限制标记

;20H.1 为按错键标记

;20H.2 为比较对错标记

;20H.3 为3秒时间标记

RS EQU P2.0

RW EQU P2.1

EN EQU P2.2

X EQU 2FH ;LCD 地址变量

BEEP EQU P3.7

;--------------------------------------------------

ORG 0000H

JMP MAIN

ORG 0BH

JMP T0_INT

;--------------------------------------------------

MAIN:

MOV SP,#60H

MOV A,#00H

MOV D_TIME,A

MOV SEC,A

MOV COUN1,A

MOV R5,#06H

MOV R0,#PASS_OLD

CLR_01: MOV @R0,A

INC R0

DJNZ R5,CLR_01

CLR EN

CLR 20H.0

CLR 20H.1

CLR 20H.2

CLR 20H.3

CALL INIT_TIMER

CALL SET_LCD

CALL MENU1

CALL PASS_READ ;读出预定密码。

LOOP1:

CALL SCAN_KEY

CALL DELAY2

CJNE A,#0fH,LOOP1 ;按F键启动进入输入密码程序

SETB TR0

LP0: CALL SCAN_KEY ;按住F键3秒以上蜂鸣器不响为止

CALL DELAY2

CJNE A,#0fH,LP3

JB 20H.3,LP1 ;3秒到,20H.3置1。

JMP LP0

LP1: CLR TR0 ;停止中断

MOV SEC,#00H ;秒单元清零

CLR 20H.3 ;清3秒标记位

LP2: MOV P1,#0F0H ;等待键释放

MOV A,P1

CJNE A,#0F0H,LP2

CALL PASS_IN

JB 20H.2,LOOP2 ;密码正确后方可转下一步

JMP LP4

LP3: CLR TR0 ;停止中断

CLR 20H.3 ;清3秒标记位

MOV SEC,#00H ;秒单元清零

LP4: CALL SYS_RST ;系统复位

RET

NOP

NOP

NOP

LJMP MAIN

LOOP2: MOV R4,#06H ;模拟输出蜂鸣器响六声

LOOP3: CALL BZ

DJNZ R4,LOOP3

MOV A,#00H

LOOP4: CALL SCAN_KEY

CJNE A,#0AH,LOOP6 ;按A键进入PASS_LOOK

CALL PASS_LOOK

LOOP5: CALL SCAN_KEY

CJNE A,#0EH,LOOP5 ;按E键退出PASS_LOOK

CALL MENU1

CALL MENU2

LOOP6: CJNE A,#0BH,LOOP8 ;按B键进入PASS_SET

CALL PASS_SET

LOOP7: CALL SCAN_KEY

CJNE A,#0EH,LOOP7 ;按E键退出PASS_SET

CALL MENU1

CALL MENU2

LOOP8: CJNE A,#0DH,LOOP4 ;按D键退出

ACALL MAIN ;PASS_LOOK和PASS_SET状态

JMP LOOP4

SYS_RST:

RST1: CALL SCAN_KEY

CJNE A,#0DH,RST1 ;"D" 键

LJMP MAIN

RET

NOP

NOP

NOP

LJMP MAIN

PASS_IN:

MOV 21H,#03H ;允许输入三次密码

P_IN1: MOV DPTR,#IN_PASS0 ;

MOV A,#1 ;

CALL LCD_SHOW

MOV DPTR,#INFO2 ;指针指到显示信息2

MOV A,#2 ;显示在第二行

CALL LCD_SHOW

MOV R0,#PASS_OLD

MOV R3,#00H

MOV R2,#09H ;设置LCD地址

MOV COUN1,#06H ;6位密码

SETB TR0

P_IN2: JB 20H.0,P_IN4

MOV P1,#0F0H

MOV A,P1

CJNE A,#0F0H,P_IN3

jmp P_IN2

P_IN3:

CALL KEY_IN

CALL SETDATA0

CALL BZ

JB 20H.1,P_IN4

DJNZ COUN1,P_IN2

CLR TR0

CLR 20H.0

CALL PASS_COMP

JNB 20H.2,P_IN4 ;比较对错标记

RET

P_IN4: CLR TR0

CLR 20H.0 ;

CLR 20H.1 ;

CALL INPUT_ERR

DJNZ 21H,P_IN1 ;

RET

IN_PASS0:

DB " INPUT PASSWORD ",0

PASS_COMP:

MOV COUN1,#06H ;比较6位数值

MOV R0,#PASS_OLD

MOV R1,#PASS_NEW

P_COMP0: MOV A,@R0

MOV B,@R1

CJNE A,B,P_COMP1

INC R0

INC R1

DJNZ COUN1,P_COMP0

CALL INPUT_OK

SETB 20H.2

RET

P_COMP1: CLR 20H.2

;CALL INPUT_ERR

RET

PASS_SET:

MOV 21H,#05H ;允许输入三次密码

P_SET1: MOV DPTR,#SET_PASS0 ;

MOV A,#1 ;

CALL LCD_SHOW

MOV DPTR,#INFO2 ;指针指到显示信息2

MOV A,#2 ;显示在第二行

CALL LCD_SHOW

MOV R3,#00H

MOV R2,#09H ;设置LCD地址

MOV R1,#PASS_NEW

MOV COUN1,#06H ;6位密码

SETB TR0

P_SET2: JB 20H.0,P_SET4

MOV P1,#0F0H

MOV A,P1

CJNE A,#0F0H,P_SET3

jmp P_SET2

P_SET3:

CALL KEY_IN

CALL SETDATA1

CALL BZ

JB 20H.1,P_SET4

;MOV R5,#04H

;CALL DELAY

DJNZ COUN1,P_SET2

CLR TR0

CLR 20H.0

CALL RESET_OK

CALL EEPW

RET

P_SET4: CLR TR0

CLR 20H.0 ;

CLR 20H.1 ;

CALL RESET_ERR

DJNZ 21H,P_SET1 ;

RET

SET_PASS0:

DB " RESET PASSWORD ",0

MENU1: ;LCD 显示工作菜单信息

MOV DPTR,#MENU01

MOV A,#1 ;在第一行显示信息

CALL LCD_SHOW

RET

MENU01: DB "PASSWORD CONTROL",0

MENU2: ;LCD 显示工作菜单信息

MOV DPTR,#MENU02

MOV A,#2 ;在第一行显示信息

CALL LCD_SHOW

RET

SETDATA1:

MOV A,R3

ANL A,#0FH ;取出低四位二进制数

PUSH ACC

CLR C

SUBB A,#0AH ;减10

POP ACC

JC ASCII3 ;该数小于10,转ASCII0

SETB 20H.1

RET

ADD A,#07H ;大于10的数加上37H

ASCII3: ADD A,#30H ;小于10的数加上30H

MOV @R1,A

MOV B,R2

CALL LCDP2

INC R2

INC R1

RET

SETDATA0:

MOV A,R3

ANL A,#0FH ;取出低四位二进制数

PUSH ACC

CLR C

SUBB A,#0AH ;减10

POP ACC

JC ASCII4 ;该数小于10,转ASCII4

SETB 20H.1

RET

ASCII4: ADD A,#30H ;小于10的数加上30H

MOV @R0,A ;保存密码值

MOV A,#2AH ;显示" * "

MOV B,R2

CALL LCDP2

INC R2

INC R0

RET

PASS_LOOK:

MOV DPTR,#LOOK1 ;指针指到显示信息1

MOV A,#1 ;显示在第一行

CALL LCD_SHOW

MOV DPTR,#LOOK2 ;指针指到显示信息2

MOV A,#2 ;显示在第二行

CALL LCD_SHOW

MOV R1,#PASS_NEW

MOV R2,#09

MOV COUN1,#06

LOOK0: MOV A,@R1

MOV B,R2

CALL LCDP2

INC R2

INC R1

DJNZ COUN1,LOOK0

RET

LOOK1: DB " LOOK PASSWORD ",0 ;LCD 第一行显示信息

LOOK2: DB "PASSWORD ------ ",0 ;LCD 第二行显示信息

SCAN_KEY:

SCAN_K: MOV P1,#0F0H

MOV A,P1

CJNE A,#0F0H,KEY_NUM0 ;有键按下转

JMP KEY_END

KEY_NUM0: CALL KEY_IN

CALL BZ

MOV R5,#04H

CALL DELAY

KEY_END: RET

KEY_IN: MOV P1,#0F0H ;置列线为0,行线为1

MOV A,P1

ANL A,#0F0H

MOV B,A

MOV P1,#0FH ;置列线为1,行线为0

MOV A,P1

ANL A,#0FH

ORL A,B ;高四位与低四位重新组合

CJNE A,#0FFH,KEY_IN1 ;0FFH为末按键

RET

KEY_IN1: MOV B,A

MOV DPTR,#KEYTABLE

MOV R3,#0FFH

KEY_IN2: INC R3

MOV A,R3

MOVC A,@A+DPTR

CJNE A,B,KEY_IN3

MOV A,R3 ;找到,取顺序码

RET

KEY_IN3: CJNE A,#0FFH,KEY_IN2 ;末完,继续查

RET ;0FFH为结束码

SET_LCD:

CLR EN

CALL INIT_LCD ;初始化 LCD

CALL DELAY1

MOV DPTR,#INFO1 ;指针指到显示信息1

MOV A,#1 ;显示在第一行

CALL LCD_SHOW

MOV DPTR,#INFO2 ;指针指到显示信息2

MOV A,#2 ;显示在第二行

CALL LCD_SHOW

RET

INFO1: DB " ",0 ;LCD 第一行显示信息

INFO2: DB "PASSWORD ------ ",0 ;LCD 第二行显示信息INIT_LCD: ;8位I/O控制 LCD 接口初始化

MOV A,#38H ;双列显示,字形5*7点阵

CALL WCOM

CALL DELAY1

MOV A,#38H ;双列显示,字形5*7点阵

CALL WCOM

CALL DELAY1

MOV A,#38H ;双列显示,字形5*7点阵

CALL WCOM

CALL DELAY1

MOV A,#0CH ;开显示,关光标,

CALL WCOM

CALL DELAY1

MOV A,#01H ;清除 LCD 显示屏

CALL WCOM

CALL DELAY1

RET

LCD_SHOW: ;在LCD的第一行或第二行显示信息字符

CJNE A,#1,LINE2 ;判断是否为第一行

LINE1: MOV A,#80H ;设置 LCD 的第一行地址

CALL WCOM ;写入命令

CALL CLR_LINE ;清除该行字符数据

MOV A,#80H ;设置 LCD 的第一行地址

CALL WCOM ;写入命令

JMP FILL

LINE2: MOV A,#0C0H ;设置 LCD 的第二行地址

CALL WCOM ;写入命令

CALL CLR_LINE ;清除该行字符数据

MOV A,#0C0H ;设置 LCD 的第二行地址

CALL WCOM

FILL: CLR A ;填入字符

MOVC A,@A+DPTR ;由消息区取出字符

CJNE A,#0,LC1 ;判断是否为结束码

RET

LC1: CALL WDATA ;写入数据

INC DPTR ;指针加1

JMP FILL ;继续填入字符

RET

CLR_LINE: ;清除该行 LCD 的字符

MOV R0,#24

CL1: MOV A,#' '

CALL WDATA

DJNZ R0,CL1

RET

ENABLE: ;写指令使能

CLR RS ;RS=L,RW=L,D0-D7=指令码,E=高脉冲

CLR RW

SETB EN

CALL DELAY0

CLR EN

RET

ENABLE1: ;写数据使能

SETB RS ;RS=H,RW=L,D0-D7=数据,E=高脉冲

CLR RW

SETB EN

CALL DELAY0

CLR EN

RET

DELAY0: MOV R7,#250 ;延时500微秒

DJNZ R7,$

RET

WCOM: ;以8位控制方式将命令写至LCD

MOV P0,A ;写入命令

CALL ENABLE

RET

WDATA: ;以8位控制方式将数据写至LCD

MOV P0,A ;写入数据

CALL ENABLE1

RET

LCDP2: ;在LCD的第二行显示字符

PUSH ACC ;

MOV A,B ;设置显示地址

ADD A,#0C0H ;设置LCD的第二行地址

CALL WCOM ;写入命令

POP ACC ;由堆栈取出A

CALL WDATA ;写入数据

RET

CONV:

MOV X,#9 ;设置显示起始位置

MOV A,R3

ANL A,#0F0H ;取出高四位二进制数

SWAP A ;高四位与低四位互换

PUSH ACC ;压入堆栈

CLR C ;C=0

SUBB A,#0AH ;减10

POP ACC ;弹出堆栈

JC ASCII0 ;该数小于10,转ASCII0

ADD A,#07H ;大于10的数加上37H

ASCII0: ADD A,#30H ;小于10的数加上30H

MOV B,X

CALL LCDP2

MOV A,R3

ANL A,#0FH ;取出低四位二进制数

PUSH ACC

CLR C

SUBB A,#0AH ;减10

POP ACC

JC ASCII1 ;该数小于10,转ASCII1

ADD A,#07H ;大于10的数加上37H

ASCII1: ADD A,#30H ;小于10的数加上30H

INC X

MOV B,X

CALL LCDP2

RET

DELAY2: MOV R5,#15H

DELAY: ;延时R5×10MS

MOV R6,#50

D1: MOV R7,#100

DJNZ R7,$

DJNZ R6,D1

DJNZ R5,DELAY

RET

DELAY1: ;延时5MS

MOV R6,#25

D2: MOV R7,#100

DJNZ R7,$

DJNZ R6,D2

RET

KEYTABLE:

DB 0EEH,0EDH,0EBH,0E7H,0DEH ;0,1,2,3,4, 顺序码

DB 0DDH,0DBH,0D7H,0BEH,0BDH ;5,6,7,8,9,

DB 0BBH,0B7H,07EH,07DH,07BH ;A,B,C,D,E,

DB 077H,0FFH ;F 0FF为结束码

DB 0DBH,0EEH,0DEH,0BEH,07EH ;0,1,2,3,4, 顺序码

DB 0EDH,0DDH,0BDH,07DH,0EBH ;5,6,7,8,9,

DB 0BBH,07BH,0E7H,0D7H,0B7H ;A,B,C,D,E,

DB 077H,067H,066H,065H,0FFH ;F,C+F,1+F,8+C

INIT_TIMER: ;初始化定时器

MOV TMOD,#01H ;设置定时器0 工作模式为模式1

MOV IE, #82H ;启用定时器0 中断产生

MOV TL0,#TLOW

MOV TH0,#THIGH

RET

T0_INT:

PUSH ACC

MOV TL0,#TLOW

MOV TH0,#THIGH

INC D_TIME

MOV A,D_TIME ;5ms 计数值加1

CJNE A,#COUN0,T0_T

MOV D_TIME,#0

INC SEC ;秒加1

MOV A,SEC

CJNE A,#03H,TO_INT0

SETB 20H.3

TO_INT0: CJNE A,#8,T0_T ;是否到8秒?

MOV SEC,#0 ;秒单元清0

SETB 20H.0

T0_T: POP ACC

RETI

PASS_READ:

CALL EEPR

RET

MOV COUN1,#06H ;6位密码数值

MOV R7,#00H

MOV R1,#PASS_NEW

P_READ: MOV A,R7

MOV DPTR,#R_TABLE

MOVC A,@A+DPTR

MOV @R1,A

INC R1

INC R7

DJNZ COUN1,P_READ

RET

R_TABLE:

DB 35H,36H,34H,34H,38H,38H

COMP_ERR:

MOV DPTR,#COMP_ERR1 ;

MOV A,#2 ;

CALL LCD_SHOW

RET

COMP_ERR1:

DB " PASSWORD ERROR ",0

COMP_OK:

MOV DPTR,#COMP_OK0 ;

MOV A,#2 ;

CALL LCD_SHOW

RET

COMP_OK0:

DB " PASSWORD RIGHT ",0

RESET_ERR:

MOV DPTR,#RESET_ERR0 ;

MOV A,#2 ;

CALL LCD_SHOW

RET

RESET_ERR0:

DB " RESET ERROR ",0

RESET_OK:

MOV DPTR,#RESET_OK0 ;

MOV A,#2 ;

CALL LCD_SHOW

RET

RESET_OK0:

DB " RESET RIGHT ",0

INPUT_ERR:

MOV DPTR,#INPUT_ERR0 ;

MOV A,#2 ;

CALL LCD_SHOW

RET

INPUT_ERR0:

DB " INPUT ERROR ",0

INPUT_OK:

MOV DPTR,#INPUT_OK0 ;

MOV A,#2 ;

CALL LCD_SHOW

RET

INPUT_OK0:

DB " INPUT RIGHT ",0

EEPW: PUSH ACC

PUSH PSW

CLR PSW.3

SETB PSW.4

MOV R1,#PASS_NEW

MOV R7,#06H ;连续写8个字节

LCALL START

MOV A,#0A0H ;送器件地址

ACALL SUBS

MOV A,#00H ;送片内字节地址

ACALL SUBS

AGAIN1:

MOV A,@R1

ACALL SUBS ;调发送单字节子程序

INC R1

DJNZ R7,AGAIN1 ;连续写8个字节

LCALL STOP ;发停止信号

POP PSW

POP ACC

RET

SUBS:

MOV R0,#08H ;发送单字节子程序

LOOP: CLR SCLK24

RLC A

MOV SDA,C

NOP

SETB SCLK24

ACALL DELAY24

DJNZ R0,LOOP ;循环8次送8个bit

CLR SCLK24

ACALL DELAY24

SETB SCLK24

REP: MOV C,SDA

JC REP ;判应答到否,未到则等待

CLR SCLK24

RET

DELAY24:

NOP

NOP

RET

EEPR: PUSH ACC

PUSH PSW

CLR PSW.3

SETB PSW.4

MOV R7,#06H

MOV R1,#PASS_NEW

LCALL START ;发开始信号

MOV A,#0A0H ;送器件地址

ACALL SUBS ;调发送单字节子程序

MOV A,#00H ;送片内字节地址

ACALL SUBS

LCALL START ;再发开始信号

MOV A,#0A1H

ACALL SUBS

MORE: ACALL SUBR

MOV @R1,A

MOV A,#00H

INC R1

DJNZ R7,MORE

LCALL STOP ;送停止信号

POP PSW

POP ACC

RET

SUBR: MOV R0,#08H ;接受单字节子程序

SUBR2: SETB SCLK24

ACALL DELAY24

MOV C,SDA

RLC A

CLR SCLK24

ACALL DELAY24

DJNZ R0,SUBR2

CJNE R7,#01H,ALOW

SETB SDA ;若是最后一个字节置SDA=1

AJMP SETOK

ALOW:

CLR SDA ;否则置SDA=0

SETOK: ACALL DELAY24

SETB SCLK24

ACALL DELAY24

CLR SCLK24

ACALL DELAY24

SETB SDA ;应答毕,SDA置1

RET

START:

CLR SDA

ACALL DELAY24

SETB SDA

SETB SCLK24

ACALL DELAY24

CLR SDA

SETB SCLK24

RET

STOP:

CLR SDA

SETB SCLK24

ACALL DELAY24

SETB SDA

ACALL DELAY24

RET

BZ: ;蜂鸣器

MOV R6,#100

B1: CALL DEX

CPL BEEP

DJNZ R6,B1

MOV R5,#20

CALL DELAY

RET

DEX: MOV R7,#180

DE1: NOP

DJNZ R7,DE1

RET

END

各位单片机高手,请问at89s52如何进入空闲模式及掉电模式?求详细使用方法!多谢!

PCON 电源控制寄存器 PD 跟 IDL位,

PD置1,进入掉电模式,除了外部中断外的所有外设、CPU停止工作,CPU只能被外部中断唤醒;

IDL置1,进入空闲模式,CPU停止工作,所有外设继续工作,CPU可被任意中断唤醒;

真NB,拿51做低功耗,低功耗模式都比别的单片机正常运行模式功耗大!!!所谓的“科研立项”,其实就是大家相互忽悠,学生忽悠老师、老是忽悠学校、学校忽悠教育部。。。反正不要自己掏钱,忽悠的好还能捞钱。。。

怎么设计一个由51单片机控制的电子密码锁

#includereg51.h

#define uint unsigned int

char leab[]={0x7f,0x7f,0x7f,0x7f,0x7f,0x7f};

delay(uint z)

{

uint x;

for(;z0;z--)

for(x=0;x10;x++);//1ms

}

disp()

{

char x,y;

for(x=5;x=0;x--)

{for(y=0;y10;y++)

{P0=0;

P2=x;

P0=leab[x];

delay(10);

P0=0;}

}

}

char sao(char g)

{ char d;

switch(g)

{

case 1:d=1; break;

case 2:d=2; break;

case 4:d=3; break;

case 8:d=4; break;

default:d=0; break;

}

return d;

}

char key()

{

char H=0,L=0,d,d1,d2;

while(1)

{ d=0;

P1=0xf0;

if(P1!=0xf0)

{

delay(10);

if(P1!=0xf0)

{

H=(~(P1^0x0f))4;

P1=0xff;

P1=0x0f;

L=~(P1^0xf0);

d2=sao(L);

d1=sao(H);

d=(d1-1)*4+d2;

P2=d;

}}

if(d!=0) break;

disp();

}

return d;

}

main()

{

char leab1[]={0x00,0x00,0x00,0x00,0x00,0x00};

char leab2[]={0x09,0x08,0x00,0x06,0x01,0x01};

char a,b,d,e=0;

int f;

while(1)

{

P3=0xff;

for(a=0;a6;a++)

{

leab[a]=0x7f;

leab1[a]=0x00;

}

for(b=0;b100;b++)

{

disp();

}

//for(c=0;c6;c++)

//{

// leab[c]=0x00;

//}

while(1)

{

for(d=0;d6;d++)

{

e=key();

if((e=1)(e=10))

{

leab[d] =0x71;

disp();

leab1[d]=e-1;

}

else

{d=d-1; disp();}

if(e==15) break;

}

if(e==15) break;

while(e!=16)

{ disp();

e=key();

if(e==16)break;

if(e==15) break;

}

if(e==15) break;

if((leab1[0]==leab2[0])(leab1[0]==leab2[0])

(leab1[0]==leab2[0])(leab1[0]==leab2[0])

(leab1[0]==leab2[0])(leab1[0]==leab2[0]))

{

for(f=0;f800;f++)

{P3=0x02;

delay(100);

disp();

}

}

else

{for(f=0;f800;f++)

{P3=0x01;

delay(100);

disp();

}}

break;

}

}}

基于单片机的电子密码锁设计

功能键

S6---S15 数字键0-9

S16---更改密码 S17---更改密码完毕后确认

S18---重试密码、重新设定 S19---关闭密码锁

初始密码:000000 密码位数:6位

注意:掉电后,所设密码会丢失,重新上点时,密码恢复为原始的000000

与P1相连的8位发光LED点亮代表锁被打开;熄灭代表锁被锁上

程序功能: 本程序结合了24C02存储器的存储功能,可以掉电保存密码。

第一次运行时,若输入000000原始密码后无反应,可以试验着将主程序中前面的

一小段被注释线屏蔽的程序前的注释线删掉,然后重新编译下载(可以将密码还原为000000)。

此后,再将这小段程序屏蔽掉,再编译下载。方可正常使用。

1、开锁:

下载程序后,直接按六次S7(即代表数字1),8位LED亮,锁被打开,输入密码时,

六位数码管依次显示小横杠。

2、更改密码:

只有当开锁(LED亮)后,该功能方可使用。

首先按下更改密码键S16,然后设置相应密码,此时六位数码管会显示设置密码对应

的数字。最后设置完六位后,按下S17确认密码更改,此后新密码即生效。

3、重试密码:

当输入密码时,密码输错后按下键S18,可重新输入六位密码。

当设置密码时,设置中途想更改密码,也可按下此键重新设置。

4、关闭密码锁:

按下S19即可将打开的密码锁关闭。

推荐初级演示步骤:输入原始密码000000---按下更改密码按键S16---按0到9设置密码---按S17

确认密码更改---按S18关闭密码锁---输入新的密码打开密码锁

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

#includereg52.h

#include intrins.h

#define uint unsigned int

#define uchar unsigned char

uchar old1,old2,old3,old4,old5,old6; //原始密码000000

uchar new1,new2,new3,new4,new5,new6; //每次MCU采集到的密码输入

uchar a=16,b=16,c=16,d=16,e=16,f=16; //送入数码管显示的变量

uchar wei,key,temp;

bit allow,genggai,ok,wanbi,retry,close; //各个状态位

sbit dula=P2^6;

sbit wela=P2^7;

sbit beep=P2^3;

sbit sda=P2^0; //IO口定义

sbit scl=P2^1;

unsigned char code table[]=

{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,

0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00,0x40};

/*****************IIC芯片24C02存储器驱动程序************************************/

void nop()

{

_nop_();

_nop_();

}

/////////24C02读写驱动程序////////////////////

void delay1(unsigned int m)

{ unsigned int n;

for(n=0;nm;n++);

}

void init() //24c02初始化子程序

{

scl=1;

nop();

sda=1;

nop();

}

void start() //启动I2C总线

{

sda=1;

nop();

scl=1;

nop();

sda=0;

nop();

scl=0;

nop();

}

void stop() //停止I2C总线

{

sda=0;

nop();

scl=1;

nop();

sda=1;

nop();

}

void writebyte(unsigned char j) //写一个字节

{

unsigned char i,temp;

temp=j;

for (i=0;i8;i++)

{

temp=temp1;

scl=0;

nop();

sda=CY; //temp左移时,移出的值放入了CY中

nop();

scl=1; //待sda线上的数据稳定后,将scl拉高

nop();

}

scl=0;

nop();

sda=1;

nop();

}

unsigned char readbyte() //读一个字节

{

unsigned char i,j,k=0;

scl=0; nop(); sda=1;

for (i=0;i8;i++)

{

nop(); scl=1; nop();

if(sda==1)

j=1;

else

j=0;

k=(k1)|j;

scl=0;

}

nop();

return(k);

}

void clock() //I2C总线时钟

{

unsigned char i=0;

scl=1;

nop();

while((sda==1)(i255))

i++;

scl=0;

nop();

}

////////从24c02的地址address中读取一个字节数据/////

unsigned char read24c02(unsigned char address)

{

unsigned char i;

start();

writebyte(0xa0);

clock();

writebyte(address);

clock();

start();

writebyte(0xa1);

clock();

i=readbyte();

stop();

delay1(100);

return(i);

}

//////向24c02的address地址中写入一字节数据info/////

void write24c02(unsigned char address,unsigned char info)

{

start();

writebyte(0xa0);

clock();

writebyte(address);

clock();

writebyte(info);

clock();

stop();

delay1(5000); //这个延时一定要足够长,否则会出错。因为24c02在从sda上取得数据后,还需要一定时间的烧录过程。

}

/****************************密码锁程序模块********************************************************/

void delay(unsigned char i)

{

uchar j,k;

for(j=i;j0;j--)

for(k=125;k0;k--);

}

void display(uchar a,uchar b,uchar c,uchar d,uchar e,uchar f)

{

dula=0;

P0=table[a];

dula=1;

dula=0;

wela=0;

P0=0xfe;

wela=1;

wela=0;

delay(5);

P0=table[b];

dula=1;

dula=0;

P0=0xfd;

wela=1;

wela=0;

delay(5);

P0=table[c];

dula=1;

dula=0;

P0=0xfb;

wela=1;

wela=0;

delay(5);

P0=table[d];

dula=1;

dula=0;

P0=0xf7;

wela=1;

wela=0;

delay(5);

P0=table[e];

dula=1;

dula=0;

P0=0xef;

wela=1;

wela=0;

delay(5);

P0=table[f];

dula=1;

dula=0;

P0=0xdf;

wela=1;

wela=0;

delay(5);

}

void keyscan()

{

{

P3=0xfe;

temp=P3;

temp=temp0xf0;

if(temp!=0xf0)

{

delay(10);

if(temp!=0xf0)

{

temp=P3;

switch(temp)

{

case 0xee:

key=0;

wei++;

break;

case 0xde:

key=1;

wei++;

break;

case 0xbe:

key=2;

wei++;

break;

case 0x7e:

key=3;

wei++;

break;

}

while(temp!=0xf0)

{

temp=P3;

temp=temp0xf0;

beep=0;

}

beep=1;

}

}

P3=0xfd;

temp=P3;

temp=temp0xf0;

if(temp!=0xf0)

{

delay(10);

if(temp!=0xf0)

{

temp=P3;

switch(temp)

{

case 0xed:

key=4;

wei++;

break;

case 0xdd:

key=5;

wei++;

break;

case 0xbd:

key=6;

wei++;

break;

case 0x7d:

key=7;

wei++;

break;

}

while(temp!=0xf0)

{

temp=P3;

temp=temp0xf0;

beep=0;

}

beep=1;

}

}

P3=0xfb;

temp=P3;

temp=temp0xf0;

if(temp!=0xf0)

{

delay(10);

if(temp!=0xf0)

{

temp=P3;

switch(temp)

{

case 0xeb:

key=8;

wei++;

break;

case 0xdb:

key=9;

wei++;

break;

case 0xbb:

genggai=1;

wei=0;

break;

case 0x7b:

if(allow)

ok=1;

break;

}

while(temp!=0xf0)

{

temp=P3;

temp=temp0xf0;

beep=0;

}

beep=1;

}

}

P3=0xf7;

temp=P3;

temp=temp0xf0;

if(temp!=0xf0)

{

delay(10);

if(temp!=0xf0)

{

temp=P3;

switch(temp)

{

case 0xe7:

retry=1;

break;

case 0xd7:

close=1;

break;

}

while(temp!=0xf0)

{

temp=P3;

temp=temp0xf0;

beep=0;

}

beep=1;

}

}

}

}

void shumima() //对按键采集来的数据进行分配

{

if(!wanbi)

{

switch(wei)

{

case 1:new1=key;

if(!allow) a=17;

else a=key; break;

case 2:new2=key;

if(a==17) b=17;

else b=key; break;

case 3:new3=key;

if(a==17) c=17;

else c=key; break;

case 4:new4=key;

if(a==17) d=17;

else d=key; break;

case 5:new5=key;

if(a==17) e=17;

else e=key; break;

case 6:new6=key;

if(a==17) f=17;

else f=key;

wanbi=1; break;

}

}

}

void yanzheng() //验证密码是否正确

{

if(wanbi) //只有当六位密码均输入完毕后方进行验证

{

if((new1==old1)(new2==old2)(new3==old3)(new4==old4)(new5==old5)(new6==old6))

allow=1; //当输入的密码正确,会得到allowe置一

}

}

void main()

{

init(); //初始化24C02

/*********下面的一小段程序的功能为格式化密码存储区。************

******当24c02中这些存储区由于其他程序的运行而导致***************

*******所存数据发生了变化,或者密码遗忘时, ********************

******可以删掉其前面的注释线,然后重新编译下载。****************

******而将密码还原为000000后,请将下面的程序用******************

******注释屏蔽掉,重新编译、下载,方可正常使用****************/

// write24c02(110,0x00);

// write24c02(111,0x00);//24c02的第110到115地址单元作为密码存储区

// write24c02(112,0x00);

// write24c02(113,0x00);

// write24c02(114,0x00);

// write24c02(115,0x00);

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

old1=read24c02(110);

old2=read24c02(111);

old3=read24c02(112);

old4=read24c02(113);

old5=read24c02(114);

old6=read24c02(115);

while(1)

{

keyscan();

shumima();

yanzheng();

if(allow) //验证完后,若allow为1,则开锁

{

P1=0x00;

if(!genggai)

wanbi=0;

}

if(genggai) //当S16更改密码键被按下,genggai会被置一

{

if(allow) //若已经把锁打开,才有更改密码的权限

{

while(!wanbi) //当新的六位密码没有设定完,则一直在这里循环

{

keyscan();

shumima();

if(retry|close) //而当探测到重试键S18或者关闭密码锁键S19被按下时,则跳出

{ wanbi=1;

break;

}

display(a,b,c,d,e,f);

}

}

}

if(ok) //更改密码时,当所有六位新密码均被按下时,可以按下此键,结束密码更改

{ //其他时间按下此键无效

ok=0; wei=0;

genggai=0;

old1=new1;old2=new2;old3=new3; //此时,旧的密码将被代替

old4=new4;old5=new5;old6=new6;

//新密码写入存储区。

write24c02(110,old1);

write24c02(111,old2);

write24c02(112,old3);

write24c02(113,old4);

write24c02(114,old5);

write24c02(115,old6);

a=16;b=16;c=16;d=16;e=16;f=16;

}

if(retry) //当重试按键S18被按下,retry会被置位

{

retry=0; wei=0;wanbi=0;

a=16;b=16;c=16;d=16;e=16;f=16;

new1=0;new2=0;new3=0;new4=0;new5=0;new6=0;

}

if(close) //当关闭密码锁按键被按下,close会被置位

{

close=0;genggai=0;//所有变量均被清零。

wei=0; wanbi=0;

allow=0;

P1=0xff;

a=16;b=16;c=16;d=16;e=16;f=16;

new1=0;new2=0;new3=0;new4=0;new5=0;new6=0;

}

display(a,b,c,d,e,f); //实时显示

}

}

对着代码自己做吧,,要是还做不出来,,那我就不说什么了,,

51单片机汇编语言进入空闲掉电模式

PCON寄存器的IDL位(bit 0)用于控制单片机进入空闲模式。当产生中断或发生复位时自动恢复运行。

SETB PCON.0

PCON寄存器的PD位(bit 1)用于控制单片机进入掉电模式。当发生复位时自动恢复运行。

SETB PCON.1

单片机电子密码锁带空闲模式的介绍到此就结束了,感谢您耐心阅读,谢谢。

本文标签:单片机电子密码锁带空闲模式

<