本人初學單片機,想知道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;
}
|