标题:
组态王单片机ASCII协议编程源码与仿真(含注解)
[打印本页]
作者:
2405502292
时间:
2018-8-14 08:54
标题:
组态王单片机ASCII协议编程源码与仿真(含注解)
组态王51单片机ASCII协议编程
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
0.png
(18.2 KB, 下载次数: 33)
下载附件
2018-8-14 18:02 上传
0.png
(53.56 KB, 下载次数: 32)
下载附件
2018-8-14 18:03 上传
单片机源程序如下:
#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)
……………………
…………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
组态王单片机ASCII协议编程.rar
(25.66 KB, 下载次数: 102)
2018-8-14 08:53 上传
点击文件名下载附件
下载积分: 黑币 -5
作者:
kathyzheng369
时间:
2018-8-29 23:22
非常感谢楼主的分享
作者:
strongben
时间:
2019-7-6 14:40
组态王的那部分怎么做,想知道组态王怎么和Proteus连接起来
作者:
慕斯雪芙
时间:
2020-4-13 13:03
是我需要的
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1