程序.asm
来自「AT89C52单片机为核心」· 汇编 代码 · 共 869 行 · 第 1/2 页
ASM
869 行
QCH: MOV @R0,A
INC R0
DJNZ R3,QCH
ret
;***********************************************************************************************
;键盘扫描子程序
;***********************************************************************************************
KEYIN: MOV P1,#0FH
MOV A,P1
ANL A,#0FH
MOV B,A
MOV P1,#0F0H
MOV A,P1
ANL A,#0F0H
ORL A,B
RET
;***********************************************************************************************
;查顺序码子程序
;***********************************************************************************************
CHA: MOV R0,#0FFH ;查键码所对应的
MOV DPTR,#TABLE1
GO: INC R0
MOV A,R0
MOVC A,@A+DPTR
CJNE A,KEYC,GO
MOV KEYC1,R0
RET
WAIT1: MOV R6,#0ffH ;延时子程序
DL4: MOV R7,#0ffH
DL3: NOP
NOP
DJNZ R7,DL3
DJNZ R6,DL4
RET
;************************************************************************************************
;延时子程序(延时1MS)
;***********************************************************************************************
WAIT: MOV R6,#0AH ;延时子程序
DL2: MOV R7,#18H
DL1: NOP
NOP
DJNZ R7,DL1
DJNZ R6,DL2
RET
;***********************************************************************************************
;清除键盘缓冲区内容
;***********************************************************************************************
CLEAR: MOV R0,#30H
MOV R1,#03H
CLEAR1: MOV A,#00H
MOV @R0,A
INC R0
DJNZ R1,CLEAR1
RET
;***********************************************************************************************
;数码管三位显示
;***********************************************************************************************
SS: MOV R3,#03H
MOV R5,A
SS1: LCALL WRITE7219
INC R5
MOV A,R5
DJNZ R3,SS1
RET
;************************************************************************************************
;输入数字显示程序
;***********************************************************************************************
sdp: mov r3,#03h
mov r0,#33h
mov r5,a
pp1: dec r0
mov a,@r0
mov r4,a
mov a,r5
lcall write7219
dec r5
djnz r3,pp1
ret
;*******************************************************************************************
;max7219显示子程序
;*******************************************************************************************
DISPLAY:MOV R0,#34H ;显示数据首地址
MOV R1,#01H
MOV R3,#8H ;显示位数
L2: MOV A,@R0
MOV R4,A
MOV A,R1
ACALL WRITE7219 ;将数据→7219
INC R0
INC R1
DJNZ R3,L2
RET
;----------------------------------------------------------------------------------------
;向MAX7219送数据或地址的子程序:
;----------------------------------------------------------------------------------------
SEND7219:MOV R6,#8 ;向MAX7219 送8 位数据或地址
CLR C
L1: NOP
NOP
CLR P0.0 ;CLK下跳
RLC A ;数据→C
MOV P0.1,C ;传数
NOP
NOP
SETB P0.0 ;CLK上跳
DJNZ R6,L1
RET
;----------------------------------------------------------------------------------------
;写MAX7219的子程序:
;-----------------------------------------------------------------------------------------
WRITE7219:ACALL SEND7219 ;先向MAX7219送地址
MOV A,R4 ;待送内容
ACALL SEND7219 ;向MAX7219 送数据
SETB P0.2 ;数据装载
NOP
CLR P0.2
NOP
RET
;-----------------------------------------------------------------------------------------
;非压缩性BCD码转换成压缩BCD码
;入口条件:待转换的非压缩性BCD码存放在[R0]中,字节数放在R7中。
;出口条件:转换后的压缩性BCD码放在[R1]中
;-----------------------------------------------------------------------------------------
ZHUAN: MOV UU,R0
MOV A,UU
SUBB A,R7 ;修改指针
MOV UU,A
ZHUAN1: MOV A,@R0
ORL A,#0F0H
MOV R6,A
DEC R0
MOV A,R0
CJNE A,UU,KK ;判断是否转换完,为了防止待转换字节是奇数
MOV A,R6
ANL A,#0FH
MOV @R1,A
LJMP TT
KK: MOV A,@R0
SWAP A
ORL A,#0FH
ANL A,R6
MOV @R1,A
DEC R1
DEC R0
dec r7
DJNZ R7,ZHUAN1
TT: NOP
RET
;----------------------------------------------------------------------------------------
;入口条件:待转换的压缩BCD码放在[R0]中,转换的字节数放在R7中。
;出口条件:转换后的非压缩BCD码放在[R1]中。
;影响资源:A,R0,R1,R2,R7。
;----------------------------------------------------------------------------------------
ZHUAN2: MOV A,R7
ADD A,R0
MOV R0,A
MOV A,R7
ADD A,R1
MOV R1,A
DEC R0
ZHUAN3: MOV A,@R0
MOV R2,A
ANL A,#0FH
MOV @R1,A
CJNE R7,#01H,CC
MOV A,R2
SWAP A
ANL A,#0FH
JZ NN
DEC R1
MOV @R1,A
LJMP NN
CC: DEC R1
MOV A,R2
SWAP A
ANL A,#0FH
MOV @R1,A
DEC R0
DEC R1
DJNZ R7,ZHUAN3
NN: NOP
RET
;***********************************************************************************************
;多字节BCD码加法。
;入口条件:字节数放在R7中,被加数放在[R0]中,加数放在[R1]中。
;出口信息:和在[R0]中,最高位进位在CY中。
;影响资源:PSW,A,R2.
;***********************************************************************************************
BCDA: MOV A,R7
MOV R2,A ;取字节数放在R2中
ADD A,R0 ;初始化指针
MOV R0,A
MOV A,R2
ADD A,R1
MOV R1,A
CLR C
BCDA1: DEC R0
DEC R1
MOV A,@R0
ADDC A,@R1
DA A
MOV @R0,A
DJNZ R2,BCDA1
RET
;************************************************************************************************
;多字节压缩BCD码减法子程序
;出口信息:差在[R0]中,最高位进位在CY中。
;入口信息:字节数在R7中,被减数在[R1]中。
;影响资源:PSW,A,R2.
;************************************************************************************************
BCDB: LCALL NEG1 ;减数[R1]十进制取补
LCALL BCDA ;按多字节BCD码加法处理
CPL C ;将补码加法的进位标志转换成借位标志
MOV F0,C ;保护借位标志
LCALL NEG1 ;恢复减数[R1]的原始值
MOV C,F0 ;恢复借位标志
RET
NEG1: MOV A,R0
XCH A,R1
XCH A,R0
LCALL NEG
MOV A,R0
XCH A,R1
XCH A,R0
RET
;多字节BCD码取反
NEG: MOV A,R7
DEC A
MOV R2,A
MOV A,R0
MOV R3,A
NEG0: CLR C
MOV A,#99H;十进制取补
SUBB A,@R0
MOV @R0,A
INC R0
DJNZ R2,NEG0
MOV A,#9AH
SUBB A,@R0
MOV @R0,A
MOV A,R3
MOV R0,A
RET
;**************************************************************************************************
; 24C64发送数据程序
;名称:SENDDATA
;描述:发送BYTECNT 个字节给被控器PCF8583
;被控器地址在SLVADR 中单元地址在SUBADR 中
;所发送数据的字节数ByteCnt 在中发送的数据在XmtDat 缓冲区中
;发送数据正常返回标志F0=0 F0=1 表示被控器无应答或损坏
;*************************************************************************************************
SENDDATA:CLR EA
LCALL START ;发送I2C 总线起始条件
MOV A,SLVADR ;取被控器总线地址
LCALL SENTBYTE ;发送被控器总线地址
JB F0,SENDRETURN ;出错返回
MOV A,SUBADR1 ;取单元地址
LCALL SENTBYTE ;发送单元地址
JB F0,SENDRETURN ;出错返回
SENDTWO:MOV A,SUBADR2 ;取单元地址2
LCALL SENTBYTE ;发送单元地址
JB F0,RCVRETURN ;出错返回
SENDONE:MOV R0,#XMTDAT ;取发送数据缓冲区首址
SENTNEXT:MOV A,@R0
LCALL SENTBYTE ;发送一次数据
JB F0,SENDRETURN ;出错返回
INC R0 ;取下一个数据
DJNZ BYTECNT,SENTNEXT ;重复操作直到发送完最后一个数据
LCALL STOP ;发送I2C 总线停止条件
DELAY10:MOV R7,#30H ;延时10MS,等待数据写完
D1: MOV R6,#34H
D2: DJNZ R6,D2
DJNZ R7,D1
SENDRETURN: SETB EA
RET
;***************************************************************************************************
;24C64接收数据程序;
;名称:RcvData
;描述:从被控器PCF8583 接收ByteCnt 个字节数据
;被控器地址在SlvAdr 中单元地址在SubAdr 中
;所接收数据的字节数ByteCnt 在中接收的数据在XmtDat 缓冲区中
;接收数据正常返回标志F0=0 F0=1 表示被控器无应答或损坏
;**************************************************************************************************
RCVDATA:CLR EA
LCALL START ;发送I2C 总线起始条件
MOV A,SLVADR ;取被控器总线地址
LCALL SENTBYTE ;发送被控器总线地址
JB F0,RCVRETURN ;出错返回
MOV A,SUBADR1 ;取单元地址
LCALL SENTBYTE ;发送单元地址
JB F0,RCVRETURN ;出错返回
RCVTWO: MOV A,SUBADR2 ;取单元地址2
LCALL SENTBYTE ;发送单元地址
JB F0,RCVRETURN ;出错返回
RCVONE: LCALL START ;发送I2C 总线重复起始条件
MOV A,SLVADR ;取被控器总线地址
SETB ACC.0 ;取总线读操作位
LCALL SENTBYTE ;发送被控器总线地址
JB F0,RCVRETURN ;出错返回
CLR ACK ;清接收非应答标志准备接收数据
MOV R0,#RCVDAT ;取接收数据缓冲区首址
DJNZ BYTECNT,RCVNEXT ;如果还未接收数据则转去接收前BYTECNT)-1 个数据
SJMP RCVLAST ;只剩最后一个数据未接收转去接收最后一个数据
RCVNEXT:LCALL RCVBYTE ;接收数据
MOV @R0,A ;将数据放入接收缓冲区中
INC R0 ;指向下一个缓冲区地址
DJNZ BYTECNT,RCVNEXT ;重复操作直到剩下最后一个数据
RCVLAST:SETB ACK ;置接收非应答标志准备在接收完最后一个数据后发出非应答信;号以停止接收数据
LCALL RCVBYTE ;接收最后一个数据
MOV @R0,A ;将最后一个数据放入接收缓冲区中
LCALL STOP ;发送I2C 总线停止条件
RCVRETURN: SETB EA
RET
;------------------------------------------------------------------------------------------------
;名称:START
;描述:启动I2C 总线子程序--发送I2C 起始条件
;--------------------------------------------------------------------------------------------------
START: SETB SDA ;发送起始条件的数据信号
NOP
SETB SCL ;发送起始条件的时钟信号
NOP ;起始条件建立时间大于4.7 S
NOP
NOP
NOP
NOP
CLR SDA ;发送起始信号
NOP ;起始条件锁定时间大于4 S
NOP
NOP
NOP
NOP
CLR SCL ;钳住I2C 总线准备发送或接收数据
RET
;---------------------------------------------------------------------------------------------------
;名称:STOP
;描述:停止I2C 总线子程序--发送I2C 总线停止条件
;---------------------------------------------------------------------------------------------------
STOP: CLR SDA ;发送停止条件的数据信号
NOP
SETB SCL ;发送停止条件的时钟信号
NOP ;起始条件建立时间大于4 s
NOP
NOP
NOP
NOP
SETB SDA ;发送I2C 总线停止信号
NOP
NOP
NOP
NOP
RET
;------------------------------------------------------------------------------------
;名称:SentByte
;描述:字节数据传送子程序发送一个字节数据或地址给被控器PCF8583
;要发送的数据在ACC 中
;发送数据正常返回标志F0=0 F0=1 表示被控器无应答或损坏
;-------------------------------------------------------------------------------------
SENTBYTE:MOV B,#08H ;要传送的数据长度为8 位
SENTB: RLC A ;要发送的数据左移,发送位入C
JC SENT1 ;发送位为“1”转发送数据位“1”
CLR SDA ;发送数据位“0”
SJMP SENT ;转发送数据位
SENT1: SETB SDA ;发送数据位“1”
NOP
SENT: NOP
SETB SCL ;置时钟线为高通知被控器开始接收数据位
NOP ;保证时钟高周期大于4 S
NOP
NOP
NOP
NOP
CLR SCL ;钳住总线准备接收下一个数据位
DJNZ B,SENTB ;8 位没发送完继续发送
NOP
NOP
SETB SDA ;8 位发送完后释放数据线准备收应答位
NOP
NOP
SETB SCL ;开始接收应答信号
NOP
NOP
CLR F0 ;预先清发送数据出错标志
JNB SDA, ACKEND ;判断是否接收到应答信号正常转ACKEND
SETB F0 ;未收到应答置位错误标志
ACKEND: NOP
CLR SCL ;发送结束钳住总线准备下一步发送或接收数据或进行其它处理
RET
;----------------------------------------------------------------------------------------------------
;名称:RCVBYTE
;描述:字节数据接收子程序从被控器PCF8583 接收一个字节数据然后根据主程序要求发送应答位
;接收的字节数据在ACC 中
;---------------------------------------------------------------------------------------------------
RCVBYTE:SETB SDA ;置数据线为输入方式
MOV B,#08H ;要传送的数据长度为8 位
RCV: NOP
CLR SCL ;置时钟线为低准备接收数据位
NOP ;时钟低周期大于4.7 S
NOP
NOP
NOP
NOP
SETB SCL ;置时钟线为高使数据线上数据有效
NOP
NOP
CLR C ;准备将接收的数据位放入ACC 中
JNB SDA,RCV0 ;读数据位若为“0”则置C=0 并转RCV0 接收数据位
SETB C ;读数据位若为“1”则置C=1
RCV0: RLC A ;接收的数据位放入ACC 中
NOP
NOP
DJNZ B,RCV ;8 位没收完继续接收
CLR SCL ;8 位接收完置时钟线和数据线为低准备发送应答或非应答信号
NOP
NOP
NOP
CLR SDA
JNB ACK,SENTACKB ;判断是否需要继续接收字节数据若需要则转SENTACKB 发送应答位
SETB SDA ;发送非应答信号
SENTACKB:NOP ;以下程序发送应答位
NOP
SETB SCL ;置时钟线为高使应答位有效
NOP ;时钟高周期大于4 S
NOP
NOP
NOP
NOP
CLR SCL ;清时钟线钳住I2C 总线以便继续接收字接数据或发送停止条件
CLR ACK ;清接收非应答标志
RET
TABLE1: DB 7EH,0BEH,0DEH,0EEH
DB 7DH,0BDH,0DDH,0EDH
DB 7BH,0BBH,0DBH,0EBH
DB 77H,0B7H,0D7H,0E7H
END
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?