51单片机多机通信协议Word文件下载.docx
《51单片机多机通信协议Word文件下载.docx》由会员分享,可在线阅读,更多相关《51单片机多机通信协议Word文件下载.docx(16页珍藏版)》请在冰豆网上搜索。
0Xf1//握手后的命令字,从机到主机
#defineM_SOK
0Xf2//主到从准备完成,从机发送的反馈信息
#defineS_MOK0xf3//从到主准备完成,主机发送的反馈信息
#defineSTOP0xf4//主机到从机发送结束
#defineERROR0xf5//错误
#defineResponse0xf6//应答信号
#defineCONTINUE0xf7//接受数据之后给对方发送的反馈,请求继续
#defineOK0xf8
//--------------------------------------------------
//数据定义
ucharDATA[20]={0};
//从机返回的状态值
ucharCMD[20]={0x44,0x44,0x44,0x55,0x55,0x55,0x47,0x45,0x65,0x35,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,};
//主机给从机发送的命令
ucharstate=0;
//状态值,进行中断判断
ucharAddress;
//呼叫从机地址
uchartemp=0;
//SBUF缓存
uchar*Position=0;
//数据指针,指定数据更新的位置
//---------------------------------------------
//串口1初始化,用于和从机通讯
voidUart1_Init(void)//9600bps@11.0592MHz
{
PCON&
=0x7F;
//波特率不倍速
SCON=0xD0;
//9位数据,可变波特率
AUXR|=0x40;
//定时器1时钟为Fosc,即1T
AUXR&
=0xFE;
//串口1选择定时器1为波特率发生器
TMOD&
=0x0F;
//清除定时器1模式位
TMOD|=0x20;
//设定定时器1为8位自动重装方式
TL1=0xDC;
//设定定时初值
TH1=0xDC;
//设定定时器重装值
ET1=0;
//禁止定时器1中断
TR1=1;
//启动定时器1
EA=1;
//总中断启动
SM2=0;
ES=1;
}
//------------------------------------------
//查询法发送一个数据,TB8=0;
voidSendByte(uchardate)
//EN_DATASEND;
//TB8=0;
SBUF=date;
while(!
TI);
TI=0;
//-----------------------------------
//寻址从机
voidSearch(ucharADD)
//EN_ADDSEND;
SBUF=ADD;
//主机向从机发送命令
//因为主机为控制端,为便于控制从机,所以选择用查询法而不选用中断
voidM_S_Protocol(ucharadd,uchar*m)//三个参量分别为从机地址,命令的字节数,命令的位置
state=1;
Position=m;
Search(add);
//主机接收从机状态,同样也为查询法不用中断
voidS_M_Protocol(ucharadd,uchar*m)//三个参量分别为从机地址,命令的字节数,命令的位置
state=4;
voidM_S_Send(ucharadd,uchar*m)//主机到从机整个过程
M_S_Protocol(add,m);
while(state);
ES=0;
voidS_M_Send(ucharadd,uchar*m)//从机到主机的整个过程
S_M_Protocol(add,m);
//-----------------------------
//主函数,主机主函数主要用于与GPRS和从机之间做桥接
voidmain()
Uart1_Init();
while
(1)
S_M_Send(0x01,CMD);
voidUART1()interrupt4
RI=0;
//清除中断标志
temp=SBUF;
if(state)//处于传输状态
switch(state)
//-----------------------------------------------------------------
//---------------------M_S部分--------------------------------
case1:
if(temp==Response)//寻址成功
SendByte(M_S);
//发送M_S命令
state=2;
//转换状态
break;
/*else//寻址不成功,通信结束,转换为非通信状态
state=0;
SendByte(STOP);
//发送通信停止命令
}*/
case2:
if(temp==M_SOK)//M_S得到回应
state=3;
SendByte(*Position);
//发送第一字节
case3:
if(temp==CONTINUE)//从机继续要求数据
if(Position-CMD
Position++;
else//数组溢出,停止通信
//-----------------------------------------------------------------------
//----------------接收部分---------------------------------------------
case4:
if(temp==Response)//呼叫从机得到回应
state=5;
SendByte(S_M);
//发送从机到主机命令
/*else//无回应,停止此次传输
}*/
else
case5:
if(temp==OK)//发送S_M得到回应
state=6;
SendByte(S_MOK);
//准备完成
/*else//无回应,停止通信
//发送停止命令
case6:
*Position=temp;
//接收数据
SendByte(CONTINUE);
//要求从机继续发送数据
else//超出数组,停止通信
default:
//从机程序,从机接收信息,所以用中断法会更便于反馈和执行命令
//-------------------------------
sbitkey=P3^7;
ucharDATA[20]={0x12,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,};
ucharCMD[20]={0};
//主机给从机发送的命令
ucharADDR;
//STC12具有7字节全球唯一ID,将7位的ID加和作为从机地址.(有可能从机地址会重复)
ucharSet_Add()
uchar*p;
uchari;
ucharaddr=0;
p=0xf1;
//上电后唯一ID起始地址
for(i=0;
i
addr+=*p;
return(addr);
voidAll_Init()
ADDR=Set_Add();
//打开总中断
//打开串口中断
//查询法发送一个字
//关断串口中断
EN_DATASEND;
//打开串口中断
//主函数,可以用大循环只执行全局数组命令,而中断接收并修改全局命令命令
All_Init();
Position=DATA;
//SendCmd(DATA);
while
(1);
//串口1中断服务程序,用state进行状态判断处理
//读取数据
if(state)
switch(state)
if(temp==M_S)//主机发送到从机,从机准备好接收数据
SendByte(M_SOK);
//发送应答
//更换状态
elseif(temp==S_M)//主机要求从机发数据
SendByte(OK);
//回应主机
elseif(temp==STOP)
SM2=1;
if(temp==STOP)//停止符判定,回到待机状态
DATA[1]=temp;
//接收数据后回应
//SendByte(DATA[1]);
//串口测试用的
switch(temp)
caseS_MOK:
//主机准备完成
caseCONTINUE:
caseSTOP:
//停止命令,返回待机状态
if(RB8==1)//判断寻址
if(temp==ADDR)//进行地址判断
//从机响应,清除SM2
SendByte(Response);
else//用于主机呼叫从机之后,错误的呼叫其他从机,则使该机处于待机状态