modbus2002-1d.asm

来自「自已编写的MODBUS程序」· 汇编 代码 · 共 1,722 行 · 第 1/4 页

ASM
1,722
字号
	CPL	P2.2			;清看门狗
	CLR	P2.3			;转换通道。
	CLR	TONGXUN_ZX		;置与CPU通讯位
	CLR	JI_JIAOYAN		;置偶校验标志	
	CLR	TI			
	CLR	RI				
	MOV	2DH,	#00		;每次,清与CPU通讯故障标志位	
	MOV	TH1,	R5
	MOV	TL1,	R6
	CLR	T35			;清T35标志		
	MOV	CISHU_T35,#01H		;送T35定时次数
	SETB	ET1			;允许T1产生中断
	SETB	TR1			;启动T1
	CPL	P2.2			;清看门狗
SEND_1:	
	JBC	T35,	SEND_2		;一次延时时间到,清标志转处理
	JB	P0.2,	SEND_1		;执行器没有响应继续查询(P0.2=0)?		
	CLR     TR1                     ;停T1定时器
	CLR     ET1                     ;禁止T1中断	
	MOV	R0,	#50H		;送发送CPU数据首址
	MOV	R1,	LONG_S_CPU	;送发送给CPU的数据长度
SEND_3:	MOV	A,	@R0		;取发送数据
	MOV	C,	P		;取偶校验位
	MOV	TB8,	C
	MOV	SBUF,	A		;发送
	JNB	TI,	$		;发送未完等待	
	CLR	TI		 	;清发送完成标志位
	INC	R0			;地址加1		
	DJNZ	R1,SEND_3		;未完继续
;	MOV	SCON,	#0D0H
	CPL	P2.2			;清看门狗
	MOV	R0,	#58H		;准备接受
	MOV	R1,LONG_R_CPU		;送接收长度
RECE_1:	CLR	T35			;清T35标志
	MOV	CISHU_T35,#01		;送T35定时次数
	MOV	TH1,	R5
	MOV	TL1,	R6
	SETB	ET1			;允许T1产生中断
	SETB	TR1			;启动T1
RECE_2:	JBC	T35,SEND_2		;延时时间到,转出错处理子程序1
	JNB	RI,RECE_2		;没有接收数据继续查询
	CLR	RI			;有数据,清接收标志位
	CLR	ET1			;禁止T1中断
	CLR	TR1			;停T1定时器
	JNB	JIAOYAN,RECE_3
	MOV	A,	SBUF		;增加偶校验
	JNB	P,	VERIFY_0
	JB	RB8,	RECE_3
	SJMP	COMM_ERR4		;增加偶校验完毕--
RECE_3:	MOV	@R0,	A		;存数据
	INC	R0			;地址加1
	DJNZ	R1,	RECE_1		;未完继续	
	CLR	T35			;再次,清T35标志!!	
	MOV	A,	50H		;发送命令=接收命令吗?
	XRL	A,	58H
	JNZ	COMM_ERR2
	MOV	2DH,#00H		;OK,清通讯标志.
COMM_END:
	SETB	P2.3			;换回总线通道
	SETB	TONGXUN_ZX		;置与总线通讯位
	CLR	JIESHOU_WAN		;清接收完标志位
	CLR	MANG			;清接收处理标志位
	MOV	C,	P1.7
	JC	APPLY_OVER			
	CLR	P1.6			;总线仲裁完毕,复位/A
COMM_OVER:		
	LCALL	T2_MAKE			;换总线用波特率
	POP	PSW			;恢复现场
	POP	ACC
	RET
SEND_2:	
	CPL	P2.2			;清看门狗
	CLR	TR1
	CLR	ET1
	MOV     A,  CISHU_CPU
	JZ      COMM_ERR1                   
	DEC	CISHU_CPU
	LJMP    APPLY_1			
VERIFY_0:
	JB	RB8,	COMM_ERR4		
	SJMP	RECE_3
COMM_ERR1:
	SETB	TONGXUN_CPU_ERR		;与CPU通讯总故障
	SETB	TIME_O_CPU		;与CPU通讯超时
	SJMP	COMM_END
COMM_ERR2:
	SETB	TONGXUN_CPU_ERR		;与CPU通讯总故障
	SETB	FEIFA_CPU		;与CPU通讯非法命令			
COMM_ERR4:
	MOV	R6,	CISHU_CPU
	CJNE	R6,#00H,COMM_ERR40
	SETB	TONGXUN_CPU_ERR		;与CPU通讯总故障
	SETB	JIAOYAN_CPU_ERR		;与CPU通讯校验故障
	SJMP	COMM_END
COMM_ERR40:	
	LJMP	SEND_2		
	LJMP    START                   ;软件抗干扰语句	
APPLY_OVER:
	CLR	P1.4			;总线仲裁完毕,复位/B
	SJMP	COMM_OVER	
;------------------****延时140微秒子程序****-------------	
DELAY_140:		
	PUSH	ACC			;保护现场
	MOV	A,	#28H		;赋计数次数
DELAY1:	DEC	A
	JNZ	DELAY1			;未完继续
	POP	ACC			;恢复现场
	RET
;-----------------****延时100毫秒子程序****--------------	
DELAY_100mS:	;延时计算公式:T=()*12/fosc
	PUSH	ACC			;保护现场
	MOV	A,	#0EEH		;赋计数次数
DELAY2:	LCALL	DELAY_140		;延时140微秒
	LCALL	DELAY_140		;延时140微秒
	LCALL	DELAY_140		;延时140微秒
	DEC	A			
	JNZ	DELAY2			;未完继续
	POP	ACC			;恢复现场
	RET
	LJMP    START                   ;软件抗干扰语句
;---------------****总线发送子程序****-------------
SEND_BUS:		;入口:LONG_S_BUS    MODE17	
	PUSH	PSW			;保护现场
	SETB	P2.1			;禁止接收
	SETB	P2.7			;发送允许
	CLR	ES			;禁止接收中断	
	JB	GUANGBO,SEND_BUS_END	;广播不回发数据
	MOV	R0,	#48H		;送待发送数据首地址
	JNB	MODE17,	SEND_BUS0	;是F17功能吗?
	MOV	R0,	#30H		;功能5/6/15/16/17时从30H开始	
SEND_BUS0:
	SETB	TB8			;TB8=1			
	MOV	SBUF,	@R0		;发送地址
	JNB	TI,	$		;发送未完成等待
	CLR	TI			;清发送完成标志位
	LCALL	DELAY_140		;延时0.5T/38.400KBPS
	DJNZ	LONG_S_BUS,SEND_BUS1
	SJMP	SEND_BUS_END		
SEND_BUS1:
	LCALL	DELAY_140
	INC	R0			;地址加1
	CLR	TB8			;TB8=0
	MOV	SBUF,	@R0		;发送
	JNB	TI,	$		;发送未完等待	
	CLR	TI			;清发送完成标志位
	DJNZ	LONG_S_BUS,SEND_BUS1	;未完继续
SEND_BUS_END:
	CLR	P2.7			;禁止发送
	CLR	P2.1			;允许接收
	CLR	MODE17			;清F17功能标志
	SETB	ES			;允许接收中断
	POP	PSW			;恢复现场
	RET				
	LJMP    START                   ;软件抗干扰语句	
;----------------------****CRC校验子程序****-----------------
CRC:	        ;入口(数据首)地址=20H(21H),数据长度=22H
		;23H=低位	24=高位 	
		;22H=待校验数据长度
	PUSH	PSW			;保护现场
	CLR	RS1			;取RAM01区
	SETB	RS0
	MOV	R1,	22H		;取要进行校验的实际数据长度
	MOV	R0,	20H		;送CRC校验数据首地址
	MOV	R7,	#0FFH		;R7为CRC校验寄存器低位
	MOV	R6,	#0FFH		;R6为CRC校验寄存器高位	
CRC0:	MOV	A,	R6		;取高位
	XRL	A,	@R0		;得出index
	INC	R0			;地址指针指向下一位数据	
	MOV	R5,	A		;R5暂存变量
	MOV	DPTR,	#TAB6		;送高位表基址
	MOVC	A,	@A+DPTR		;查表得校验高位数据
	XRL	A,	R7		;异或CRC低位
	MOV	R6,	A		;存高位CRC结果
	MOV	DPTR,	#TAB5		;送低位表基址
	MOV	A,	R5
	MOVC	A,	@A+DPTR		;查表得校验低位数据	
	MOV	R7,	A		;存低位CRC结果		
	DJNZ	R1,	CRC0		;未完继续
	MOV	23H,	R6		;CRC计算结果送出口寄存器(23H--低位)	
	MOV	24H,	R7		;24H存CRC校验高位结果
	POP	PSW			;恢复现场
	RET					
	LJMP    START                   ;软件抗干扰语句					
;---------------------****判断是否溢出子程序****-------------------
OVER_FLOW:	;说明:  本程序只适用于01,02,03,04,15,16功能
	MOV	2FH,	#00H
	MOV	A,	32H
	JNZ	OVER_FLOW1		;地址溢出,转处理
	MOV	DPTR,	#TAB7		;送数据表基址
	MOV	A,	31H		;取功能码
	MOVC	A,@A+DPTR		;查表得数据(=最大地址+1)
	MOV	B,	A		;暂存
	MOV	A,	33H		;地址溢出?
	CLR	C
	SUBB	A,	B
	JNC	OVER_FLOW1		;地址溢出,转处理
	MOV	A,	34H
	JNZ	OVER_FLOW2		;长度溢出,转处理
	MOV	A,	31H		;取功能码
	MOV	DPTR,	#TAB7		;送数据表基址
	MOVC	A,@A+DPTR		;查表得数据(=最大长度+1)
	INC	A
	MOV	B,	A		;暂存
	MOV	A,	35H		;长度溢出?
	JZ	OVER_FLOW2		;数据长度为0?
	ADD	A,	33H
	CLR	C
	SUBB	A,	B
	JNC	OVER_FLOW2		;长度溢出,转处理
	RET
OVER_FLOW1:
	SETB	DIZHI_Z_ERR		;置地址错误(溢出)标志	
	RET
OVER_FLOW2:
	SETB	SHUJU_Z_ERR		;置数据错误(长度溢出)标志
	RET	
	LJMP    START                   ;软件抗干扰语句
;---------------------****T1装载服务子程序****----------------
		;	T1计时时间为T35
T1_MAKE:
	PUSH	ACC			;保护现场
	PUSH	B
	MOV	A,	BOTELU		;取波特率设定值
	ANL	A,	#0FH		;取低位数据---波特率代码
	JB	TONGXUN_ZX,   T1MAKE0	;是与总线通讯吗 ?
	MOV	A,	#08H		;与CPU通讯时波特率为38400BPS
T1MAKE0:MOV	B,	A
	MOV	DPTR,	#TAB2		;送代码表基址
	MOVC	A,	@A+DPTR		;查表取得T1低位重装值
	MOV	TL1,	A		;T1低位装载
	MOV	R6,	A
	MOV	A,	B	
	ADD	A,	#09H		;取得高位代码
	MOVC	A,	@A+DPTR		;查表取得T1高位重装值
	MOV	TH1,	A		;T1高位装载
	MOV	R5,	A
	MOV	DPTR,	#TAB3
	MOV	A,	B
	MOVC	A,	@A+DPTR		;查表取得T35重装值
	MOV	CISHU_T35,A
	POP	B			;恢复现场
	POP	ACC
	RET
	LJMP    START                   ;软件抗干扰语句
;--------------------****定时/计数器2设定子程序****---------------
T2_MAKE:    ;在与执行器未取得联系时,与执行器的通讯波特率为9600BPS							
	CLR	TR2			;停T2
	MOV	T2CON,	#30H		;RCLK=TCLK=1
	MOV	A,	#08H		;与CPU通讯时波特率为38400BPS
	JNB	TONGXUN_ZX,T2_MAKE0	;是与CPU通讯吗 ?
	MOV	A,	BOTELU		;取波特率设定值
	ANL	A,	#0FH		;取低位数据---波特率代码
	MOV	B,	A		;波特率代码有误?
	CLR	C
	SUBB	A,	#09H
	MOV	A,	B
	JNC	T2_MAKE2
T2_MAKE0:
	MOV	B,	A
	MOV	DPTR,	#TAB4		;送代码表基址
	MOVC	A,	@A+DPTR		;查表取得T2低位重装值
	MOV	RCAP2L,	A		;T2低位装载
	MOV	A,	B	
	ADD	A,	#09H		;取得高位代码
	MOVC	A,	@A+DPTR		;查表取得T2高位重装值
	MOV	RCAP2H,	A		;T2高位装载
	SETB	TR2			;启动定时器2
	RET	
T2_MAKE2:				;波特率代码出错处理
        MOV	R0,	#0A7H
        MOV	@R0,	#00H
        INC	R0	
        MOV	@R0,	#00H
        LJMP	START
;***********************中断服务程序区*****************************
		;***////串行接收中断服务子程序////***
SIO_INT:	;*********SM2=0*******,接收总线数据
	PUSH	ACC		;保护现场
	PUSH	PSW
	CLR	RS0		;RAM 02区
	SETB	RS1		
	JNB	RI,SIO_INT_END	;是接收中断?
	CLR	RI
	CLR	ES		;转为查询方式
	CLR	JIESHOU_WAN
	JB	MANG,SIO_INT_E	;忙?
	CLR 	GUANGBO
	MOV	A,	SBUF	;数据暂存	
	MOV	B,	A
	JNZ	SIO_INT_A	;广播?
	SETB	GUANGBO		
	SJMP	SIO_INT_B
SIO_INT_A:
	MOV	R0,	#9DH	;呼叫本卡?
	XRL	A,	@R0
	JNZ 	SIO_INT_END
SIO_INT_B:
	MOV	R0,	#30H	
	MOV	R1,	#00H
	MOV	@R0,	B	;存数据
	LCALL	T1_MAKE
	MOV	R4,	CISHU_T35 
SIO_INT_C:
	INC	R0		;地址加1
	INC	R1		;数据长度加1	
	CLR	T35
	CLR	TR1
	MOV	TH1,	R5	;T1装载
	MOV	TL1,	R6
	MOV	CISHU_T35,R4
	SETB	ET1		;允许T1中断
	SETB	TR1		;启动T1
SIO_INT_D:
	JBC	T35,SIO_INT_OVER
	JNB	RI,	SIO_INT_D
	CLR	RI
	MOV	@R0,	SBUF	;接收数据
	SJMP	SIO_INT_C
SIO_INT_E:				;忙处理
	MOV	R0,	#99H		;送从机总线忙低位地址(=98H\99H,高位在前)		
	MOV	A,	@R0	
	CLR	C
	ADD	A,	#01H		;从机忙次数加1
	MOV	@R0,	A		;存从机忙低位
	DEC	R0
	CLR	A
	ADDC	A,	@R0
	MOV	@R0,	A		;存从机忙高位
	SJMP	SIO_INT_END	
SIO_INT_OVER:	
	SETB	JIESHOU_WAN
	MOV	LONG_R_BUS,R1
SIO_INT_END:
	CLR	T35			;等待下一次中断
	CLR	TR1
	SETB	ES
	POP	PSW			;恢复现场
	POP	ACC
	RETI	
	LJMP    START                   ;软件抗干扰语句	
;-------------****   T1中断服务子程序   ***-----------------	
T1_INT: 
	CLR	TR1			;停计时器1 
	CPL	P2.2			;清看门狗
	DJNZ	CISHU_T35,T1_INT1	;T35计时到了吗 ?
	CLR	ET1			;禁止T1中断
	SETB	T35			;置T35计时到标志			
	RETI
T1_INT1:MOV	TH1,	R5		;T1进行装载
	MOV	TL1,	R6
	SETB	TR1			;启动T1
	RETI				
	LJMP    START                   ;软件抗干扰语句
;-----------------------**** 功能散转表 ****----------------
TAB0:
	LJMP	FUNCTION01		;	功能F01
	LJMP	FUNCTION02		;	功能F02
	LJMP	FUNCTION03		;	功能F03	
	LJMP	FUNCTION04		;	功能F04
	LJMP	FUNCTION05		;	功能F05
	LJMP	FUNCTION06		;	功能F06
	LJMP	FUNCTION07		;	功能F07
	LJMP	FUNCTION08		;	功能F08(CPU支持?)
	LJMP	ERROR			;	ERROR
	LJMP	ERROR			;	ERROR
	LJMP	ERROR			;	ERROR
	LJMP	ERROR			;	ERROR
	LJMP	ERROR			;	ERROR
	LJMP	ERROR			;	ERROR
	LJMP	FUNCTION15		;	功能F15
	LJMP	FUNCTION16		;	功能F16
	LJMP	FUNCTION17		;	功能F17(CPU不支持)	
	LJMP	START			;若程序出错,则复位
;------------****  T1计数用的不同时间常数   ****-----------------
TAB1:	DB      'WRICH RQM MODBUS MODULE ** M1.01'
	;	以下18个子节为T35计数T1重装值,低位重装值	
TAB2:	DB	00H,00H,00H,80H, 40H, 20H, 90H,0C8H, 64H
	DB	04H,19H,19H,8CH,0C6H,0E3H,0F1H,0F8H,0FCH
;-----------------****以下为T35计数次数表****----------------------	
TAB3:	DB	05H,02H,01H,01H, 01H, 01H, 01H, 01H, 01H										
;------------------**** 与回路通讯的波特率 ****--------------------
 	;	以下18个字节为波特率代码-------CPU时钟为11.0592MHz
	    ;	0.11, 0.3, 0.6, 1.2, 2.4, 4.8, 9.6,19.2,38.4-----对应波特率	
TAB4:	DB	0BAH, 80H,0C0H,0E0H, 70H,0B8H,0DCH,0EEH,0F7H  ;T2低位重装值	
	DB	0F3H,0FBH,0FDH,0FEH,0FFH,0FFH,0FFH,0FFH,0FFH  ;T2高位重装值
;------------------****   CRC校验用表  ****------------------------    	
        ;	以下为校验表低位数据
TAB5:	DB	 00H,0C0H,0C1H, 01H,0C3H, 03H, 02H,0C2H,0C6H, 06H, 07H,0C7H, 05H,0C5H,0C4H
	DB	 04H,0CCH, 0CH, 0DH,0CDH, 0FH,0CFH,0CEH, 0EH, 0AH,0CAH,0CBH, 0BH,0C9H, 09H
	DB	 08H,0C8H,0D8H, 18H, 19H,0D9H, 1BH,0DBH,0DAH, 1AH, 1EH,0DEH,0DFH, 1FH,0DDH
	DB	 1DH, 1CH,0DCH, 14H,0D4H,0D5H, 15H,0D7H, 17H, 16H,0D6H,0D2H, 12H, 13H,0D3H
	DB	 11H,0D1H,0D0H, 10H,0F0H, 30H, 31H,0F1H, 33H,0F3H,0F2H, 32H, 36H,0F6H,0F7H
	DB	 37H,0F5H, 35H, 34H,0F4H, 3CH,0FCH,0FDH, 3DH,0FFH, 3FH, 3EH,0FEH,0FAH, 3AH
	DB	 3BH,0FBH, 39H,0F9H,0F8H, 38H, 28H,0E8H,0E9H, 29H,0EBH, 2BH, 2AH,0EAH,0EEH
	DB	 2EH, 2FH,0EFH, 2DH,0EDH,0ECH, 2CH,0E4H, 24H, 25H,0E5H, 27H,0E7H,0E6H, 26H
	DB	 22H,0E2H,0E3H, 23H,0E1H, 21H, 20H,0E0H,0A0H, 60H, 61H,0A1H, 63H,0A3H,0A2H
	DB	 62H, 66H,0A6H,0A7H, 67H,0A5H, 65H, 64H,0A4H, 6CH,0ACH,0ADH, 6DH,0AFH, 6FH
	DB	 6EH,0AEH,0AAH, 6AH, 6BH,0ABH, 69H,0A9H,0A8H, 68H, 78H,0B8H,0B9H, 79H,0BBH
	DB	 7BH, 7AH,0BAH,0BEH, 7EH, 7FH,0BFH, 7DH,0BDH,0BCH, 7CH,0B4H, 74H, 75H,0B5H
	DB	 77H,0B7H,0B6H, 76H, 72H,0B2H,0B3H, 73H,0B1H, 71H, 70H,0B0H, 50H,090H,091H
	DB	 51H,093H, 53H, 52H,092H, 96H, 56H, 57H,097H, 55H,095H,094H, 54H,09CH, 5CH
	DB	 5DH,09DH, 5FH,09FH,09EH, 5EH, 5AH, 9AH,09BH, 5BH,099H, 59H, 58H,098H, 88H
	DB	 48H, 49H, 89H, 4BH,08BH, 8AH, 4AH, 4EH, 8EH, 8FH, 4FH, 8DH, 4DH, 4CH, 8CH
	DB	 44H, 84H, 85H, 45H, 87H, 47H, 46H, 86H, 82H, 42H, 43H,83H,41H,81H,80H,40H
                ;	CRC校验表高位
TAB6:	DB	 00H,0C1H, 81H, 40H, 01H,0C0H, 80H, 41H, 01H,0C0H, 80H, 41H, 00H,0C1H, 81H
	DB	 40H, 01H,0C0H, 80H, 41H, 00H,0C1H, 81H, 40H, 00H,0C1H, 81H, 40H, 01H,0C0H
	DB	 80H, 41H, 01H,0C0H, 80H, 41H, 00H,0C1H, 81H, 40H, 00H,0C1H, 81H, 40H, 01H
	DB	0C0H, 80H, 41H, 00H,0C1H, 81H, 40H, 01H,0C0H, 80H, 41H, 01H,0C0H, 80H, 41H	
	DB	 00H,0C1H, 81H, 40H, 01H,0C0H, 80H, 41H, 00H,0C1H, 81H, 40H, 00H,0C1H, 81H
	DB	 40H, 01H,0C0H, 80H, 41H, 00H,0C1H, 81H, 40H, 01H,0C0H, 80H, 41H, 01H,0C0H
	DB	 80H, 41H, 00H,0C1H, 81H, 40H, 00H,0C1H, 81H, 40H, 01H,0C0H, 80H, 41H, 01H
	DB	0C0H, 80H, 41H, 00H,0C1H, 81H, 40H, 01H,0C0H, 80H, 41H, 00H,0C1H, 81H, 40H	
	DB	 00H,0C1H, 81H, 40H, 01H,0C0H, 80H, 41H, 01H,0C0H, 80H, 41H, 00H,0C1H, 81H
	DB	 40H, 00H,0C1H, 81H, 40H, 01H,0C0H, 80H, 41H, 00H,0C1H, 81H, 40H, 01H,0C0H
	DB	 80H, 41H, 01H,0C0H, 80H, 41H, 00H,0C1H, 81H, 40H, 00H,0C1H, 81H, 40H, 01H
	DB	0C0H, 80H, 41H, 01H,0C0H, 80H, 41H, 00H,0C1H, 81H, 40H, 01H,0C0H, 80H, 41H	
	DB	 00H,0C1H, 81H, 40H, 00H,0C1H, 81H, 40H, 01H,0C0H, 80H, 41H, 00H,0C1H, 81H
	DB	 40H, 01H,0C0H, 80H, 41H, 01H,0C0H, 80H, 41H, 00H,0C1H, 81H, 40H, 01H,0C0H
	DB	 80H, 41H, 00H,0C1H, 81H, 40H, 00H,0C1H, 81H, 40H, 01H,0C0H, 80H, 41H, 01H
	DB	0C0H, 80H, 41H, 00H,0C1H, 81H, 40H, 00H,0C1H, 81H, 40H, 01H,0C0H, 80H, 41H	
	DB      00H,0C1H, 81H, 40H, 01H,0C0H, 80H, 41H, 01H,0C0H, 80H,41H,00H,0C1H,81H,40H
;--------------****  总线末地址溢出判断依据(总线最高地址+1)表  ****-----------------	
TAB7:			
	;功能码: 00  01  02  03  04  05  06  07   08  09  10  11  12  13  14  15  16
	DB	 00H,08H,18H,05H,02H,08H,05H,00H,00H,00H,00H,00H,00H,00H,00H,08H,05H
	LJMP	START	;若程序出错,则复位
	END

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?