📄 duarts.asm
字号:
;******************************************************************************
; DP-51S单片机仿真实验仪上多机通讯程序
; 本程序是从机部分,主要负责与指定的接收主机发送下来的数据,并输出显示。
;
;File: DUARTS.ASM
;Date: 2002.10.30
;******************************************************************************
LED_ADDR EQU 2000H ;定义LED数码管的数据段地址
;定义本机从机地址及可屏蔽字节,每一个从机定义一个地址
;SADDR_DAT EQU 0C1H
;SADEN_DAT EQU 0FEH
;SADDR_DAT EQU 0C2H
;SADEN_DAT EQU 0FDH
;SADDR_DAT EQU 0C4H
;SADEN_DAT EQU 0FBH
;SADDR_DAT EQU 0C8H
;SADEN_DAT EQU 0F7H
;ADDR_DAT EQU 0D1H
;ADEN_DAT EQU 0FEH
;SADDR_DAT EQU 0D2H
;SADEN_DAT EQU 0FDH
;SADDR_DAT EQU 0D4H
;SADEN_DAT EQU 0FBH
SADDR_DAT EQU 0D8H
SADEN_DAT EQU 0F7H
;定义从机地址及控制寄存器,使用PHILIPS单片机的自动地址识别功能
SADDR DATA 0A9H
SADEN DATA 0B9H
;定义帧错误标志位,PHILIPS单片机的增强功能
FE BIT SCON.7
;定义串行通讯数据发送/接收缓冲区40H---4FH
DATA_BUF EQU 40H
;显示缓冲区50H---54H
DISP_BUF EQU 50H
;显示控制位定义
DISPB0 BIT P1.6 ;显示位控制
DISPB1 BIT P1.0
DISPB2 BIT P1.1
DISPB3 BIT P1.2
DISPB4 BIT P1.3
DISPB5 BIT P1.4
DISPB6 BIT P1.5
KDKEY BIT P1.7
;=========================================================================
ORG 8000H
AJMP MAIN
ORG 8023H
AJMP SERIAL_INT ;串口中断入口
ORG 8100H
MAIN:
MOV SP,#60H
MOV R7,#60
DJNZ R7,$
SERIAL_INI:
MOV TMOD,#20H ;设置定时器1工作模式,波特率发生器
MOV TH1,#0FDH ;设置波特率为9600b
SETB TR1
MOV SCON,#0F0H ;设置串口位方式3,允许串口接收。SM2=1,接收地址
ORL PCON,#40H ;SMOD0=1,使用FE标志位
MOV SADDR,#SADDR_DAT
MOV SADEN,#SADEN_DAT
SETB ES ;打开串口中断允许
SETB EA
DISP_INI:
MOV A,#SADDR_DAT
CPL A
MOV DISP_BUF,A ;L1-L8上显示从机地址
MOV DISP_BUF+1,#0FFH
MOV DISP_BUF+2,#0FFH
MOV DISP_BUF+3,#0FFH
MOV DISP_BUF+4,#0FFH
MOV DISP_BUF+5,#0FFH
MOV DISP_BUF+6,#0FFH
WAIT_INT:
ACALL DISP
ACALL DISP
ACALL DISP
SJMP WAIT_INT
;*************************************************************
;名称:TXDBYTE
;功能:发送数据到显示数据总线上,即输出扫描数据
;入口参数:ACC
;出口参数:无
;占用资源:R3、C
;*************************************************************
TXDBYTE:
MOV DPTR,#LED_ADDR ;LED数码管地址送DPTR
MOVX @DPTR,A
RET
;*************************************************************
;名称:DISP_DLEAY
;功能:显示延时,按12MHz的系统时钟计算,延时1mS
;入口参数:无
;出口参数:无
;占用资源:R7、R6
;*************************************************************
DISP_DELAY:
MOV R7,#10
DISP_DL:MOV R6,#50
DJNZ R6,$
DJNZ R7,DISP_DL
RET
;*************************************************************
;名称:DISP
;功能:将显示缓冲区的数据输出到DP-51的LED上显示
; 采用动态扫描方式,每一个显示位延时1mS,即扫描一次需要5mS
;入口参数:DISP_BUF 显示缓冲区的数据
;出口参数:无
;占用资源:A、R0、TXDBYTE子程序和DISP_DELAY子程序所占用的资源
;*************************************************************
DISP:
MOV R0,# DISP_BUF
DISP_L0:
MOV A,@R0 ;取出显示数据
ACALL TXDBYTE ;输出数据
CLR DISPB0 ;打开显示位,输出显示
ACALL DISP_DELAY ;显示延时
SETB DISPB0
DISP_L1:
INC R0
MOV A,@R0
ACALL TXDBYTE
CLR DISPB1
ACALL DISP_DELAY
SETB DISPB1
DISP_L2:
INC R0
MOV A,@R0
ACALL TXDBYTE
CLR DISPB2
ACALL DISP_DELAY
SETB DISPB2
DISP_L3:
INC R0
MOV A,@R0
ACALL TXDBYTE
CLR DISPB3
ACALL DISP_DELAY
SETB DISPB3
DISP_L4:
INC R0
MOV A,@R0
ACALL TXDBYTE
CLR DISPB4
ACALL DISP_DELAY
SETB DISPB4
DISP_L5:
INC R0
MOV A,@R0
ACALL TXDBYTE
CLR DISPB5
ACALL DISP_DELAY
SETB DISPB5
DISP_L6:
INC R0
MOV A,@R0
ACALL TXDBYTE
CLR DISPB6
ACALL DISP_DELAY
SETB DISPB6
MOV A,#0FFH
ACALL TXDBYTE
RET
;*************************************************************
;串口中断
;处理接收中断,若接收到命令帧的帧头,则开始接收一帧命令,否则不理会此数据。
;*************************************************************
SERIAL_INT:
PUSH ACC ;现场保护
PUSH PSW
ORL PSW,#08H ;切换到寄存器组1
JB TI,SERIAL_INT_EXT ;若是发送中断,则直接退出。
CLR SM2 ;开始接收数据
ACALL SERIAL_RCV_DATA ;接收命令字
JZ SERIAL_INT_EXT
MOV A,SBUF
CJNE A,#12H,SERIAL_INT_EXT ;等待帧头。若不是帧头则直接退出
;接收命令字,并放入DATA_BUF中
MOV R0,#DATA_BUF
ACALL SERIAL_RCV_DATA ;接收一字节串口上的数据,接收到的数据在R1中
JZ SERIAL_INT_EXT ;若接收超时,则退出中断
MOV A,R1 ;进行命令字的分析
MOV @R0,A
;接收命令帧的参数个数,放入DATA_BUF+1中
INC R0
ACALL SERIAL_RCV_DATA ;接收一字节串口上的数据,接收到的数据在R1中
JZ SERIAL_INT_EXT ;若接收超时,则退出中断
MOV A,R1
MOV @R0,A
;接收命令帧的其它参数,放入DATA_BUF+2....
MOV R5,A ;取出所要接收的字节数
SERIAL_INTRD:
INC R0
ACALL SERIAL_RCV_DATA ;接收一字节串口上的数据,接收到的数据在R1中
JZ SERIAL_INT_ERR ;若接收超时,返回命令接收错误,并退出中断
MOV A,R1
MOV @R0,A
DJNZ R5,SERIAL_INTRD
;进行命令帧数据的校验
MOV R7,A ;保存接收到的校验字
MOV R1,#00 ;DATA_BUF缓冲区的数据进行异或结果 (最后一字节除外)
SERIAL_CHKD:
MOV A,R1
DEC R0
XRL A,@R0 ;将DATA_BUF缓冲区的数据进行异或操作
MOV R1,A
MOV A,R0
CJNE A,#DATA_BUF,SERIAL_CHKD ;判断是否已经对接收到的数据全部进行异或操作
MOV A,#12H ;和帧头字异或操作
XRL A,R1
MOV R1,A
MOV A,R7
CJNE A,09H,SERIAL_INT_ERR ;与异或结果R1(寄存器组1)进行比较,若出错,则向主机返回出错帧
MOV A,@R0 ;取出命令字进行判断
CJNE A,#30H,SERIAL_INT_ERR
;若接收正确,则把接收到的数据写入显示缓冲区
MOV DISP_BUF+1,DATA_BUF+3
MOV DISP_BUF+2,DATA_BUF+4
MOV DISP_BUF+3,DATA_BUF+5
MOV DISP_BUF+4,DATA_BUF+6
MOV A,DATA_BUF+2 ;判断是否要回应主机
JZ SERIAL_INT_EXT
MOV R7,#4
MOV DATA_BUF,#12H ;命令帧的帧头
MOV DATA_BUF+1,#0A0H ;命令字--操作失败
MOV DATA_BUF+2,#1 ;返回参数--2字节
MOV DATA_BUF+3,#0B3H
ACALL SERIAL_SENDPC
SJMP SERIAL_INT_EXT
;接收命令出错,返回出错码00H
SERIAL_INT_ERR:
MOV A,DATA_BUF+2 ;判断是否要回应主机
JZ SERIAL_INT_EXT ;若在接收DATA_BUF+3超时或出错,可能会发送出错帧,也可能不发送。
MOV R7,#5
MOV DATA_BUF,#12H ;命令帧的帧头
MOV DATA_BUF+1,#0A1H ;命令字--操作失败
MOV DATA_BUF+2,#2 ;返回参数--2字节
MOV DATA_BUF+3,#00H ;返回码00H,表示接收命令出错
MOV DATA_BUF+4,#0B1H ;异或校验和
ACALL SERIAL_SENDPC
SERIAL_INT_EXT:
POP PSW
POP ACC
CLR TI
CLR RI
SETB SM2
RETI
;*************************************************************
;名称:SERIAL_SENDPC
;功能:将DATA_BUF的数据发送回主机
;入口参数:R7 发送的数据个数
; DATA_BUF 数据缓冲区
;出口参数:无
;占用资源:A、R1、R7
;*************************************************************
SERIAL_SENDPC:
MOV R1,#DATA_BUF
SERIAL_SPL1:
CLR TI
MOV A,@R1
MOV SBUF,A
INC R1
JNB TI,$
DJNZ R7,SERIAL_SPL1
RET
;*************************************************************
;名称:SERIAL_RCV_DATA
;功能:接收一字节串口上的数据
;入口参数:无
;出口参数:R1 接收到的数据
; A 出错值,为00H时表示接收超时,为0FH时表示正确接收。
;占用资源:A、R1、R6、R7
;*************************************************************
SERIAL_RCV_DATA:
CLR FE
CLR RI
MOV R7,#0
MOV R6,#0
SERIAL_RCVD_L1:
JB RI,SERIAL_RCVD_OK
DJNZ R6,SERIAL_RCVD_L1
DJNZ R7,SERIAL_RCVD_L1
MOV A,#00 ;接收超时,超时退出
RET
SERIAL_RCVD_OK:
MOV A,SBUF ;接收数据
MOV R1,A ;将接收到的数据放入R1返回
MOV A,#00
JB FE,SERIAL_RCVD_EXT ;若接收出错,则退出
MOV A,#0FH ;设置接收正确
SERIAL_RCVD_EXT:
RET
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -