📄 ic.asm
字号:
;*****************************************************************
; IC卡收费 单片机中地址30H至37H为8位数字的保存位
;***************************************************************
;*******************************************************************
SUR EQU 0AH
POINTER EQU 20H ;芯片中间变量地址,用来保存数据输入到的24C02的内存地址
NUM EQU 30H
SDA EQU P2.0 ;24c02数据端口
SCL EQU P2.1 ;24c02时钟端口
NUMB EQU 21H
DULA BIT P2.6
WELA BIT P2.7
SPK BIT P2.3
;********************************************************************
ORG 0000H
LJMP MAIN
ORG 0030H
;&&&&&&&&&&&&&&&&&&主程序开始&&&&&&&&&&&&&&&&&&&&&&&&&&&&
MAIN:
MOV R1,#NUM ;将30H--37H初始化为0
M1:
MOV @R1,#0H
INC R1
MOV A,R1
CJNE A,#36H,M1
LCALL RT ;把24C02中30--37H内容读入内存30H--37H
MOV R1,#35H
M4: ;判断余额是否小于10
CJNE R1,#30H,M2
LCALL FENGMING ;余额小于10蜂鸣器响
LCALL DELAY2
M5:
LCALL KSTART
JNZ MAIN1
JMP M5
M2:
CJNE @R1,#0H,MAIN1
DEC R1
JMP M4
MAIN1:
LCALL STARTSHOW ;初始化LED界面进行功能选择
CHO:
LCALL KEYSCAN ;按键扫描,进行功能选择,1 查询上一次的操作 2 扣钱 3存钱 4查询余额
LCALL SELSHOW ;对输入数字进行显示
CJNE A,#SUR,CHO ;输入不是确定键,仍能继续输入
CHO1:
;LCALL KSTART
;JZ CHO1 ;将JNZ改为JZ
LCALL FOUS ;根据输入数字选择功能
JMP MAIN1
SJMP $
;&&&&&&&&&&&&&&&&&&&&&&&&&&主程序结束$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
;子程序开始
ORG 0100H
;******************初始化LED界面进行功能选择*******************
STARTSHOW:
CLR WELA
MOV P0,#00H
SETB WELA
CLR WELA
;低电平有效
CLR DULA
MOV P0,#00H ;低电平有效
SETB DULA
CLR DULA
LOOP:
CLR WELA
MOV P0,#0FEH
SETB WELA
CLR WELA
CLR DULA
MOV P0,#40H ;选中Q1,显示C
SETB DULA
CLR DULA
LCALL DELAY2
CLR WELA
MOV P0,#0FDH
SETB WELA
CLR WELA ;低电平有效
CLR DULA
MOV P0,#76H ;;选中Q2,显示H
SETB DULA
CLR DULA
LCALL DELAY2
CLR WELA
MOV P0,#0FBH
SETB WELA
CLR WELA ;低电平有效
CLR DULA
MOV P0,#79H ;选中Q3,显示O
SETB DULA
CLR DULA
LCALL DELAY2
CLR WELA
MOV P0,#0F7H
SETB WELA
CLR WELA ;低电平有效
CLR DULA
MOV P0,#38H ;Q4,O
SETB DULA
CLR DULA
LCALL DELAY2
CLR WELA
MOV P0,#0EFH
SETB WELA
CLR WELA
CLR DULA
MOV P0,#38H ;Q5,S
SETB DULA
CLR DULA
LCALL DELAY2
CLR WELA
MOV P0,#0DFH
SETB WELA
CLR WELA
CLR DULA
MOV P0,#3fH ;Q6,E
SETB DULA
CLR DULA
LCALL DELAY2
;检测是否有键按下
MOV P3,#0F0H ;将P1口高四位置0低四位值1
MOV A,P3 ;读P1口
XRL A,#0F0H ;将A中的值与A中的值相异或
LCALL DELAY2
JNZ SE
JMP LOOP
SE: RET
;***************************功能选择***************************
FOUS:
MOV A,R0
CJNE A,#0CH,F2
LJMP INQUIRE ;查询上一次的操作
F2:
CJNE A,#0DH,F3
LJMP DEDUCT ;扣钱
F3:
CJNE A,#0EH,F4
LJMP DEPOSIT ;存钱
F4:
LJMP SURPLUS ;查询余额
RET
;********************************扣钱**************************
DEDUCT:
LCALL RT ;把外存30~37读入内存30H~37H
MOV 40H,#23H
MOV 41H,#54H
MOV 42H,#57H
MOV 43H,#46H
MOV 44H,#35H
MOV 45H,#25H
;MOV 46H,#56H
;MOV 47H,#56H
LCALL STS ;键盘输入到60h~67h单元中,并且将输入的单元送到40h~47h中以便后面处理
LCALL WT1 ;将40h起始的内容写入到24c02中50-57H,以便进行查询
;等待处理
MOV R1,#35H ;卡里的钱最高位存到37H
MOV R2,#07H
MOV R0,#50H ;统计卡里钱的位数,存到50H
LCALL LOOP1 ;子程序统计
INC R0 ;将要扣的钱位数存在51H
MOV R1,#45H ;将要扣的钱最高位存在47H
MOV R2,#07H
LCALL LOOP1 ;子程序统计
DEC R0
MOV A,@R0
INC R0
CLR C
SUBB A,@R0
JC ERRORB ;卡里钱的位数比要扣的钱的位数小则报错,调用显示出错的子程序
DEC R0
MOV A,@R0
DEC A
ADD A,#40H
MOV R1,A ;把扣钱的最高位存到R1所指定的地址单元里
MOV A,@R0
DEC A
ADD A,#30H
MOV R0,A
MOV A,@R0 ;把卡里的钱最高位存到A
CLR C
SUBB A,@R1
JC ERRORB ;若要扣的钱和存的钱的位数一样,但扣的钱大,调用显示出错的子程序
MOV R1,#30H
MOV R0,#50H
MOV A,@R0
MOV R0,#40H
MOV R2,A
CLR C
KOUQIAN:MOV A,@R1
SUBB A,@R0
JNC DURU
CLR C
SUBB A,#06H
ANL A,#0FH
SETB C
DURU: MOV @R1,A
INC R1
INC R0
DJNZ R2,KOUQIAN ;*********************************
SJMP FINISHED
ERRORB:
LCALL ERROR
FINISHED:
LCALL WT ;将处理完的30h起始的数据写入到24c02的30h起始的单元中去
;LCALL RT
MOV NUMB,#20H ;标志位,用来查询的时候判断上一次的操作
MOV POINTER,#40H;标志位写入到40h中去
LCALL WR_1B
;LCALL RD_1B
RET
ERROR:
CLR WELA ;出错时,所有数码管全显示一横
MOV P0,#00H
SETB WELA
CLR WELA
CLR DULA
MOV P0,#01H
SETB DULA
CLR DULA
LCALL DELAY2
LCALL KSTART
JZ ERROR
RET
LOOP1:MOV A,R1 ;统计数据区的有效位数,放入R0中
CLR C
SUBB A,#30H
JC ERRORA
DEC R2
MOV A,#00H ;看看30H或40H中的数是否为全零,是则跳转
CLR C
SUBB A,R2
JNC ZERO
MOV A,@R1
DEC R1
CLR C
SUBB A,#00H
JZ LOOP1
MOV A,R2
MOV @R0,A
JMP FINISH
ERRORA:LCALL ERROR
ZERO:MOV @R0,#00H
FINISH:
RET
;****************************存钱*******************************
DEPOSIT:
LCALL RT ;把内存30~37读入外存30H~37H
LCALL STS
;键盘输入到60h~67h单元中,并且将输入的单元送到40h~47h中以便后面处理
LCALL WT1 ;将40h起始的内容写入到24c02中50-57H,以便进行查询
;等待处理
MOV R1,#35H ;卡里的钱最低位存到30H
MOV R2,#07H ;统计卡里钱的位数,存到50H
MOV R0,#50H ;
LCALL LOOP2 ;子程序统计
MOV R1,#45H ;将要存的钱的低位数存到47h
MOV R2,#07H
MOV R0,#51H ;将要扣的钱位数存在51H
LCALL LOOP2 ;子程序统计
MOV R0,#36H
MOV A,#00H
MOV @R0,A
MOV 46H,#00H
MOV R0,#51H
MOV A,@R0
DEC R0
CJNE A,50H,ADDITION
;比较51H和50H中那个数大,如果一样大就按存钱的位数进行加,顺序执行
J1: MOV R1,#30H
MOV R0,#40H
INC A ;***************************************
MOV R2,A
CLR C
CUNQIAN:MOV A,@R1
ADDC A,@R0
DA A
CLR C
MOV R5,A
ANL A,#0F0H
SWAP A
CJNE A,#00H,JINBIAO ;跳转存储进位标志位,顺须执行没有进位
CONTINUE:MOV A,R5
ANL A,#0FH
MOV @R1,A
INC R1
INC R0
DJNZ R2,CUNQIAN
JMP DUSHU
JINBIAO:SETB C
SJMP CONTINUE
ADDITION:JC CARD ;C=1,卡里剩余钱位数高,跳转
JMP J1 ;C=0,存钱位数高,按存钱位数进行加
CARD: MOV A,@R0
JMP J1
DUSHU: MOV A,36H
CLR C
SUBB A,#01H
JC TIAO
MOV R0,#36H
MOV A,#00H
MOV @R0,A
SJMP ERRORC
TIAO: LCALL WT ;将处理完的30h起始的数据写入到24c02的30h起始的单元中去
;LCALL RT
MOV NUMB,#10H ;标志位
MOV POINTER,#40H ;标志位,用来查询的时候判断上一次的操作
LCALL WR_1B ;标志位写入到40h中去
JMP TIAL
ERRORC: LCALL ERROR ;然后重新调这个子程序,重新输入数字
TIAL: RET
LOOP2: DEC R2
MOV A,#00H ;看看30H或40H中的数是否为全零,是则跳转
CLR C
SUBB A,R2
JNC ZERO2
MOV A,@R1
DEC R1
CLR C
SUBB A,#00H
JZ LOOP2
MOV A,R2
MOV @R0,A
jMP FINISHED1
ZERO2:
MOV A,#00H
MOV @R0,A
FINISHED1: RET
;***************************查询上一次的操作**********************
INQUIRE:
MOV POINTER,#40H
LCALL RD_1B
MOV A,R7
CJNE A,#10H,IN1 ;是否为存
CLR WELA
MOV P0,#00H
SETB WELA
CLR WELA
CLR DULA
MOV P0,#4fH ;全选中,显示3
SETB DULA
CLR DULA
LCALL DELAY3
LCALL DELAY3
LCALL DELAY3
LCALL DELAY3
LCALL DELAY3
LCALL DELAY3
JMP IN2
IN1:
CLR WELA
MOV P0,#00H
SETB WELA
CLR WELA
CLR DULA
MOV P0,#5bH ;全选中,显示2
SETB DULA
CLR DULA
LCALL DELAY3
LCALL DELAY3
LCALL DELAY3
LCALL DELAY3
LCALL DELAY3
LCALL DELAY3
IN2:
MOV R2,#100
IN3:
LCALL DELAY2
DJNZ R2,IN3
LCALL RRT1
LCALL SHOWDO
LCALL DELAY3
LCALL DELAY3
LCALL DELAY3
LCALL DELAY3
LCALL DELAY3
LCALL DELAY3
RET
;***************************查询余额********************************
SURPLUS:
LCALL RT
SS1:
LCALL SHOWSUR
LCALL DELAY3
LCALL DELAY3
LCALL KSTART
JZ SS1
;LJMP MAIN1
RET
;**************************数据的输入***********************
NUIN:
MOV R0,#60H
MOV R7,#1
D1:
LCALL KSTART ;上一次的确认键要松开手
JNZ D1
D3:
LCALL ENTER ;调用单个键的输入
MOV 74H,A
D2:
LCALL KSTART ;等待松手
JNZ D2
MOV A,74H
CJNE A,#0AH,GS ;判断不是确定键则继续输入,否则返回
JMP DEND
GS:
CJNE A,#0BH,GS1 ;判断是不是取消键
MOV R1,#60H
D5:
MOV @R1,#00H
INC R1
CJNE R1,#66H,D5
JMP DEND
GS1:
LCALL SHOWNUM ;不是确认键则调用显示程序
JMP D3
DEND:
RET
;*******************************单个数字的输入*********************
ENTER: ;存取钱的时候对键盘输入值的处理
ENEXT:
LCALL KEYSCAN ;扫描键盘输入
CJNE A,#0AH,ENT ;判断不是确定键则继续输入,否则返回
JMP ENTEND
ENT:
MOV @R0,A ;将输入数据放入以60h开始的单元
INC R0
INC R7
JMP E1
ENTEND:
E1: RET
;*************************对已输入数据的循环显示*******************
SHOWNUM:
S0:
MOV 55h,R7 ;单轮循环次数放在b中
LCALL KSTART
JNZ SEND
MOV 71H,#0FEH
S1:
MOV R1,#60H ;循环显示的起始位置
S3:
DJNZ R7,S2 ;一轮是否显示完
MOV R7,55h ;显示完毕则重给R2赋原值
JMP S0
S2:
MOV A,@R1 ;显示的数字放入A中
LCALL K2N
CLR DULA
MOV P0,#00H
SETB DULA
CLR DULA
CLR WELA
MOV P0,71H
SETB WELA
CLR WELA
CLR DULA
MOV P0,72H ;全灭,选中71H位,显示72H内容
SETB DULA
CLR DULA
LCALL DELAY2
MOV A,71H
RL A
MOV 71H,A
INC R1
JMP S3
SEND:
RET
;****************************键值转化为表示的码*********************
K2N:
CJNE A,#0H,NU1
MOV 72H,#3FH
JMP NUEND
NU1:
CJNE A,#1H,NU2
MOV 72H,#06H
JMP NUEND
NU2:
CJNE A,#2H,NU3
MOV 72H,#5BH
JMP NUEND
NU3:
CJNE A,#3H,NU4
MOV 72H,#4FH
JMP NUEND
NU4:
CJNE A,#4H,NU5
MOV 72H,#66H
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -