51单片机多机通信协议.docx
《51单片机多机通信协议.docx》由会员分享,可在线阅读,更多相关《51单片机多机通信协议.docx(16页珍藏版)》请在冰豆网上搜索。
51单片机多机通信协议
51单片机多机通信协议
做自己以前没做过的东西,总会有各种踌躇,害怕做不出来,其实要是真的开始去做了,问题就解决大半了。
在家没网,就开始写了, 熬了两夜,加一个半天,总算是完成了通信协议,经调试,可以正常工作。
如果有孩子也要做这个,可以参考一下哈!
别的不多说,贴代码。
//-------------------------------------------------
//主机程序,主机座控制,用中断法
//-----------------------------------------------
#include"basic.h"
//---------------------------------------------------
//宏定义
#defineEN_ADDSEND TB8=1;//发送寻址,搜寻从机
#defineEN_DATASENDTB8=0;//发送数据
#defineM_S 0Xf0//握手后的命令字,主机到从机
#defineS_M 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;
TB8=1;
SBUF=date;
while(!
TI);
TI=0;
}
//-----------------------------------
//寻址从机
voidSearch(ucharADD)
{
//EN_ADDSEND;
TB8=1;
SBUF=ADD;
while(!
TI);
TI=0;
}
//主机向从机发送命令 //因为主机为控制端,为便于控制从机,所以选择用查询法而不选用中断
voidM_S_Protocol(ucharadd,uchar*m)//三个参量分别为从机地址,命令的字节数,命令的位置
{
state=1;
ES=1;
Position=m;
Search(add);
}
//主机接收从机状态,同样也为查询法不用中断
voidS_M_Protocol(ucharadd,uchar*m)//三个参量分别为从机地址,命令的字节数,命令的位置
{
state=4;
ES=1;
Position=m;
Search(add);
}
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);
while(state);
ES=0;
}
//-----------------------------
//主函数,主机主函数主要用于与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);//发送通信停止命令
break;
}*/
break;
}
case2:
{
if(temp==M_SOK)//M_S得到回应
{
state=3;
SendByte(*Position);//发送第一字节
break;
}
break;
}
case3:
{
if(temp==CONTINUE)//从机继续要求数据
{
if(Position-CMD
{
Position++;
SendByte(*Position);//发送数据
break;
}
else//数组溢出,停止通信
{
state=0;
SendByte(STOP);
break;
}
}
break;
}
//-----------------------------------------------------------------------
//----------------接收部分---------------------------------------------
case4:
{
if(temp==Response)//呼叫从机得到回应
{
state=5;//转换状态
SendByte(S_M);//发送从机到主机命令
break;
}
/*else//无回应,停止此次传输
{
state=0;
SendByte(STOP);
break;
}*/
else
break;
}
case5:
{
if(temp==OK)//发送S_M得到回应
{
state=6;//转换状态
SendByte(S_MOK);//准备完成
break;
}
/*else//无回应,停止通信
{
state=0;
SendByte(STOP); //发送停止命令
break;
}*/
else
break;
}
case6:
{
if(Position-CMD
{
*Position=temp;//接收数据
Position++;
SendByte(CONTINUE);//要求从机继续发送数据
break;
}
else//超出数组,停止通信
{
state=0;
SendByte(STOP);
break;
}
}
default:
break;
}
}
}
//-----------------------------------------------
//从机程序,从机接收信息,所以用中断法会更便于反馈和执行命令
//-------------------------------
#include"basic.h"
//---------------------------------------------------
//宏定义
#defineEN_ADDSEND TB8=1;//发送寻址,搜寻从机
#defineEN_DATASENDTB8=0;//发送数据
#defineM_S 0Xf0//握手后的命令字,主机到从机
#defineS_M 0Xf1//握手后的命令字,从机到主机
#defineM_SOK 0Xf2//主到从准备完成,从机发送的反馈信息
#defineS_MOK0xf3//从到主准备完成,主机发送的反馈信息
#defineSTOP0xf4//主机到从机发送结束
#defineERROR0xf5//错误
#defineResponse0xf6//应答信号
#defineCONTINUE0xf7//接受数据之后给对方发送的反馈,请求继续
#defineOK0xf8
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};//主机给从机发送的命令
ucharstate=0;//状态值,进行中断判断
ucharADDR;//呼叫从机地址
uchartemp=0;//SBUF缓存
uchar*Position=0;//数据指针,指定数据更新的位置
//------------------------------------------
//STC12具有7字节全球唯一ID,将7位的ID加和作为从机地址.(有可能从机地址会重复)
ucharSet_Add()
{
uchar*p;
uchari;
ucharaddr=0;
p=0xf1;//上电后唯一ID起始地址
for(i=0;i
{
addr+=*p;
}
return(addr);
}
//---------------------------------------------
//串口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
}
voidAll_Init()
{
Uart1_Init();
ADDR=Set_Add();
EA=1;//打开总中断
ES=1;//打开串口中断
}
//------------------------------------------
//查询法发送一个字
voidSendByte(uchardate)
{
ES=0;//关断串口中断
EN_DATASEND;
SBUF=date;
while(!
TI);
TI=0;
ES=1;//打开串口中断
}
//主函数,可以用大循环只执行全局数组命令,而中断接收并修改全局命令命令
voidmain()
{
All_Init();
Position=DATA;
//SendCmd(DATA);
while
(1);
{
}
}
//串口1中断服务程序,用state进行状态判断处理
voidUART1()interrupt4
{
RI=0;
temp=SBUF;//读取数据
if(state)
{
switch(state)
{
case1:
if(temp==M_S)//主机发送到从机,从机准备好接收数据
{
SendByte(M_SOK);//发送应答
state=2;//更换状态
break;
}
elseif(temp==S_M)//主机要求从机发数据
{
SendByte(OK);//回应主机
state=3;//转换状态
Position=DATA;
break;
}
elseif(temp==STOP)
{
SM2=1;
state=0;
break;
}
break;
case2:
{
if(temp==STOP)//停止符判定,回到待机状态
{
state=0;
SM2=1;
break;
}
DATA[1]=temp;//接收数据
SendByte(CONTINUE);//接收数据后回应
//SendByte(DATA[1]);//串口测试用的
break;
}
case3:
{
switch(temp)
{
caseS_MOK:
//主机准备完成
{
SendByte(*Position);//发送数据
break;
}
caseCONTINUE:
{
Position++;
SendByte(*Position);//发送数据
break;
}
caseSTOP:
//停止命令,返回待机状态
{
state=0;
SM2=1;
break;
}
}
}
}
}
if(RB8==1)//判断寻址
{
if(temp==ADDR)//进行地址判断
{
SM2=0;//从机响应,清除SM2
SendByte(Response);//发送应答
state=1;//更换状态
}
else//用于主机呼叫从机之后,错误的呼叫其他从机,则使该机处于待机状态
{
SM2=1;
state=0;
}
}
}