单片机多机通信(课程设计)[1]
- 格式:docx
- 大小:26.79 KB
- 文档页数:15
一﹑数据通信协议
1.帧格式:
总字节数 + 命令 + 地址 + 内容 + 校验
2.帧格式说明:
总字节数:4 位
命令:4 位
地址:1 字节
校验:1 字节
内容:实际传送的数据,最大为13字节
3.总字节数说明:总字节数4位,一帧数据最大16个字节,最小3个字节
4.命令格式说明:
0000:寻址命令,此时地址表示从机的ID
0001:应答寻址命令
0010:主机向从机写数据命令
0011:主机向从机读数据命令
0100:从机应答主机的读/写命令
此时是片内寻址命令。地址表示从机内存的起始地址,主机读/写数据的起始地址,地址的增长方向由主机决定,寻址范围:0
~ 255
0101:从机向主机写数据命令
0110:从机向主机读数据命令
0111:主机响应从机读/写
此时是片内寻址命令。地址表示主机内存的起始地址,从机读/写数的起始地址,地址的增长方向由从机决定,寻址范围:0 ~
255
1000:
1001:
1010:
1011:
1100:
1101:
此时是片外寻址命令,地址增为2个字节,寻址范围:0 ~ 64K
此命令是未开发命令
1110:帧错误 1111:通信结束命令
5.地址格式说明:
当片内寻址命令时,地址是一个字节,寻址片内范围:0 ~ 255
当片外寻址命令时,地址是两个字节,寻址范围:0 ~ 64K
6.内容格式说明:
是传输的数据,总大小有帧大小以及命令格式决定
7.校验格式说明:
校验是存储帧中数字1的个数
二、主机通信程序流程图
三、从机通信程序流程图 N Y Y N Y N N Y 开始
主机初始化
置M为计数标志
M = 0?
发送地址帧,M = M-1
收到从机应答帧
解析应答帧
帧校验正确?
重设M的值
M = 0 ?
发送数据帧M = M-1 通信失败
通信失败 N
Y Y N
解析应答帧
解析应答帧
帧校验正确? 收到应答帧 等待从机应答帧
返回 通信结束
N
Y N
Y Y N
Y
N Y N Y N Y N 从机初始化
等待主机广播
收到地址帧
解析地址帧
校验正确?
地址匹配?
回复应答帧
值SM2 = 0
置M为计数器
M = 0 ?
接受一帧数据 收到一帧数据
解析帧数据
校验正确?
处理接受的一帧数据 是数据帧?
重置M的值
通信失败 结束帧
准备接受下一帧
四、主机通信功能模块
1、主机初始化模块
设置缓冲区16个字节(既是发送,又是接收缓冲区)
设置计数值M
设置堆栈指针
2、帧设置模块
设置帧的通信方式(总字节数、命令、地址、内容、校验)
计算校验方式即设置校验字节
3、接受帧模块
送数据到指定的缓冲区
4、发送帧模块
设置发送缓冲区
5、解析帧模块
解析帧大小
解析帧命令
解析地址
五、从机通信功能模块
1、主机初始化模块
设置缓冲区16个字节(既是发送,又是接收缓冲区)
设置计数值M
设置堆栈指针
2、帧设置模块
设置帧的通信方式(总字节数、命令、地址、内容、校验)
计算校验方式即设置校验字节
3、接受帧模块
设置接收缓冲区
4、发送帧模块
根据解析格式发送数据
5、解析帧模块
解析帧大小
解析帧命令
解析地址
/*
多机通信中的主机通信程序
将以地址04H开始的数据发送到从机缓冲区中
*/
org 0000h
ljmp start
org 0024h ;0014h~0023h,16字节为数据缓冲区
start:
mov sp,#03h ;0004h~0013h为堆栈区
mov r2,#6 ;计数值N
mov 07h,#255
clr es ;关闭串口中断
sloop1:call set_frame
mov a,r2
jz error
call send_frame
dec r2
call receive_frame
mov a,07h
jz sloop1 ;没有收到应答帧
call analy_frame ;有收到应答帧
cjne r6,#01h,sloop1 ;没有收到从机地址应答帧
mov r2,#6 ;重设N的值
sloop2:call send_frame ;发送数据帧
mov a,r2
jz error
dec r2
call receive_frame
mov a,07h
jz sloop2 ;没有收到应答帧
call analy_frame ;有收到应答帧
cjne r6,#04h,error;没有收到数据应答帧,失败
jmp mreturn
error:
sjmp $
mreturn:
ljmp start
/*
函数名称:set_frame
入口参数:r0(帧缓冲区首址)、r1(帧数据区首址)
r7(帧大小)、r6(帧命令)
r5(地址)、r4(校验)、r3(帧数据大小)
出口参数:r0(帧缓冲区首址)、r1(帧数据区首址)
r7(帧大小)、r6(帧命令)
r5(地址)、r4(校验)、r3(帧数据大小)
功能:设置帧
*/
set_frame:
mov r0,#14h
mov a,r7 ;设置帧的大小
swap a
mov @r0,a
mov a,r6 ;设置帧命令
orl a,@r0
mov @r0,a
inc r0
mov a,r5
mov @r0,a ;设置地址(从机地址或内存地址)
cjne r3,#0,sloop
jmp sreturn
sloop:
inc r0
mov a,@r1
mov @r0,a
djnz r3,sloop
sreturn:
call check_frame ;此处应该增加一个校验函数
ret
/*
函数名称:send_frame
入口参数:r0(帧缓冲区首址)、
r7(帧大小)、r3(帧数据大小)
出口参数:无
功能:发送帧
*/
send_frame:
loop2:
mov a,@r0
mov sbuf,a
jnb ti,$
inc r0
djnz r7,loop2
clr ti
ret
/*
函数名称:receive
入口参数:r0(帧缓冲区首址)、07h(表示接受时限)
07h = 0表示主机等待超时,接收失败
出口参数:r0(帧缓冲区首址)、07h
函数功能:*/
receive_frame:
wait:
jb ri,rec
djnz 07h,wait
jmp rreturn
rec:
mov a,sbuf
mov @r0,a
swap a ;计算接收帧的大小
anl a,#0eh
mov r7,a
clr ri
loop3: ;接收帧的数据
jnb ri,$
inc r0
mov @r0,sbuf
djnz r7,loop3
call analy_frame
rreturn:
ret
/*
函数名称:check_frame
出口参数:r0(帧缓冲区首址)
入口参数:r0(帧缓冲区首址)
r4(校验)
功能:帧校验函数,累加帧中1个数
*/
check_frame:
mov r4,#00h
mov a,@r0
anl a,#0f0h
swap a
mov r7,a
mov a,#01h
check: ;累加帧中1的个数
anl a,@r0
jz cloop
inc r4
cloop:
rl a
djnz r7,check