本人初学单片机,想知道51单片机多机通信,需要遵守哪些协议,是主机发送一次数据,从机应答,返回一次。以此循环?以下是我参考书上写的程序;但测试时主机能发送完地址,从机响应后,返回来,主机便无反应。
请大神帮忙知道下。
/*************主机*******************/
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define SLAVE 0x02 //定义从机的地址
#define BN 16
uchar rbuf[16];
uchar code tbuf[16] = {"1234567891234567"};//传输
void err()//复位信号
{
SBUF = 0xff;
while(TI != 1)
TI=0;
}
uchar master(uchar addr,uchar command
{
uchar aa,i,p;
while(1)
{
SBUF = SLAVE ; //主机发送从机地址 (主机发送地址后,从机开始检验,并返回给主机自己的地址再次确认)
while(!TI);
TI=0;
while(!RI)
RI =0;
/**/ P1 = 0xfe;// 主机收到从机的回信 /*********/
if(SBUF != addr
{
err(); //主机发送复位信号
}
else
{
//主机收到从机应答地址后,确认地址是否相符,不符合,则发复位信号(TB8=1);符合则TB8=0,主机开始发送数据
TB8=0; //清地址标志
SBUF = command
while(!TI);
TI=0;
/**/ P1 = 0xfd; // 主机发送命令判断 /***过不来***/
while(!RI); //主机等待接收
RI =0;
aa = SBUF;
if(aa & 0x80 == 0x80) // 若命令未被接收,发复位信号(TB8 = 1)
{
TB8 =1;
err();
}
else
{
// if(command == 0x01) //主机命令从机接收命令
{
if((aa & 0x01)== 0x01)
{
/**/ P1 = 0xfc; //从机返回命令
do
{
p=0; //清校验和
for(i=0;i<BN;i++)
{
SBUF=tbuf[i]
p += tbuf[i] ;//计算校验和
while(!TI);
TI=0;
}
SBUF = p ; //发送校验和 判断是否完全接收
while(!TI);
TI=0;
while(!RI)
RI =0;
}while(SBUF != 0); //接收不正确则重新发送
/**/ P1 = 0xf7; // 从机接收完成
TB8 = 1; //发地址帧(置地址标志)
return(0); //结束函数
}
else
{
if((aa&0x02) == 0x02) //主机接受命令,从机准备好发送
{
while(1)
{
p=0; //清校验和
for(i=0;i<BN;i++)
{
while(!RI)
RI =0;
rbuf[i]=SBUF
p += rbuf[i] ;//计算校验和
}
while(!RI)
RI =0;
if(SBUF == p) //发送校验和 判断是否完全接收
{
SBUF =0X00; //校验和相同 发00
P1 = 0xfc;
while(!TI);
TI=0;
break;
}
else
{
SBUF = 0xff; //校验和不同发0FF 重新接收
while(!TI);
TI=0;
}
}
TB8 = 1; //发地址帧(置地址标志)
return(0); //结束函数
}
}
}
}
}
}
}
void main()
{
TMOD = 0x20; //定时器 T1 方式2
TL1 = 0xfd; //9600
TH1 = 0xfd;
PCON = 0x00; //电源寄存器 波特率正常
TR1 = 1; //打开定时器
SCON =0xf8; //TB8=1;串口工作方式3 SM2=1
while(1)
{
master(SLAVE,0x01); //01 从机接收数据
master(SLAVE,0x02);
}
}
/**************从机*****************/
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define SLAVE 0x02 //定义从机的地址
#define BN 16 //一次传输
uchar rbuf[16]; //接收数组变量
uchar tbuf[6]= {"i konw"}; //接收数组变量
bit tready = 0; //从机发送准备位 1为准备好
bit rready = 0; //从机接收准备位 1为准备好
void str(); //发送数据函数
void sre(); //接收数据函数
bit TR_flag = 0;
bit RE_flag = 0;
void main()
{
TMOD =0x20;
TL1 =0xfd;
TH1 =0xfd;
PCON = 0x00;
TR1 =1;
SCON = 0xf0 ; //串口3 SM2 = 1;
ES = 1;
EA = 1;
while(1)
{
tready= 1;
rready = 1; //假定准备好接收和发送
if(RE_flag == 1)
{
P1 = 0x55; //1 3 5 7
}
if(TR_flag == 1)
{
P1 = 0xaa; // 2 4 6 8
}
}
}
/*从机以中断方式控制和主机的通信*/
void ser() interrupt 4
{
uchar a ;
P1 = 0xfe;//*// ///从机收到主机指令
RI=0;
ES=0;
if(SBUF != SLAVE)
{
ES = 1;
goto reti;
}
SM2 = 0
SBUF = SLAVE; //再次向主机发送本地址
while(!TI);
TI=0;
P1 = 0xfd; //从机确认
while(!RI);
RI=0;
if(RB8 == 1)
{
SM2 = 1;
ES=1;
goto reti;
} // /*复位信号,回复监听*/
a = SBUF; //接收主机的命令 command
if(a == 0x01
{
P1 = 0xfc; //判断是否收到主机命令
if(rready == 1)
SBUF =0x01;
else
SBUF = 0x00;
while(!TI);
TI = 0;
while(!RI); //
RI=0;
if(RB8 == 1) //随时准备接收新的地址
{
SM2 = 1;
ES = 1;
goto reti;//* 定义一个标签, 然后告诉你的
} //试着删除,可加上检验
sre(); //接收数据
}
else
{
if( a == 0x02) //从机向主机发送数据
{
if(tready == 1)//从机发送状态准备好
SBUF =0x02;
else
SBUF = 0x00;
while(!TI);
TI = 0;
/* while(!RI);
RI=0; */
if(RB8 == 1) //随时准备接收新的地址
{
SM2 = 1;
ES = 1;
goto reti;
} // */ //lingshan kejiashang jianyan
str(); //发送数据
}
else
{
SBUF = 0x80 ; /*命令非法*/
while(!TI);
TI = 0;
SM2 = 1; //恢复监听
ES = 1;
}
}
}
void str() //发送数据
{
uchar p, i;
tready =0;
do
{
p=0;
for(i=0;i<BN;i++)
{
SBUF=tbuf[i]
p += tbuf[i] ;//计算校验和
while(!TI);
TI=0;
/* while(!RI);
RI=0;*/
}
SBUF = p ; //发送校验和 判断是否完全接收
while(!TI);
TI=0;
while(!RI)
RI =0;
}while(SBUF != 0);
TR_flag = 1;//发送完成
SM2 = 1;
ES = 1;
}
void sre() //接收数据
{
uchar p , i ;
rready =0; //////*////
while(1)
{
p=0; //清校验和
for(i=0;i<BN;i++)
{
while(!RI) //主机等待接收
RI =0;
rbuf[i]=SBUF
p += rbuf[i] ;//计算校验和
}
while(!RI) //从机等待接收主机的 返回值 jiaoyanhe
RI =0;
if(SBUF == p) //发送校验和 判断是否完全接收
{
SBUF =0X00; //校验和相同 发00
RE_flag = 1;
break;
}
else
{
SBUF = 0xff; //校验和不同发0FF 重新接收
while(!TI);
TI=0;
}
}
SM2 = 1;
ES = 1;
}
|