⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 startup.a51

📁 上位机与多台下位机的单片机多机通信。 做好了通信框架
💻 A51
字号:
/*********************************************
发送缓冲区信息数据结构:
byte	SBB			;send buffer begin(value:68h)(ram:30h)
byte	SBTA			;send buffer target address(31h)
byte	SBCMD			;send buffer command(32h)
byte	SBDL			;sned buffer data length(33h)
bytes	SBDS			;send buffer datas(ram:34h-3ch)
byte	SBS			;send buffer sum(3dh)
byte	SBE			;send buffer end(value:eeh)(ram:3eh)

接收缓冲区类似,但地址改为40H-4fH
接收状态字 RStatus控制接收到的信息存放位置
Rstatus 00H 初始态,等待接收开始符
Rstatus	01H 等待接收地址
Rstatus	02H 等待接收命令字
Rstatus	03H 等待接收数据长
Rstatus 04H 等待接收数据
Rstatus	05H 等待接收校验和
Rstatus	06H 等待接收结束符

command:		(SBCMD RBCMD)
	value:0fh	means:地址为0ffh广播时候重置所有下位机的sm2为1
	value:80h	means:地址匹配命令 只有下位机地址与数据帧地址一致时候才清该下位机的sm2 
			      如果有匹配的下位机,则返回一个command为01h 数据:00h(该下位机无数据需要发送)
								      	    01h(该下位机有数据需要发送)
	value:81h	means:允许下位机数据发送信号
	value:01h	means:command为01H代表该帧为响应帧
	value:82h	means:command为82h代表该帧为数据帧

addr	下位机地址
 
************变量初始化**************************/
	SBB	equ	30h		;帧头 总为68h
	SBTA	equ	31h		;目标地址  
	SBCMD	equ	32h		;command
	SBDL	equ	33h		;9=>sbdl>=1 34h-3ch存放发送的数据,不在长度范围内将导致数据发送失败
	SBS	equ	3dh		;校验和
	SBE	equ	3eh		;帧尾 总为 55h
	addr	equ	3fh		;数据发送目标地址


	RBB	equ	40h		;类似发送缓冲区
	RBTA	equ	41h
	RBCMD	equ	42h
	RBDL	equ	43h		;9=>rbdl>=1 44h-4ch存放接收的数据
	RBS	equ	4dh
	RBE	equ	4eh
	Rstatus	equ	4fh		;接收状态字 代表目前接收的字节归属
	RBRDY	bit	00h		;接收完成标志
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	org	00h
	ljmp	start
	org	0bh
	ljmp	T_0			;T0用于判断下位机响应是否超时
	org	23h
	ljmp	recieve
	org	30h
    start:
    	mov	sp,#6fh
    	anl	pcon,#7fh		;设置smod=0
	mov	scon,#90h		;串行方式2
	clr	sm2			;不论收到的rb8值是多少,都可以接收到数据
	setb	ea			;开总中断
	setb	es			;开串口中断
	setb	ps			;串口中断优先
	mov	tmod,#01h		;定时器方式1
	setb	et0			;开定时器中断
	clr	tr0			;暂时不计时

	mov	r0,#0fh			;重置所有下位机
	mov	r1,#1h			;数据长为1 (无用的数据,兼容用)
	mov	34h,#00h	;任意值
	mov	addr,#0ffh	;广播地址
	setb	TB8		;所有mcu都可以接收到此信息
	lcall	write_SB	
	lcall	Send		;发送
	
	mov	addr,#00h
    next_mcu:
	lcall	next_addr	;取下一下位机地址
	mov	r0,#80h		;地址匹配命令
	mov	r1,#1h		;
	mov	34h,#00h	;任意值
	setb	TB8		;所有下位机都可以接收到此信息
	lcall	write_SB
	lcall	Send		;发送

	setb	tr0		;计时开始
	jnb	RBRDY,$
	clr	tr0
	mov	th0,#0
	mov	tl0,#0
	clr	RBRDY

	mov	a,#01h
	cjne	a,RBCMD,next_mcu	;不是slave机响应信息则说明该机不存在,测试下一地址
	mov	a,#01h		
	cjne	a,44h,next_mcu		;接收到的数据不是01h说明slave机没有需要传送的数据,测试下一mcu
	
    permit:
	mov	r0,#81h			;允许下位机发送数据指令
	mov	r1,#1h
	mov	34h,#00h
	clr	TB8			;只有符合地址为addr的机器才可以接收到此信息
	lcall	write_SB
	lcall	Send

	setb	tr0
	jnb	RBRDY,$			;等待slave mcu传送数据
	clr	tr0
	mov	th0,#0
	mov	tl0,#0
	clr	RBRDY

	mov	a,#82h
	cjne	a,RBCMD,permit		;不是slave mcu传来的数据信息,说明数据传送出错,重新发送允许传送信号
	lcall	recieve_ok		;通知slave mcu 数据接收成功

	lcall	do			;处理接收到的数据
	lcall	Clear_recieveBuf	;清空接收缓冲区
	ljmp	next_mcu		;处理下一slave mcu

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
T_0:
	setb	RBRDY
	reti
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
recieve_ok:
	mov	r0,#01h			;响应帧
	mov	r1,#1h
	mov	34h,#00h
	clr	TB8
	lcall	write_SB
	lcall	Send
	ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
do:
	mov	r0,#44h
	mov	r1,RBDL
    do_loop:
	mov	p2,@r0
	setb	rs0		;避免wait1S程序与do程序 r0 r1互相干扰
	lcall	wait1S
	clr	rs0
	inc	r0
	djnz	r1,do_loop
	lcall	Clear_recieveBuf
	ret

	
next_addr:			;取下一下位机地址 子程序  支持16台地址为1-10h的下位机
	inc	addr
	mov	a,#10h
	clr	c
	subb	a,addr
	jnc	no_bound
	mov	addr,#01h
    no_bound:
    	ret







write_SB:				;写入发送缓冲区
	mov	SBB,#68h
	mov	SBTA,addr
	mov	SBCMD,r0
	mov	SBDL,r1
	mov	a,SBCMD
	add	a,SBDL
	mov	r0,#34h
    add_datas:
	add	a,@r0
	inc	r0
	djnz	r1,add_datas
	mov	SBS,a
	mov	SBE,#55h
	ret



	


	


recieve:		;数据接收



	jbc	TI,is_Send		
	clr	RI
	mov	a,#00h
	cjne	a,Rstatus,ignore_begin
	mov	RBB,sbuf
	mov	a,#68h
	cjne	a,RBB,garbage_info
	mov	Rstatus,#01h
	reti
    garbage_info:
    	mov	Rstatus,#00h
	reti
    is_Send:
    	reti
    ignore_begin:
    	mov	a,#01H
	cjne	a,Rstatus,ignore_addr
	mov	RBTA,sbuf
	mov	Rstatus,#02h
	reti
    ignore_addr:
    	mov	a,#02h
	cjne	a,Rstatus,ignore_comm
	mov	RBCMD,sbuf
	mov	Rstatus,#03h
	mov	RBS,RBCMD
	reti
    ignore_comm:
    	mov	a,#03h
	cjne	a,Rstatus,ignore_DLen
	mov	RBDL,sbuf
	mov	r1,RBDL
	mov	r0,#44h
	mov	a,RBS
	add	a,RBDL
	mov	RBS,a
	mov	Rstatus,#04h
	reti
    ignore_DLen:
    	mov	a,#04h
	cjne	a,Rstatus,ignore_Data
	mov	@r0,sbuf
	mov	a,RBS
	add	a,@r0
	mov	RBS,a
	inc	r0
	djnz	r1,continueRD
	mov	Rstatus,#05h
    continueRD:
	reti


    ignore_Data:
    	mov	a,#05h
	cjne	a,Rstatus,ignore_Sum
	mov	a,sbuf
	cjne	a,RBS,recieve_err
	mov	Rstatus,#06h
	reti

    ignore_Sum:
    	mov	a,#06h
	cjne	a,Rstatus,recieve_err
	mov	a,sbuf
	cjne	a,#55h,recieve_err
	mov	RBE,#55h
	mov	Rstatus,#00h
	lcall	recieve_success
	reti

    recieve_err:
    	mov	Rstatus,#00h
	lcall	recieve_error


	reti

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
recieve_success:
	setb	RBRDY
	ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
recieve_error:
	;接收失败  扩展用
	ret





Send:			;数据发送

	mov	sbuf,SBB
	lcall	wait1ms
	mov	sbuf,SBTA
	lcall	wait1ms
	mov	sbuf,SBCMD
	lcall	wait1ms
	mov	sbuf,SBDL
	lcall	wait1ms
	mov	r1,SBDL
	mov	r0,#34h
    send_datas:
	mov	sbuf,@r0
	setb	rs0
	lcall	wait1ms
	clr	rs0
	inc	r0
	djnz	r1,send_datas
    send_sum:
    	mov	sbuf,SBS
	lcall	wait1ms
	mov	sbuf,SBE
	lcall	wait1ms


	ret
/**************************************/


Clear_SendBuf:		;清发送缓冲区



	mov	r0,#30h
	mov	r1,#10h
    clear_SB:
	mov	@r0,#0h
	inc	r0
	djnz	r1,clear_SB



	ret
/******************************************/

Clear_RecieveBuf:	;清接收缓冲区


	mov	r0,#40h
	mov	r1,#10h
    clear_RB:
    	mov	@r0,#0h
	inc	r0
	djnz	r1,clear_RB


	ret

/**************************************/

wait1S:

	mov	r0,#250d
    WT1SL1:
	mov	r1,#200d
    WT1SL2:
	mov	b,#10d
	djnz	b,$
	djnz	r1,WT1SL2
	djnz	r0,WT1SL1

	ret


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
	
wait1ms:
	
	mov	r0,#25d
    w1msL1:
	mov	b,#20d
	djnz	b,$
	djnz	r0,w1msL1

	ret
/**********************************************/

	end
	

	

⌨️ 快捷键说明

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