转自:http://www.cnblogs.com/weifeng727/category/845655.html
#include<reg52.h>
//------------------串口通信协议-----------------//
/*
客户端数据包格式解释(长度恒为15):
例如:A01_fmq_01Off___#
A--------数据包的开始标记(可以为A到Z,意味着数据包可以有26种)
01-----设备代号
fmq_01Off___--------指令(长度恒为10),指令的前4个人字符是指令头部,指令的后6个字符是指令尾部
#---------数据包的结束标记
服务器端数据包格式解释(长度恒为15):
例如:A02_SenT010250#
A--------数据包的开始标记(可以为A到Z,意味着数据包可以有26种)
02-----设备代号
SenT010250--------指令(长度恒为10),指令的前4个人字符是指令头部,指令的后6个字符是指令尾部
#---------数据包的结束标记
*/
char buf_string[16]; //定义数据包长度为15个字符
#define deviceID_1Bit '0' //用于串口通信时,定义本地设备ID的第1位
#define deviceID_2Bit '2' //用于串口通信时,定义本地设备ID的第2位
#define datapackage_headflag 'A' //用于串口通信时,定义数据包头部的验证标记
char DataPackage_DS18B20[16]={datapackage_headflag,deviceID_1Bit,deviceID_2Bit,'_','S','e','n','T','X','X','X','X','X','X','#'};
char HeartBeat[16]={datapackage_headflag,deviceID_1Bit,deviceID_2Bit,'_','B','e','a','t','X','X','X','X','X','X','#'};
//----------------------------------------------//
/*******************************
串口通信
MCU:89C52RC 11.0592MHz
//11.0592MHz 0xd0 1200bps
//12MHz 0xcc 1200bps
//11.0592MHz 0xfa 9600bps
//0xf4 11.0592MHz 0xf3 12MHz 4800bps
//均在SMOD=1的情况下(波特率倍增模式)
*******************************/
//串口发送函数
void PutString(unsigned char *TXStr)
{
ES=0;
while(*TXStr!=0)
{
SBUF=*TXStr;
while(TI==0);
TI=0;
TXStr++;
}
ES=1;
}
//串口接收函数
bit ReceiveString()
{
char * RecStr=buf_string;
char num=0;
unsigned char count=0;
loop:
*RecStr=SBUF;
count=0;
RI=0;
if(num<14) //数据包长度为15个字符,尝试连续接收15个字符
{
num++;
RecStr++;
while(!RI)
{
count++;
if(count>130)return 0; //接收数据等待延迟,等待时间太久会导致CPU运算闲置,太短会出现"数据包被分割",默认count=130
}
goto loop;
}
return 1;
}
//定时器1用作波特率发生器
void Init_USART()
{
SCON=0x50; //串口方式1,使能接收
TMOD|=0x20; //定时器1工作方式2(8位自动重装初值)
TMOD&=~0x10;
TH1=0xfa; //9600bps
TL1=0xfa;
PCON|=0x80; //SMOD=1
TR1=1;
TI=0;
RI=0;
//PS=1; //提高串口中断优先级
ES=1; //开启串口中断使能
}
//比较指令头部
bit CompareCMD_head(char CMD_head[])
{
unsigned char CharNum;
for(CharNum=0;CharNum<4;CharNum++) //指令长度为10个字符
{
if(!(buf_string[CharNum+4]==CMD_head[CharNum]))
{
return 0; //指令头部匹配失败
}
}
return 1; //指令头部匹配成功
}
//比较指令尾部(start:从哪里开始比较,quality:比较多少个字符,CMD_tail[]:要比较的字符串)
bit CompareCMD_tail(unsigned char start,unsigned char quality,char CMD_tail[])
{
unsigned char CharNum;
for(CharNum=0;CharNum<quality;CharNum++)
{
if(!(buf_string[start+CharNum]==CMD_tail[CharNum]))
{
return 0;
}
}
return 1;
}
bit Deal_UART_RecData() //处理串口接收数据包函数(成功处理数据包则返回1,否则返回0)
{
//PutString(buf_string);
if(buf_string[0]==datapackage_headflag&&buf_string[14]=='#') //进行数据包头尾标记验证
{
switch(buf_string[1]) //识别发送者设备ID的第1位数字
{
case '0':
switch(buf_string[2]) //识别发送者设备ID的第2位数字
{
case '3':
if(CompareCMD_head("Ligt")) //判断指令头部是否为"Ligt"
{
//下面是指令尾部分析
switch(buf_string[8])
{
case '0':
switch(buf_string[9])
{
case '0':
return 0;
case '1':
if(CompareCMD_tail(10,3,"Off")) //A03_Ligt01Off_#
{
//要执行的代码
return 1;
}
if(CompareCMD_tail(10,3,"On_"))
{
return 1;
}
return 0;
default:
return 0;
}
case '1':
default:
return 0;
}
}
if(CompareCMD_head("SenT"))
{
}
if(CompareCMD_head("jdq_"))
{
}
if(CompareCMD_head("Try!"))
{
}
return 0;
default:
return 0;
}
default:
return 0;
}
}
return 0;
}
/************************
中断函数
************************/
//串口中断服务函数-----------
void USART() interrupt 4 //标志位TI和RI需要手动复位,TI和RI置位共用一个中断入口
{
if(ReceiveString())
{
//数据包长度正确则执行以下代码
Deal_UART_RecData();
}
else
{
//数据包长度错误则执行以下代码
//LED1=~LED1;
}
RI=0; //接收并处理一次数据后把接收中断标志清除一下,拒绝响应在中断接收忙的时候发来的请求
}
/***************************
主函数
***************************/
void main()
{
EA=1;
Init_USART();
while(1)
{
//PutString(buf_string);//空格20H,回车0DH
}
}