51单片机多机通信协议

发布者:梦回归处最新更新时间:2015-06-15 来源: 51hei关键字: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) //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;
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<19)//数组长度判断
{
Position++;
SendByte(*Position);//发送数据
break;

 
}
else//数组溢出,停止通信
{
state=0;
SendByte(STOP);
break;
}
break;
}[page]
//-----------------------------------------------------------------------
//----------------接收部分---------------------------------------------
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<20) //数组溢出判断
{
*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<7;i++)
{
addr+=*p;
}
return (addr);
}

 
//---------------------------------------------
//串口1初始化,用于和从机通讯
void Uart1_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
}
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;
}
}
 
}

关键字:51单片机  多机通信协议 引用地址:51单片机多机通信协议

上一篇:C8051F的nRF24L01 PTR6000无线收发
下一篇:让没有PWM功能的单片机实现PWM功能

推荐阅读最新更新时间:2024-03-16 14:03

51单片机lcd1602d电子时钟设计
由于课程设计需要,本人做了一个基于51单片机控制的lcd1602d显示的电子时钟电子设计产品。可以显示万年历,星期。 本来还想加上温湿度的检测,发现屏幕空间不够用了。。有需要可以再另外共享那个设计。第一次 单片机源程序如下: #include reg52.h #define uint unsigned int #define uchar unsigned char sbit rs=P1^0; sbit rw=P1^1; sbit en=P1^2; sbit key_set=P3^4; sb
[单片机]
<font color='red'>51单片机</font>lcd1602d电子时钟设计
51单片机+18B20显示程序+74HC164扩展显示数码管
51 单片机 +18B20显示程序+74HC164扩展显示数码管 #include stc.h #include intrins.h //_nop_();延时函数用 #define uchar unsigned char #define uint unsigned int //================18b20数据口定义=============== uint temp; // 定义一个16位变量用于COPY数据 sbit DQ = P2^6; char flash,presence; uint temp1,temp2; //读出温度暂放 uchar s1,s2,s3,s4
[单片机]
51单片机实现两片联级74HC595驱动16个LED灯
一、使用proteus绘制简单的电路图,用于后续仿真 二、编写程序 /******************************************************************************************************************** ---- @Project: LED-74HC595 ---- @File: main.c ---- @Edit: ZHQ ---- @Version: V1.0 ---- @CreationTime: 20200524 ---- @ModifiedTime: 20200524 ---- @Description: 两片联级
[单片机]
<font color='red'>51单片机</font>实现两片联级74HC595驱动16个LED灯
基于51单片机矩阵键盘的简易计算器制作
1. 运算过程、符号公式实时显示在显示屏上(I2C 1602)。 2. 自带三角函数、开根号、平方运算。 3. 计算得出的结果可设置保存并用以下一次计算。 4. 所有运算结果精确到至少小数点后两位。 5. 运算结果可通过串口发送给上位机。 6. 当断电重启时,能存储并显示断电前正在计算的任务。(AT24C02) 硬件连接图如下: 单片机源程序如下: main.c #include REGX52.H #include Calculate.H #include Martixkey.h #include AT24C02.h #include stdio.h #i
[单片机]
基于<font color='red'>51单片机</font>矩阵键盘的简易计算器制作
51单片机的cpu主要由什么组成_51单片机的字长是多少
  51单片机的cpu主要由什么组成   51单片机的cpu主要组成部分有中央处理器( CPU )、内部数据存储器( RAM)、内部程序存储器( ROM)、定时器/计数器、并行I/0口、口、中断控制系统、定时与控制部件。   单片机是一种集成电路芯片,是采用超大规模集成电路技术把具有数据处理能力的中央处理器CPU、随机存储器RAM、只读存储器ROM、多种I/O口和中断系统、定时器/计数器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A/D转换器等电路)集成到-块硅片上构成的一个小而完善的微型计算机系统,在工业控制领域广泛应用。从上世纪80年代,由当时的4位、8位单片机,发展到现在的300M的高速单片机。  
[单片机]
基于C51单片机的校园自助导览仪设计
摘要:在分析MP3标准算法的基础上,基于C51单片机实现MP3的编解码,并对MP3编码进行了多方面的优化;在单片机上的MP3算法中加入无线功能,设计成为一种校园自助导览仪。经野外测试,效果良好。 关键词:MP3编解码;无线模块;自助导览 引言 MP3是MPEG-I的音频标准第三层压缩模式。虽然算法比较复杂,但压缩比最大在低码率条件下基本能达到CD的音质效果。其压缩比例高、音质失真小的特点使之成为用于当前PC、网络、PDA等最为流行的音频格式。在嵌入式系统中实现MP3音频编解码常见的有两种方案;一种是硬件解码(即通过专用的MP3解码硬件进行解码),其特点是可以实现较高的性能和较低的功耗,目前大多数商用MP3都采用这种方案;另外一
[单片机]
基于C<font color='red'>51单片机</font>的校园自助导览仪设计
51单片机十进制整数与二进制整数转换汇编语言子程序
==================================== 【4位十进制整数转换为二进制整数子程序】 入口:十进制整数千位数RAM址存于R0,百位数、十位数、个位数RAM址依次加1; 返回值:转换所得二进制整数存于R3(高字节)R4(低字节)。 DtoB: MOV R2, #4 ;;R2←递减的循环次数初值 MOV A, @R0 MOV R4, A ;;R4←千位数 LP1 : MOV A, R4 ;;R3R4←(R3)(R4)*10 MOV B, #10 MUL AB MOV R4, A MOV B, #10 XCH A
[单片机]
基于89C51单片机的环境噪声测量仪
   1 引 言      环境噪声监测,是人类提高生活质量,加强环境保护的一个重要环节,在各大城市的繁华街区和居民区,已有大型环境噪声显示器竖立街头。但目前国内的便携式噪声测试仪,多为价格昂贵的进口专用设备,除卫生、计量等环保专业部门拥有外,无法作为民用品推广普及。本文介绍一种以89C51单片机为核心,采用V/F转换技术构成的低成本、便携式数字显示环境噪声测量仪。该仪器工作稳定、性能良好,经校验定标后能满足一般民用需要,可广泛应用于工矿企业、机关、学校等需要对环境噪声进行测量和控制的场合。 2 声压级的测量机理   人耳的听阈一般是20μPa,痛阈一般是200 Pa,其间相差107倍,这样宽广的声压范围很不易测量,
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved