/*
单片机与组态王进行数据通讯(HEX模式)
2005-11-18测试通过
赵学军
*/
#include <reg51.h>
#define byte unsigned char
#define word unsigned int
#define ENQ 0x05 //询问
#define ACK 0x06 //确认
#define NAK 0x15 //否认
#define EOT 0x04 //发送结束
#define ETX 0x03 //应答结束
#define DB 0x01 //字节
#define DW 0x02 //字
#define DF 0x03 //浮点
#define BufMax 30
#define time0 -100000
bit RecvOk,CRCok;
bit LED;
sbit LIT=P0^0;
byte idata Rbuf[BufMax],Tbuf[BufMax];
byte data Rptr,Tptr,Tnum;
byte data MyAddr,DelayMs,last,ReadMe;
byte idata DatB[8];
word idata DatW[8];
float idata DatF[8];
void CheckCRC()
{
byte i,n,crc;
n=Rptr;
crc=ENQ;
for(i=0;i<n;i++) crc^=Rbuf[i];
if(crc==0) CRCok=1;
else CRCok=0;
}
void Uart() interrupt 4 using 1
{
byte m;
if(RI) //ENQ.......EOT,CRC
{
RI=0;m=SBUF;
if(last==ENQ &&(m==MyAddr ||m=='R' || m=='W')) Rptr=0;
if(Rptr<BufMax)
{
Rbuf[Rptr]=m; Rptr++;
}
if(last==EOT) RecvOk=1;
last=m;
}
else
{
TI=0;
if(Tnum>0)
{
SBUF=Tbuf[Tptr];
if(++Tptr>=BufMax) Tptr=0;
Tnum--;
}
else if(ReadMe==2)
{
SM2=1; ReadMe=0;
}
}
}
void Timer1() interrupt 1 using 2
{
TH0=time0>>8; TL0=time0&0xff;
if(DelayMs>0) DelayMs--;
else SM2=1;
}
void main()
{
byte n,i,*p,crc,k;
word ptr,num;
IE=0x92;SCON=0xD0; SM2=1; TB8=0;
TMOD=0x21; PCON=0x80;
TH1=-2; TL1=-2; TR1=1;
TH0=time0>>8; TL0=time0&0xff; TR0=1;
Tptr=0; Tnum=0; Rptr=0;
ReadMe=0; RecvOk=0;MyAddr=0;
DatB[0]=123;DatB[1]=234;DatB[2]=111; DatB[3]=222;
DatW[0]=1234;DatW[1]=5678;DatW[2]=7890;DatW[3]=17890;
DatF[0]=12.34; DatF[1]=123.4; DatF[2]=1234.5;
while(1)
{
DatB[1]=P1;
if(RecvOk)
{
RecvOk=0; CheckCRC();
if(Rbuf[0]==MyAddr && CRCok==1 && SM2==1) //对PC的查询命令进行应答
{
LED=!LED; LIT=LED;
Tbuf[0]=ACK; Tbuf[1]=MyAddr; Tbuf[2]=ETX;
crc=0; for(i=0;i<3;i++) crc^=Tbuf[i];
Tbuf[3]=crc;
Tptr=0; Tnum=4; TI=1;
DelayMs=10; ReadMe=1;
SM2=0;
}
else if(SM2==0 && CRCok==1) //在应答后进行数据传送控制
{
ReadMe=2;
n=Rbuf[4];
ptr=Rbuf[3]<<8 | Rbuf[2];
if(Rbuf[0]=='R')
{
switch(Rbuf[1])
{
case DB:num=n;
DatB[0]++;
p=(byte*)DatB+ptr;
for(i=0;i<num;i++)
{
k=i;
Tbuf[3+k]=p[k];
}
break;
case DW:num=n/2;
DatW[0]++;
p=(byte*)DatW+ptr*2;
for(i=0;i<num;i++)
{
k=i*2;
Tbuf[3+k]=p[k+1];
Tbuf[4+k]=p[k];
}
break;
case DF:num=n/4;
DatF[0]+=0.01;
p=(byte*)DatF+ptr*4;
for(i=0;i<num;i++)
{
k=4*i;
Tbuf[6+k]=p[k];
Tbuf[5+k]=p[k+1];
Tbuf[4+k]=p[k+2];
Tbuf[3+k]=p[k+3];
}
break;
}
Tbuf[0]=ACK; Tbuf[1]=n&0xff; Tbuf[2]=n>>8;
Tbuf[3+n]=ETX;
crc=0; for(i=0;i<4+n;i++) crc^=Tbuf[i];
Tbuf[4+n]=crc;
Tptr=0; Tnum=n+5; TI=1;
}
else if(Rbuf[0]=='W')
{
n=Rptr-6;
switch(Rbuf[1])
{
case DB:num=n;
p=(byte*)DatB+ptr;
for(i=0;i<num;i++)
{
k=i;
p[i]=Rbuf[k+4];
}
break;
case DW:num=n/2;
p=(byte*)DatW+ptr*2;
for(i=0;i<num;i++)
{
k=i*2;
p[k+1]=Rbuf[k+4];
p[k]=Rbuf[k+5];
}
break;
case DF:num=n/4;
p=(byte*)DatF+ptr*4;
for(i=0;i<num;i++)
{
k=4*i;
p[k+3]=Rbuf[k+4];
p[k+2]=Rbuf[k+5];
p[k+1]=Rbuf[k+6];
p[k]=Rbuf[k+7];
}
break;
}
Tbuf[0]=ACK; Tbuf[1]=MyAddr; Tbuf[2]=ETX;
crc=0; for(i=0;i<3;i++) crc^=Tbuf[i];
Tbuf[3]=crc;
Tptr=0; Tnum=4; TI=1;
}
}
}
}
}