#define uchar unsigned char
#define uint unsigned int
#define tim0 -50000
#define BPS57600 -1 //11.0592
#define BPS28800 -2 //11.0592
#define BPS19200 -3 //11.0592
#define BPS9600 -6 //11.0592
#define BPS4800 -12 //11.0592
//////////////////////////////////////////////////////////////
//支持字节和字类型,由于他的浮点怪异所以不支持
idata uchar DatB[4]; //组态字节
idata uint DatW[4]; //组态整数
idata float DatF[4]; //组态浮点
uchar Addr;
bit RECV=0;
idata uchar Rbuf[40],Rptr,Rnum;
idata uchar Tbuf[40],Tptr,Tnum;
code uchar asc[]="0123456789ABCDEF";
uchar AscHex(uchar m)
{
if(m>='0' && m<='9') return m-'0';
else if(m>='A' && m<='F') return m-'A'+10;
else if(m>='a' && m<='f') return m-'a'+10;
return 0;
}
uchar AscByte(uchar p) //ASC变BYTE
{
uchar x1,x2;
x1=AscHex(Rbuf[p]);
x2=AscHex(Rbuf[p+1]);
return x2+x1*16;
}
void ByteAsc(uchar p) //BUYE变ASC
{
Tbuf[Tnum++]=asc[p>>4];
Tbuf[Tnum++]=asc[p&15];
}
bit ChkLRC() //接收数据包效验
{
uchar i,d,s=0;
for(i=0;i<Rnum-2;i++) s^=Rbuf[i];
d=AscByte(Rnum-2);
return s==d;
}
void SetLRC() //发送数据包效验并发送
{
uchar i,s=0;
for(i=0;i<Tnum;i++) s^=Tbuf[i];
ByteAsc(s);
Tbuf[Tnum++]=0x0d; //添加包结束符
SBUF=0x40; //发送包起始并启动串口发送
}
void serial() interrupt 4 using 2 //串口数据收发
{
uchar m;
if(RI) //接收部分
{
RI=0; m=SBUF;
if(m==0x40) //帧开始
{
Rptr=0; Rnum=0;
}
else if(m==0x0D) //帧结束
{
RECV=1;
}
else if(Rnum<40) //包长限制
{
Rbuf[Rptr++]=m;
Rnum++;
}
}
if(TI) //发送部分
{
TI=0;
if(Tnum>0)
{
SBUF=Tbuf[Tptr++];
Tnum--;
}
}
}
//////////////////////////////////////////////////////
void KingASC() //通信协议的处理程序
{
uint p,x0,x1,x2;
uchar n,cmd,i;
uchar *s;
cmd=AscByte(2)&0xf;
p=AscByte(4)*256+AscByte(6);
n=AscByte(8);
if((cmd&1)==0) //组态王从单片机读数据
{
Tnum=0; Tptr=0;
ByteAsc(Addr);
ByteAsc(n);
switch(cmd&0x0c)
{
case 0x00: //字节变量处理
s=(uchar*)DatB+p;
for(i=0;i<n;i++)
ByteAsc(s[i]);
break;
case 0x04: //字变量处理
s=(uchar*)DatW+2*p;
for(i=0;i<n/2;i++)
{
ByteAsc(s[2*i]);
ByteAsc(s[2*i+1]);
}
break;
case 0x08: //浮点变量处理
case 0x0c: //浮点变量处理
s=(uchar*)DatF+4*p;
for(i=0;i<n/4;i++)
{
x1=s[4*i]&0x80;
x2=s[4*i]<<1;
x2+=(s[4*i+1])>>7;
ByteAsc(x1+x2-126);
ByteAsc((s[4*i+1])|0x80);
ByteAsc(s[4*i+2]);
ByteAsc(s[4*i+3]);
}
break;
}
SetLRC();
}
else //组态王向单片机写数据
{
switch(cmd&0x0c)
{
case 0x00: ////字节变量处理
s=(uchar*)DatB+p;
for(i=0;i<n;i++)
s[i]=AscByte(10+2*i);
break;
case 0x04: //字变量处理
s=(uchar*)DatW+2*p;
for(i=0;i<n/2;i++)
{
s[2*i]=AscByte(10+4*i);
s[2*i+1]=AscByte(12+4*i);
}
break;
case 0x08: //浮点变量处理
case 0x0c: //浮点变量处理
s=(uchar*)DatF+4*p;
for(i=0;i<n/4;i++)
{
x0=AscByte(10+8*i);
x1=x0&0x80;
x2=x0&0x7f;
x2=x2+126;
x0=x1|(x2>>1);
s[4*i]=x0;
x0=AscByte(12+8*i)&0x7f;
if(x2&1) x0=x0|0x80;
s[4*i+1]=x0;
s[4*i+2]=AscByte(14+8*i);
s[4*i+3]=AscByte(16+8*i);
}
break;
}
Tnum=0; Tptr=0;
ByteAsc(Addr);
Tbuf[Tnum++]='#';
Tbuf[Tnum++]='#';
SetLRC();
}
Rnum=0; Rptr=0;
}
void timer0() interrupt 1 //定时对串口收到的数据包进行处理
{
TH0=tim0>>8; TL0=tim0;
if(RECV)
{
RECV=0;
if(ChkLRC()) //先进行数据效验
{
if(AscByte(0)==Addr) KingASC(); //地址是本机则进行协议的处理
}
}
}
void Init() //对定时器及串口进行初始化
{
EA=1; ES=1; ET0=1;
TMOD=0X21; IP=0x10;
SCON=0X50; PCON=0X80;
TH1=BPS19200; TR1=1; //串口波特率的设置
TH0=tim0>>8; TL0=tim0; TR0=1;
}
主函数:
#include <reg52.h>
#include <glzxj.h> //对协议的引用
///////////////////////////////////////////////////////
main()
{
Init(); //资源的初始化
DatB[0]=0xff; DatB[1]=0xff;
DatW[0]=123; DatW[1]=234;
DatW[2]=345; DatW[3]=456;
DatF[0]=-1.123; DatF[1]=-1.145;
DatF[2]=10.123; DatF[3]=100.145;
Addr=1; //单片机地址设置
while(1)
{
P0=DatB[0]; P2=DatB[1]; //用P0与P2测试字节的输出
DatB[2]=P1; DatB[3]=P3; //用P1与P3测试字节的输入
}
}