51单片机多机通信协议

做自己以前没做过的东西,总会有各种踌躇,害怕做不出来,其实要是真的开始去做了,问题就解决大半了。  在家没网,就开始写了,  熬了两夜,加一个半天,总算是完成了通信协议,经调试,可以正常工作。  如果有孩子也要做这个,可以参考一下哈!  别的不多说,贴代码。

//-------------------------------------------------

//主机程序,主机座控制,用中断法

//-----------------------------------------------

#include "basic.h"

//---------------------------------------------------

//宏定义

#define EN_ADDSEND   TB8=1;//发送寻址,搜寻从机

#define EN_DATASEND TB8=0;//发送数据

#define M_S         0Xf0//握手后的命令字,主机到从机

#define S_M         0Xf1//握手后的命令字,从机到主机

#define M_SOK       0Xf2//主到从准备完成,从机发送的反馈信息

#define S_MOK 0xf3//从到主准备完成,主机发送的反馈信息

#define STOP 0xf4//主机到从机发送结束

#define ERROR 0xf5//错误

#define Response 0xf6//应答信号

#define CONTINUE 0xf7//接受数据之后给对方发送的反馈,请求继续

#define OK 0xf8

//--------------------------------------------------

//数据定义

uchar DATA[20]={0};//从机返回的状态值

uchar CMD[20]= {0x44,0x44,0x44,0x55,0x55,0x55,0x47,0x45,0x65,0x35,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,};// 主机给从机发送的命令

uchar state=0;//状态值,进行中断判断

uchar Address;//呼叫从机地址

uchar temp=0;//SBUF缓存

uchar *Position=0;//数据指针,指定数据更新的位置

//---------------------------------------------

//串口1初始化,用于和从机通讯

void Uart1_Init(void) //[email protected]

{

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;

void SendByte (uchar date)

{

//EN_DATASEND;//TB8=0;

TB8=1;

SBUF=date;

while(!TI);

TI=0;

}

//-----------------------------------

//寻址从机

void Search(uchar ADD)

{

//EN_ADDSEND;

TB8=1;

SBUF=ADD;

while(!TI);

TI=0;

}

//主机向从机发送命令  //因为主机为控制端,为便于控制从机,所以选择用查询法而不选用中断

void M_S_Protocol(uchar add,uchar *m)//三个参量分别为从机地址,命令的字节数,命令的位置

{

state=1;

ES=1;

Position=m;

Search(add);

}

//主机接收从机状态,同样也为查询法不用中断

void S_M_Protocol(uchar add,uchar *m)//三个参量分别为从机地址,命令的字节数,命令的位置

{

state=4;

ES=1;

Position=m;

Search(add);

}

void M_S_Send(uchar add,uchar *m)//主机到从机整个过程

{

M_S_Protocol(add,m);

while(state);

ES=0;

}

void S_M_Send(uchar add,uchar *m)//从机到主机的整个过程

{

S_M_Protocol(add,m);

while(state);

ES=0;

}

//-----------------------------

//主函数,主机主函数主要用于与GPRS和从机之间做桥接

void main()

{

Uart1_Init();

while(1)

{

S_M_Send(0x01,CMD);

}

}

void UART1() interrupt 4

{

RI=0;//清除中断标志

temp=SBUF;

if(state)//处于传输状态

{

switch(state)

{

//-----------------------------------------------------------------

//---------------------M_S部分--------------------------------

case 1:

{

if(temp==Response)//寻址成功

{

SendByte(M_S); //发送M_S命令

state=2;  //转换状态

break;

}

/*else//寻址不成功,通信结束,转换为非通信状态

{

state=0;

SendByte(STOP);//发送通信停止命令

break;

}*/

break;

}

case 2:

{

if(temp==M_SOK)//M_S得到回应

{

state=3;

SendByte(*Position);//发送第一字节

break;

}

break;

}

case 3:

{

if(temp==CONTINUE) //从机继续要求数据

{

if(Position-CMD

{

Position++;

SendByte(*Position);//发送数据

break;

}

else//数组溢出,停止通信

{

state=0;

SendByte(STOP);

break;

}

}

break;

}

//-----------------------------------------------------------------------

//----------------接收部分---------------------------------------------

case 4:

{

if(temp==Response)//呼叫从机得到回应

{

state=5;//转换状态

SendByte(S_M);//发送从机到主机命令

break;

}

/*else//无回应,停止此次传输

{

state=0;

SendByte(STOP);

break;

} */

else

break;

}

case 5:

{

if(temp==OK)//发送S_M得到回应

{

state=6;//转换状态

SendByte(S_MOK);//准备完成

break;

}

/*else //无回应,停止通信

{

state=0;

SendByte(STOP);   //发送停止命令

break;

}*/

else

break;

}

case 6:

{

if(Position-CMD

{

*Position=temp;//接收数据

Position++;

SendByte(CONTINUE); //要求从机继续发送数据

break;

}

else//超出数组,停止通信

{

state=0;

SendByte(STOP);

break;

}

}

default:

break;

}

}

}

//-----------------------------------------------

//从机程序,从机接收信息,所以用中断法会更便于反馈和执行命令

//-------------------------------

#include "basic.h"

//---------------------------------------------------

//宏定义

#define EN_ADDSEND   TB8=1;//发送寻址,搜寻从机

#define EN_DATASEND TB8=0;//发送数据

#define M_S         0Xf0//握手后的命令字,主机到从机

#define S_M         0Xf1//握手后的命令字,从机到主机

#define M_SOK       0Xf2//主到从准备完成,从机发送的反馈信息

#define S_MOK 0xf3//从到主准备完成,主机发送的反馈信息

#define STOP 0xf4//主机到从机发送结束

#define ERROR 0xf5//错误

#define Response 0xf6//应答信号

#define CONTINUE 0xf7//接受数据之后给对方发送的反馈,请求继续

#define OK 0xf8

sbit key=P3^7;

//--------------------------------------------------

//数据定义

uchar DATA[20]={0x12,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,};//从机返回的状态值

uchar CMD[20]={0};//主机给从机发送的命令

uchar state=0;//状态值,进行中断判断

uchar ADDR;//呼叫从机地址

uchar temp=0;//SBUF缓存

uchar *Position=0;//数据指针,指定数据更新的位置

//------------------------------------------

//STC12具有7字节全球唯一ID,将7位的ID加和作为从机地址.(有可能从机地址会重复)

uchar Set_Add()

{

uchar *p;

uchar i;

uchar addr=0;

p=0xf1;//上电后唯一ID起始地址

for(i=0;i

{

addr+=*p;

}

return (addr);

}

//---------------------------------------------

//串口1初始化,用于和从机通讯

void Uart1_Init(void) //[email protected]

{

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

}

void All_Init()

{

Uart1_Init();

ADDR=Set_Add();

EA=1;//打开总中断

ES=1;//打开串口中断

}

//------------------------------------------

//查询法发送一个字

void SendByte (uchar date)

{

ES=0;//关断串口中断

EN_DATASEND;

SBUF=date;

while(!TI);

TI=0;

ES=1; //打开串口中断

}

//主函数,可以用大循环只执行全局数组命令,而中断接收并修改全局命令命令

void main()

{

All_Init();

Position=DATA;

//SendCmd(DATA);

while(1);

{

}

}

//串口1中断服务程序,用state进行状态判断处理

void UART1() interrupt 4

{

RI=0;

temp=SBUF;//读取数据

if (state)

{

switch (state)

{

case 1:

if(temp==M_S)//主机发送到从机,从机准备好接收数据

{

SendByte(M_SOK);//发送应答

state=2;//更换状态

break;

}

else if(temp==S_M)//主机要求从机发数据

{

SendByte(OK);//回应主机

state=3;//转换状态

Position=DATA;

break;

}

else if(temp==STOP)

{

SM2=1;

state=0;

break;

}

break;

case 2:

{

if(temp==STOP)//停止符判定,回到待机状态

{

state=0;

SM2=1;

break;

}

DATA[1]=temp;//接收数据

SendByte(CONTINUE);//接收数据后回应

//SendByte(DATA[1]);//串口测试用的

break;

}

case 3:

{

switch(temp)

{

case S_MOK://主机准备完成

{

SendByte(*Position);//发送数据

break;

}

case CONTINUE:

{

Position++;

SendByte(*Position);//发送数据

break;

}

case STOP:// 停止命令,返回待机状态

{

state=0;

SM2=1;

break;

}

}

}

}

}

if(RB8==1)//判断寻址

{

if(temp==ADDR)//进行地址判断

{

SM2=0;//从机响应,清除SM2

SendByte(Response);//发送应答

state=1;//更换状态

}

else//用于主机呼叫从机之后,错误的呼叫其他从机,则使该机处于待机状态

{

SM2=1;

state=0;

}

}

}

做自己以前没做过的东西,总会有各种踌躇,害怕做不出来,其实要是真的开始去做了,问题就解决大半了。  在家没网,就开始写了,  熬了两夜,加一个半天,总算是完成了通信协议,经调试,可以正常工作。  如果有孩子也要做这个,可以参考一下哈!  别的不多说,贴代码。

//-------------------------------------------------

//主机程序,主机座控制,用中断法

//-----------------------------------------------

#include "basic.h"

//---------------------------------------------------

//宏定义

#define EN_ADDSEND   TB8=1;//发送寻址,搜寻从机

#define EN_DATASEND TB8=0;//发送数据

#define M_S         0Xf0//握手后的命令字,主机到从机

#define S_M         0Xf1//握手后的命令字,从机到主机

#define M_SOK       0Xf2//主到从准备完成,从机发送的反馈信息

#define S_MOK 0xf3//从到主准备完成,主机发送的反馈信息

#define STOP 0xf4//主机到从机发送结束

#define ERROR 0xf5//错误

#define Response 0xf6//应答信号

#define CONTINUE 0xf7//接受数据之后给对方发送的反馈,请求继续

#define OK 0xf8

//--------------------------------------------------

//数据定义

uchar DATA[20]={0};//从机返回的状态值

uchar CMD[20]= {0x44,0x44,0x44,0x55,0x55,0x55,0x47,0x45,0x65,0x35,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,};// 主机给从机发送的命令

uchar state=0;//状态值,进行中断判断

uchar Address;//呼叫从机地址

uchar temp=0;//SBUF缓存

uchar *Position=0;//数据指针,指定数据更新的位置

//---------------------------------------------

//串口1初始化,用于和从机通讯

void Uart1_Init(void) //[email protected]

{

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;

void SendByte (uchar date)

{

//EN_DATASEND;//TB8=0;

TB8=1;

SBUF=date;

while(!TI);

TI=0;

}

//-----------------------------------

//寻址从机

void Search(uchar ADD)

{

//EN_ADDSEND;

TB8=1;

SBUF=ADD;

while(!TI);

TI=0;

}

//主机向从机发送命令  //因为主机为控制端,为便于控制从机,所以选择用查询法而不选用中断

void M_S_Protocol(uchar add,uchar *m)//三个参量分别为从机地址,命令的字节数,命令的位置

{

state=1;

ES=1;

Position=m;

Search(add);

}

//主机接收从机状态,同样也为查询法不用中断

void S_M_Protocol(uchar add,uchar *m)//三个参量分别为从机地址,命令的字节数,命令的位置

{

state=4;

ES=1;

Position=m;

Search(add);

}

void M_S_Send(uchar add,uchar *m)//主机到从机整个过程

{

M_S_Protocol(add,m);

while(state);

ES=0;

}

void S_M_Send(uchar add,uchar *m)//从机到主机的整个过程

{

S_M_Protocol(add,m);

while(state);

ES=0;

}

//-----------------------------

//主函数,主机主函数主要用于与GPRS和从机之间做桥接

void main()

{

Uart1_Init();

while(1)

{

S_M_Send(0x01,CMD);

}

}

void UART1() interrupt 4

{

RI=0;//清除中断标志

temp=SBUF;

if(state)//处于传输状态

{

switch(state)

{

//-----------------------------------------------------------------

//---------------------M_S部分--------------------------------

case 1:

{

if(temp==Response)//寻址成功

{

SendByte(M_S); //发送M_S命令

state=2;  //转换状态

break;

}

/*else//寻址不成功,通信结束,转换为非通信状态

{

state=0;

SendByte(STOP);//发送通信停止命令

break;

}*/

break;

}

case 2:

{

if(temp==M_SOK)//M_S得到回应

{

state=3;

SendByte(*Position);//发送第一字节

break;

}

break;

}

case 3:

{

if(temp==CONTINUE) //从机继续要求数据

{

if(Position-CMD

{

Position++;

SendByte(*Position);//发送数据

break;

}

else//数组溢出,停止通信

{

state=0;

SendByte(STOP);

break;

}

}

break;

}

//-----------------------------------------------------------------------

//----------------接收部分---------------------------------------------

case 4:

{

if(temp==Response)//呼叫从机得到回应

{

state=5;//转换状态

SendByte(S_M);//发送从机到主机命令

break;

}

/*else//无回应,停止此次传输

{

state=0;

SendByte(STOP);

break;

} */

else

break;

}

case 5:

{

if(temp==OK)//发送S_M得到回应

{

state=6;//转换状态

SendByte(S_MOK);//准备完成

break;

}

/*else //无回应,停止通信

{

state=0;

SendByte(STOP);   //发送停止命令

break;

}*/

else

break;

}

case 6:

{

if(Position-CMD

{

*Position=temp;//接收数据

Position++;

SendByte(CONTINUE); //要求从机继续发送数据

break;

}

else//超出数组,停止通信

{

state=0;

SendByte(STOP);

break;

}

}

default:

break;

}

}

}

//-----------------------------------------------

//从机程序,从机接收信息,所以用中断法会更便于反馈和执行命令

//-------------------------------

#include "basic.h"

//---------------------------------------------------

//宏定义

#define EN_ADDSEND   TB8=1;//发送寻址,搜寻从机

#define EN_DATASEND TB8=0;//发送数据

#define M_S         0Xf0//握手后的命令字,主机到从机

#define S_M         0Xf1//握手后的命令字,从机到主机

#define M_SOK       0Xf2//主到从准备完成,从机发送的反馈信息

#define S_MOK 0xf3//从到主准备完成,主机发送的反馈信息

#define STOP 0xf4//主机到从机发送结束

#define ERROR 0xf5//错误

#define Response 0xf6//应答信号

#define CONTINUE 0xf7//接受数据之后给对方发送的反馈,请求继续

#define OK 0xf8

sbit key=P3^7;

//--------------------------------------------------

//数据定义

uchar DATA[20]={0x12,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,};//从机返回的状态值

uchar CMD[20]={0};//主机给从机发送的命令

uchar state=0;//状态值,进行中断判断

uchar ADDR;//呼叫从机地址

uchar temp=0;//SBUF缓存

uchar *Position=0;//数据指针,指定数据更新的位置

//------------------------------------------

//STC12具有7字节全球唯一ID,将7位的ID加和作为从机地址.(有可能从机地址会重复)

uchar Set_Add()

{

uchar *p;

uchar i;

uchar addr=0;

p=0xf1;//上电后唯一ID起始地址

for(i=0;i

{

addr+=*p;

}

return (addr);

}

//---------------------------------------------

//串口1初始化,用于和从机通讯

void Uart1_Init(void) //[email protected]

{

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

}

void All_Init()

{

Uart1_Init();

ADDR=Set_Add();

EA=1;//打开总中断

ES=1;//打开串口中断

}

//------------------------------------------

//查询法发送一个字

void SendByte (uchar date)

{

ES=0;//关断串口中断

EN_DATASEND;

SBUF=date;

while(!TI);

TI=0;

ES=1; //打开串口中断

}

//主函数,可以用大循环只执行全局数组命令,而中断接收并修改全局命令命令

void main()

{

All_Init();

Position=DATA;

//SendCmd(DATA);

while(1);

{

}

}

//串口1中断服务程序,用state进行状态判断处理

void UART1() interrupt 4

{

RI=0;

temp=SBUF;//读取数据

if (state)

{

switch (state)

{

case 1:

if(temp==M_S)//主机发送到从机,从机准备好接收数据

{

SendByte(M_SOK);//发送应答

state=2;//更换状态

break;

}

else if(temp==S_M)//主机要求从机发数据

{

SendByte(OK);//回应主机

state=3;//转换状态

Position=DATA;

break;

}

else if(temp==STOP)

{

SM2=1;

state=0;

break;

}

break;

case 2:

{

if(temp==STOP)//停止符判定,回到待机状态

{

state=0;

SM2=1;

break;

}

DATA[1]=temp;//接收数据

SendByte(CONTINUE);//接收数据后回应

//SendByte(DATA[1]);//串口测试用的

break;

}

case 3:

{

switch(temp)

{

case S_MOK://主机准备完成

{

SendByte(*Position);//发送数据

break;

}

case CONTINUE:

{

Position++;

SendByte(*Position);//发送数据

break;

}

case STOP:// 停止命令,返回待机状态

{

state=0;

SM2=1;

break;

}

}

}

}

}

if(RB8==1)//判断寻址

{

if(temp==ADDR)//进行地址判断

{

SM2=0;//从机响应,清除SM2

SendByte(Response);//发送应答

state=1;//更换状态

}

else//用于主机呼叫从机之后,错误的呼叫其他从机,则使该机处于待机状态

{

SM2=1;

state=0;

}

}

}


相关内容

  • 单片机与上位机通信协议的制定
  • 单片机与上位机通信协议的制定 单片机和上位机的串口通信协议分为上行协议和下行协议,要分别制定! 上行协议,即由单片机向上位机发送数据. 下行协议,即由上位机向单片机发送数据. 而通信协议又要分固定长度和不定长度两种 本文所介绍的协议属于简单的固定字长的通信协议! 下行协议由四个字节构成 上表是简单的 ...

  • 基于单片机GPRS通信系统的计毕业设计好
  • 基于单片机GPRS通信系统的计 摘要 GPRS(通用分组无线电业务)是利用包交换的概念发展的一套无线传输方式,GPRS网络是基于现有的GSM(全球移动通信系统)网络实现的,在现有的GSM网络中需要增加一些节点,如GGSN(GPRS网关支持节点)和SGSN(GPRS服务支持节点).SGSN的主要作用是 ...

  • 出色通信工程(电子)汪是这样炼成的
  • 我们当中,很多通信专业的同学,在读书的时候不知道该做啥,在毕业了以后也不知道该干嘛,职业规划和能力提高都不知道怎么下手,我们来看一下李宇同学是怎么处理这些问题的. 通信工程狗在大学要学啥 先简单介绍一下,作者本科时候985学校的通信工程,到现在工作满4年,在武汉一私企,14K月薪. 这水平在很多北上 ...

  • 组态王6.53与51单片机
  • 基于51单片机的智能仪表与组态王的通讯 1242人阅读 | 0条评论 发布于:2009-8-10 23:01:00 1.引言 随着工业自动化进程的不断加快,现场仪器.仪表.设备正不断向数字化.智能化和网络化方向推进. 单片机以其强大的现场数据处理能力,低廉的价格,紧凑的系统结构.高度的灵活性,微小的 ...

  • 智能家居控制与通信的实现毕业论文
  • 课程设计报告 课程名称 设计题目 智能家居(控制与通信的实现) 基于物联网的智能家居系统设计 摘要 物联网作为朝阳的产业,被列为国家五大新兴战略性产业之一.物联网是通过射频识别.红外感应器.全球定位系统.激光扫描器等信息传感设备,按约定的协议,把任何物品与互联网连接起来,进行信息交换和通讯,以实现智 ...

  • 智能家居毕业论文
  • 课程设计报告 2014-2015学年第 一学期 课程名称 设计题目 智能家居(控制与通信的实现) 2014年9月3日 基于物联网的智能家居系统设计 摘要 物联网作为朝阳的产业,被列为国家五大新兴战略性产业之一.物联网是通过射频识别.红外感应器.全球定位系统.激光扫描器等信息传感设备,按约定的协议,把 ...

  • 离子感应探测器
  • 2006年 第2期 仪表技术与传感器 Instrument Technique and Sensor2006 No 2 带IP节点的离子感烟探测器 陈 彦1,徐 平1,张 伟2,张 杰2 (1.北京航空航天大学理学院,北京 100083;2.山东信息职业技术学院电子工程系,山东 潍坊 261041) ...

  • 基于ARM的蓝牙无线通信模块的设计
  • 湖南文理学院 课程设计报告 课程名称: 嵌入式系统课程设计 专业班级: 应用电子技术09201班 学生姓名: 崔 剑 指导教师: 袁 里 弛 完成时间: 2011年12月25日 报告成绩: 卷 首 摘 要 传统工业数据通信系统以单片机为下位机采集系统.PC 构建的数据中心以及RS232等有线方式构建 ...

  • 单片机应用实习报告
  • 学生实习报告书 实习类别 单片机应用实习 实习地址 武汉理工大学信息工程学院 学 院 专 业 班 级 姓 名 指导教师 2013 年 1 月 16 日 信息工程学院 通信工程 实 习 执 行 大 纲 一. 实习目的 1.巩固<单片机原理与应用>理论课的理论知识: 2.熟悉单片机应用系统的 ...

  • 电气专业的一些毕业设计题目
  • 电气专业的一些毕业设计题目 电子类: 1.红外遥控照明灯(电路+程序+论文) 2.基于单片机的多功能智能小车设计论文(电路+程序+论文) 3.基于数字信号处理器(DSP)的异步电机直接转矩控制研究(硕士)(论文+上位机下位机软件+程序) 4.简单温度控制系统(仅论文) 5.漏电保护器(电路+程序+论 ...