include"8515def.inc" org $0000 rjmp RESET org $0010 RESET:ldi r16,$5F out SPL,R16 ldi r16,$02 out SPH,r16 ;设堆栈底为$025F ldi r25,$00 ;r25用于统计密码输错的次数.    ldi r22,$04 ;内定4个密码    clr r29 ldi r28,$73 ;4个密码存于70-73H  L1:clr r30 ldi r31,$03 ld r0,z+ st y-,r0 dec r22 brne L1 START:ldi r16,$03 out ddrc,r16 ; c口为低二位输出,其余为输入    ldi r16,$FC out portc,r16 ; 开始灯不亮,出c口无输入    ldi r20, $04 ;清除显示器存放地址80-83H的地址    ldi r16,$00 CLEAR: ldi r28,$80 clr r29 st y+,r16 dec r20 brne CLEAR L2: clr r16 out ddrb,r16 ;B口输入    ldi r16,$FF out portb,r16  l3: in r0,pinb ;读b口的输入值 cpi r0,$FF  ;是否有b口键按下? brne KEYIN1 in r1,pinc   ;读c口的输入值 andi r1,$FC ;是否有c口键按下? cpi r1,$FC brne KEYIN2 rjmp L3 KEYIN2: bst r1,4 ;是否按"C",是则显示密码     brtc X3 bst r1,5 ;是否按"D",是则比较密码     brtc x4 D1: ldi r16,$56 recall DELAY ;消除抖动,延时1s D2: in r2,pinc andi r2,$FC cp r2,r1 breq D2 ; 按键放开否?   bst r1,6 ;是否按"#" brtc START ;是则清除   bst r1,7 ;是否按"*"  brtc SET0 ;是则设定新密码   clr r31 ldi r30,$82 ldi r16,$03 CS1: ld r3,z+ ;82H存人83H,81H存人82H,80H存人81H st z, r3 subi r30,2 dec r16 brne CS1 bst r1,3 ;新输入值存人80H brtc N9 bst r1,2 brtc N8 rcall disp ;调用显示子程序 rjmp L3                N8: ldi r19,8 ;如果按8,9中的数, st z,r19 ;分别把它们存人z寄存器所指向的RAM ret N9:ldi r19,9 st z,r19 ret KEYIN1:in r2,pinc cp r2,r0 breq KEYIN1 ;按键放开否?    clr r31 ldi r30,$82 ldi r16,$03 CS2:ld r3,z+ ;$82存人$83,$81存人$82,$80存人$81, st z,r3 subi r30,2 dec r16 brne CS2 bst r0,0 ;按键值0-7 存人$80 brtc N0 bst r0,1 brtc N1 bst r0,2 brtc N2 bst r0,3 brtc N3 bst r0,4 brtc N4 bst r0,5 brtc N5 bst r0,6 brtc N6 bst r0,7 brtc N7 rcall disp rjmp L3 N0: ldi r19,0 ;如果按0-7中的数, st z,r19 ;分别把它们存人z寄存器所指向的RAM ret N1: ldi r19,1 st z,r19 ret N2: ldi r19,2 st z,r19 ret N3: ldi r19,3 st z,r19 ret N4: ldi r19,4 st z,r19 ret N5: ldi r19,5 st z,r19 ret N6: ldi r19,6 st z,r19 ret N7: ldi r19,7 st z,r19 ret X3:rjmp disp2 X4:rjmp COMP disp:ldi r30,$83   ;显示地址指针    clr r31 disp1:ld r3,z-   ;载人D4显示值 adiw r3,$30 ;加上D4 74138的扫描值    ldi r16,oxFF out ddra,r16 ;设置A口为输出    out porta,r3 ;显示D4的值    ldi r16,ox56 rcall DELAY ;扫描延时1s ld r3,z- ; 显示D3,D2,D1 adiw r3,$20 out porta,r3 rcall DELAY ;扫描延时1s ld r3,z- adiw r3,$10 out porta,r3 rcall DELAY ;扫描延时1s ld r3,z- adiw r3,$00 out porta,r3 rcall DELAY ;扫描延时1s ret SET0: ldi r18,$04 ;  要设置4位密码    ldi r28,$80 ; 按键显示地址    ldi r30,$70 ; 密码存放地址 clr r29 clr r31  E1:ld r3,y+ ;$80 存人$70.....$83存人$73 st z+,r3 dec r18 brne E1 ldi r16,ox56  ;延时1s rcall DELAY   E2:rjmp START COMP:ldi r18, $04 ;比较4位密码   ldi r28,$83 ;按键显示地址 ldi r30,$73 ;密码存放地址 clr r29 clr r31 C1:ld r3,y- ld r4,z- cp r3,r4    ;按键值与密码值比较 brne C3 dec r18    ; 相同则比较下一位 brne C1 out portc,$FE ;全部相同则开锁 ldi r16,$2F C2:rcall DELAY clr r25 rjmp START C3:inc r25 cpi r25,$03 breq C4 rjmp START c4:ldi r16,$FD    ;门不开,并打开报警装置 out portc,r16 ldi r16,$CF ; 报警30秒 rcall DELAY ret disp2:         ;欲显示密码值    ldi r30,$73   ;密码存放地址 clr r31 rcall disp1   ;调用显示子程序 in r3,pinc     ;"C"放开否?没有则继续显示 bst r3,4 brtc disp2 ldi r16,$56    ;延时1s rcall DELAY rjmp START DELAY:push r16    ;三次嵌套延时子程序 L0:push r16 L1:push r16 L2:push r16 L3:dec r16 brne L3 pop r16 dec r16 brne L2 pop r16 dec r16 brne L1 pop r16 dec r16 brne L0 pop r16 ret org $300 TABLE: db $02,$06,$03,$02 ;内定密码值 end