📄 ic.asm
字号:
JMP NUEND
NU5:
CJNE A,#5H,NU6
MOV 72H,#6DH
JMP NUEND
NU6:
CJNE A,#6H,NU7
MOV 72H,#7DH
JMP NUEND
NU7:
CJNE A,#7H,NU8
MOV 72H,#07H
JMP NUEND
NU8:
CJNE A,#8H,NU9
MOV 72H,#7FH
JMP NUEND
NU9:
MOV 72H,#6FH
NUEND:
RET
;*****************************向存储芯片写入*******************
WR_1B: SETB SDA ;初始状态
SETB SCL ;置SDA&SCL=1
ACALL START ;启动I2C总线
MOV R7,#0A0H ;写命令
ACALL WR8BIT ;按位写入1个字节
ACALL CACK ;应答检查
MOV ACC,POINTER ;取芯片地址
MOV R7,ACC ;送芯片地址
ACALL WR8BIT ;写芯片地址
ACALL CACK ;应答检查
MOV ACC,NUMB ;取待写数据
MOV R7,ACC ;送数据
ACALL WR8BIT ;写数据
ACALL CACK ;应答检查
ACALL STOP ;停止
ACALL DEL10MS ;等待内部写周期完成
RET
;***************************读存储芯片指定地址的单元******************
RD_1B: LCALL START ;启动总线
MOV R7,#0A0H ;写命令
LCALL WR8BIT ;写写命令
LCALL CACK ;应答检查
MOV A,POINTER ;取地址
MOV R7,A ;送地址
LCALL WR8BIT ;写地址
LCALL CACK ;应答检查
SETB SDA ;
SETB SCL ;保证启动条件
LCALL START ;再次启动总线,以便进行读操作
MOV R7,#0A1H ;送芯片地址+写命令
LCALL WR8BIT ;写芯片地址+写命令
LCALL CACK ;应答检查
LCALL RD8BIT ;读8位数
LCALL STOP ;关闭总线
RET
START: LCALL DEL5US ;对2402操作开始
CLR SDA ;在SCL=1时,SDA由1变为0表示开始
LCALL DEL5US
CLR SCL
LCALL DEL5US
RET
;***************************写8比特*****************************
WR8BIT: MOV A,R7 ;将R7中的数发送出去
MOV R6,#08H ;数据位数
WR1BIT: RLC A ;将A中的数据移到数据线上
MOV SDA,C ;送出数据
LCALL DEL5US ;延时5US
SETB SCL ;发送串行时钟进行写操作
LCALL DEL5US
CLR SCL
DJNZ R6,WR1BIT ;串行发送8BIT
SETB SDA ;准备接收ACK
LCALL DEL5US
SETB SCL ;接收ACK的时钟
LCALL DEL5US
RET
CACK: MOV R1,#05 ;检测应答
CACK1: MOV C,SDA
DJNZ R1,Y1
LJMP Y2
Y1: JC CACK1 ;有应答的时候应为低电平
AJMP Y3
Y2: MOV R1,#06H
Y3: CLR SCL ;为下一步其他操作做准备
CLR SDA ;
LCALL DEL1MS ;等待内部写完
RET
;***************************读8比特*****************************
RD8BIT: PUSH ACC ;保存 ACC
MOV R6,#08H
RD1B: SETB SDA ;置数据线=1
LCALL DEL5US
SETB SCL ;输出一个串行时钟
LCALL DEL5US
MOV C,SDA ;读数据线上的数据到C
RLC A ;移到ACC
LCALL DEL5US
CLR SCL
DJNZ R6,RD1B ;读8BIT数据
LCALL DEL5US
CLR SDA
MOV R7,ACC ;将接收到的数据保存到R7
POP ACC ;还原ACC
RET
STOP: LCALL DEL5US ;对2402操作结束
SETB SCL ;在 SCL =1时,SDA由0变为1表示结束
LCALL DEL5US
SETB SDA
LCALL DEL5US
RET
DEL5US: NOP
NOP
NOP
NOP
RET
DEL1MS: MOV R4,#200
NOP
NOP
NOP
DJNZ R4,$-3
RET
DEL10MS: MOV 3FH,#10
LCALL DEL1MS
DJNZ 3FH,$-3
RET
;*******************把内存30~37写入外存30H~37H****************
WT:
MOV R0,#30H
MOV R1,#30H
CUN1:
MOV POINTER,R0
MOV 39H,R1
MOV NUMB,@R1
LCALL WR_1B
CJNE R1,#06H,W13
JMP W11
W13:
MOV R1,39H
INC R0
INC R1
CJNE R0,#36H,CUN1
JMP W21
W11:
LCALL WRONG
W21:
RET
;****************把内存40~47写入外存50H~57H**********************
WT1:
MOV R0,#50H
MOV R1,#40H
RCUN1:
MOV POINTER,R0
MOV 59H,R1
MOV NUMB,@R1
LCALL WR_1B
CJNE R1,#06H,RW13
JMP RW11
RW13:
MOV R1,59H
INC R0
INC R1
CJNE R0,#56H,RCUN1
JMP RW21
RW11:
LCALL WRONG
RW21:
RET
;***************************60TO40****************************
STS:
MOV R4,#05H
MOV R1,#60H
DD1:
MOV @R1,#00H
INC R1
DJNZ R4,DD1
LCALL NUIN
MOV R6,#05H
MOV R0,#60H
MOV A,#40H
ADD A,R7
CLR C
SUBB A,#2H
MOV R1,A
MOV 53H,A
DD2:
MOV A,@R0
MOV @R1,A
INC R0
DEC R1
DJNZ R7,DD2
MOV R1,53H
INC R1
DD3:
MOV @R1,#00H
INC R1
;MOV A,R1
CJNE R1,#46H,DD3
RET
;*****************************错卡显示********************
WRONG:
CLR WELA
MOV P0,#00H
SETB WELA
CLR WELA
CLR DULA
MOV P0,#08H ;全选中,显示下横线
SETB DULA
CLR DULA
LCALL DELAY2
MOV R3,#100
WRO:
LCALL DELAY2
DJNZ R3,WRO
RET
;********************把外存30~37读入内存30H~37H*********************
RT:
MOV R0,#30H
MOV R1,#30H
QU1:
MOV POINTER,R0
MOV 39H,R1
LCALL RD_1B
MOV A,R7
MOV R1,39H
MOV @R1,A
INC R0
INC R1
CJNE R0,#36H,QU1
JMP RT21
RT11:
LCALL WRONG
RT21:
RET
;***************************显示余额*********************
SHOWSUR:
SH0:
MOV R7,#07H
LCALL KSTART ;有任意键按下则返回
JNZ SHEND
MOV 71H,#0FEH ;初始化,此时选中最左边的数码管
SH1:
MOV R1,#35H ;循环显示的起始位置,数据的最高位
SH3:
DJNZ R7,SH2 ;一轮是否显示完
MOV R7,#07h ;显示完毕则重给R2赋原值
JMP SH0
SH2:
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
DEC R1
JMP SH3
SHEND:
RET
;*****************把外存50~57写入内存40H~47H*************************
RRT1:
MOV R0,#50H
MOV R1,#40H
RQU1:
MOV POINTER,R0
MOV 59H,R1
LCALL RD_1B
MOV A,R7
MOV R1,59H
MOV @R1,A
INC R0
INC R1
CJNE R0,#56H,RQU1
JMP RRT21
RRT11:
LCALL WRONG
RRT21:
RET
;***************************显示上一次的操作数*********************
SHOWDO:
DO0:
MOV R7,#07H
LCALL KSTART ;有任意键按下则返回
JNZ DOEND
MOV 71H,#0FEH ;初始化,此时选中最左边的数码管
DO1:
MOV R1,#45H ;循环显示的起始位置,数据的最高位
DO3:
DJNZ R7,DO2 ;一轮是否显示完
MOV R7,#07h ;显示完毕则重给R2赋原值
JMP DO0
DO2:
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
DEC R1
JMP DO3
DOEND:
RET
;********************选择功能键的时候进行显示************************
SELSHOW: ;因为按键的问题,本来应该1对应1,现在改为4对应1
CJNE A,#0CH,SHOW2
;按下的是4,选择的是功能1,显示的也是1,按键依次判断,不是的就顺移
CLR WELA
MOV P0,#00H
SETB WELA
CLR WELA
CLR DULA
MOV P0,#00H ;位全选,全灭
SETB DULA
CLR DULA
CLR WELA
MOV P0,#0FEH
SETB WELA
CLR WELA
CLR DULA
MOV P0,#06H ;选中Q1,显示1
SETB DULA
CLR DULA
LCALL DELAY2
MOV R0,A ;键值送到R0 中进行传递
JMP KEYSCAN
;调用键盘扫描程序,将扫描值放回累加器中,返回的时候不再回到这里,
;而是回到上面调用SELSHOW处
SHOW2:
CJNE A,#0DH,SHOW3
CLR WELA
MOV P0,#00H
SETB WELA
CLR WELA
CLR DULA
MOV P0,#00H ;位全选,全灭
SETB DULA
CLR DULA
CLR WELA
MOV P0,#0FEH
SETB WELA
CLR WELA
CLR DULA
MOV P0,#5BH ;选中Q1,显示2
SETB DULA
CLR DULA
LCALL DELAY2
MOV R0,A
JMP KEYSCAN
SHOW3:
CJNE A,#0EH,SHOW4
CLR WELA
MOV P0,#00H
SETB WELA
CLR WELA
CLR DULA
MOV P0,#00H ;位全选,全灭
SETB DULA
CLR DULA
CLR WELA
MOV P0,#0FEH
SETB WELA
CLR WELA
CLR DULA
MOV P0,#4FH ;选中Q1,显示3
SETB DULA
CLR DULA
LCALL DELAY2
MOV R0,A
JMP KEYSCAN
SHOW4:
CJNE A,#0FH,SURE
CLR WELA
MOV P0,#00H
SETB WELA
CLR WELA
CLR DULA
MOV P0,#00H ;位全选,全灭
SETB DULA
CLR DULA
CLR WELA
MOV P0,#0FEH
SETB WELA
CLR WELA
CLR DULA
MOV P0,#66H ;选中Q1,显示4
SETB DULA
CLR DULA
LCALL DELAY2
MOV R0,A
SURE:
RET
;************************键盘扫描*********************************
KEYSCAN:
LCALL KSTART ;调用检测按键子程序
JNZ PRE ;有键按下继续
LCALL DELAY2 ;无键按下调用延时去抖动程序
AJMP KEYSCAN ;返回继续检测有无按键按下
PRE: LCALL DELAY2
LCALL DELAY2 ;有键按下继续延时去抖动
LCALL KSTART ;再一次调用检测按键程序
MOV R1,#04H
JNZ K2 ;确认有按下进行下一步
AJMP KEYSCAN ;无键按下返回继续检测
K2: MOV R2,#0feH ;将扫描值送入 R2暂存
MOV R4,#00H
K3: MOV P3,R2 ;将R2的值送入P2口
L6: JB P3.4,L1 ;P2.0等于1跳转到L1
MOV R3,#00H ;将第一行的行值00H送入ACC
AJMP LK ;跳转到键值处理程序
L1: JB P3.5,L2 ;P2.1等于1跳转到L2
MOV R3,#01H ;将第二行的行值送入ACC
AJMP LK ;跳转到键值理程序进行键值处理
L2: JB P3.6,L3 ;P2.2等于1跳转到L3
MOV R3,#02H ;将第三行的行值送入ACC
AJMP LK ;跳转到键值处理程序
L3: JB P3.7,NEXT ;P2.3等于1跳转到NEXT处
MOV R3,#03H
AJMP LK ;将第四行的行值送入ACC
NEXT:
MOV A,R2 ;将R2的值送入A
RL A ;扫描未完成将A中的值右移一位进行下一列的扫描
MOV R2,A ;将ACC的值送入R2暂存
MOV A,R4
ADD A,#4H
MOV R4,A
DJNZ R1,K3 ;跳转到K3继续
JMP K2
LK:
MOV A,R3
ADD A,R4
RET
;************************端口初始化,便于判断是否有键按下**************
KSTART:
MOV P3,#0FH ;将P1口高四位置0低四位值1
MOV A,P3 ;读P1口
XRL A,#0FH ;将A中的值与A中的值相异或
RET ;子程序返回
;********* ***************40ms延时去抖动子程序***************
DELAY2: ;8*FA*2=40ms
MOV R5,#08H
L7: MOV R6,#0AH
L8: DJNZ R6,L8
DJNZ R5,L7
RET
;*********************蜂鸣器程序************************************************
FENGMING:
MOV R5,#0B0H
FEE: CLR SPK
LCALL DELAY88
LCALL DELAY88
LCALL DELAY88
LCALL DELAY88
LCALL DELAY88
LCALL DELAY88
LCALL DELAY88
LCALL DELAY88
SETB SPK
LCALL DELAY88
DJNZ R5,FEE
RET
;**********************************************************************************
DELAY3: ;8*16*FA*2=640ms
MOV R5,#80H
LLL7: MOV R6,#0FAH
LLL8: DJNZ R6,LLL8
DJNZ R5,LLL7
RET
;***************************************************************************************
DELAY88:MOV R1,#20H
LL88: MOV R2,#02H
DJNZ R2,$
DJNZ R1,LL88
RET
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -