找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4872|回复: 3
打印 上一主题 下一主题
收起左侧

组态王单片机ASCII协议编程源码与仿真(含注解)

[复制链接]
跳转到指定楼层
楼主
组态王51单片机ASCII协议编程
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


单片机源程序如下:
  1. #define uchar unsigned char
  2. #define uint unsigned int
  3. #define tim0 -50000
  4. #define BPS57600 -1          //11.0592
  5. #define BPS28800 -2          //11.0592
  6. #define BPS19200 -3          //11.0592
  7. #define BPS9600 -6          //11.0592
  8. #define BPS4800 -12          //11.0592
  9. //////////////////////////////////////////////////////////////
  10. //支持字节和字类型,由于他的浮点怪异所以不支持
  11. idata uchar DatB[4];   //组态字节
  12. idata uint  DatW[4];   //组态整数
  13. idata float DatF[4];   //组态浮点
  14. uchar Addr;

  15. bit RECV=0;
  16. idata uchar Rbuf[40],Rptr,Rnum;
  17. idata uchar Tbuf[40],Tptr,Tnum;
  18. code uchar asc[]="0123456789ABCDEF";

  19. uchar AscHex(uchar m)
  20. {
  21.   if(m>='0' && m<='9') return m-'0';
  22.   else if(m>='A' && m<='F') return m-'A'+10;
  23.   else if(m>='a' && m<='f') return m-'a'+10;
  24.   return 0;
  25. }

  26. uchar AscByte(uchar p) //ASC变BYTE
  27. {
  28.   uchar x1,x2;
  29.   x1=AscHex(Rbuf[p]);
  30.   x2=AscHex(Rbuf[p+1]);
  31.   return x2+x1*16;
  32. }

  33. void ByteAsc(uchar p)  //BUYE变ASC
  34. {
  35.   Tbuf[Tnum++]=asc[p>>4];
  36.   Tbuf[Tnum++]=asc[p&15];
  37. }

  38. bit ChkLRC() //接收数据包效验
  39. {
  40.   uchar i,d,s=0;
  41.   for(i=0;i<Rnum-2;i++) s^=Rbuf[i];
  42.   d=AscByte(Rnum-2);
  43.   return s==d;
  44. }

  45. void SetLRC() //发送数据包效验并发送
  46. {
  47.   uchar i,s=0;
  48.   for(i=0;i<Tnum;i++) s^=Tbuf[i];
  49.   ByteAsc(s);
  50.   Tbuf[Tnum++]=0x0d;  //添加包结束符
  51.   SBUF=0x40;          //发送包起始并启动串口发送
  52. }

  53. void serial() interrupt 4 using 2  //串口数据收发
  54. {
  55.   uchar m;
  56.   if(RI)   //接收部分
  57.   {
  58.     RI=0; m=SBUF;
  59.         if(m==0x40)      //帧开始
  60.         {
  61.           Rptr=0; Rnum=0;
  62.         }
  63.         else if(m==0x0D) //帧结束
  64.         {
  65.           RECV=1;
  66.         }
  67.         else if(Rnum<40) //包长限制
  68.         {
  69.           Rbuf[Rptr++]=m;
  70.           Rnum++;
  71.         }
  72.   }
  73.   if(TI)   //发送部分
  74.   {
  75.     TI=0;
  76.     if(Tnum>0)
  77.         {
  78.           SBUF=Tbuf[Tptr++];
  79.           Tnum--;
  80.         }
  81.   }
  82. }

  83. //////////////////////////////////////////////////////

  84. void KingASC()       //通信协议的处理程序
  85. {
  86.   uint p,x0,x1,x2;
  87.   uchar n,cmd,i;
  88.   uchar *s;
  89.   cmd=AscByte(2)&0xf;
  90.   p=AscByte(4)*256+AscByte(6);  
  91.   n=AscByte(8);
  92.   if((cmd&1)==0)     //组态王从单片机读数据
  93.   {
  94.     Tnum=0; Tptr=0;
  95.         ByteAsc(Addr);
  96.         ByteAsc(n);
  97.     switch(cmd&0x0c)
  98.         {
  99.           case 0x00:   //字节变量处理
  100.             s=(uchar*)DatB+p;
  101.         for(i=0;i<n;i++)
  102.                   ByteAsc(s[i]);
  103.                 break;
  104.           case 0x04:   //字变量处理
  105.             s=(uchar*)DatW+2*p;
  106.         for(i=0;i<n/2;i++)
  107.                 {
  108.                   ByteAsc(s[2*i]);
  109.                   ByteAsc(s[2*i+1]);
  110.                 }
  111.                 break;
  112.           case 0x08: //浮点变量处理
  113.           case 0x0c: //浮点变量处理
  114.             s=(uchar*)DatF+4*p;
  115.         for(i=0;i<n/4;i++)
  116.                 {
  117.           x1=s[4*i]&0x80;
  118.           x2=s[4*i]<<1;
  119.           x2+=(s[4*i+1])>>7;
  120.                     ByteAsc(x1+x2-126);
  121.                   ByteAsc((s[4*i+1])|0x80);
  122.                   ByteAsc(s[4*i+2]);
  123.                   ByteAsc(s[4*i+3]);
  124.                 }
  125.                 break;
  126.         }
  127.         SetLRC();
  128.   }
  129.   else              //组态王向单片机写数据
  130.   {
  131.     switch(cmd&0x0c)
  132.         {
  133.           case 0x00: ////字节变量处理
  134.             s=(uchar*)DatB+p;
  135.         for(i=0;i<n;i++)
  136.                   s[i]=AscByte(10+2*i);
  137.                 break;
  138.           case 0x04: //字变量处理
  139.             s=(uchar*)DatW+2*p;
  140.             for(i=0;i<n/2;i++)
  141.                 {
  142.                   s[2*i]=AscByte(10+4*i);
  143.                   s[2*i+1]=AscByte(12+4*i);
  144.                 }
  145.                 break;
  146.           case 0x08: //浮点变量处理
  147.           case 0x0c: //浮点变量处理
  148.             s=(uchar*)DatF+4*p;
  149.             for(i=0;i<n/4;i++)
  150.                 {
  151.                   x0=AscByte(10+8*i);
  152.                   x1=x0&0x80;
  153.                   x2=x0&0x7f;
  154.           x2=x2+126;
  155.           x0=x1|(x2>>1);
  156.           s[4*i]=x0;
  157.                   x0=AscByte(12+8*i)&0x7f;
  158.           if(x2&1) x0=x0|0x80;
  159.                   s[4*i+1]=x0;
  160.                   s[4*i+2]=AscByte(14+8*i);
  161.                   s[4*i+3]=AscByte(16+8*i);
  162.                 }
  163.                 break;
  164.         }
  165.     Tnum=0; Tptr=0;
  166.         ByteAsc(Addr);
  167.     Tbuf[Tnum++]='#';
  168.     Tbuf[Tnum++]='#';
  169.         SetLRC();
  170.   }
  171.   Rnum=0; Rptr=0;
  172. }

  173. void timer0() interrupt 1  //定时对串口收到的数据包进行处理
  174. {
  175.   TH0=tim0>>8; TL0=tim0;
  176.   if(RECV)
  177.   {
  178.     RECV=0;
  179.     if(ChkLRC()) //先进行数据效验
  180.     {
  181.       if(AscByte(0)==Addr) KingASC();  //地址是本机则进行协议的处理
  182.     }
  183.   }
  184. }

  185. void Init() //对定时器及串口进行初始化
  186. {
  187.   EA=1; ES=1; ET0=1;
  188.   TMOD=0X21; IP=0x10;
  189.   SCON=0X50; PCON=0X80;     
  190.   TH1=BPS19200; TR1=1;   //串口波特率的设置
  191.   TH0=tim0>>8; TL0=tim0; TR0=1;
  192. }



  193. 主函数:
  194. #include <reg52.h>
  195. #include <glzxj.h>  //对协议的引用

  196. ///////////////////////////////////////////////////////
  197. main()
  198. {
  199.   Init(); //资源的初始化
  200.   DatB[0]=0xff; DatB[1]=0xff;
  201.   DatW[0]=123;  DatW[1]=234;
  202.   DatW[2]=345;  DatW[3]=456;
  203.   DatF[0]=-1.123;  DatF[1]=-1.145;
  204.   DatF[2]=10.123;  DatF[3]=100.145;
  205.   Addr=1; //单片机地址设置
  206.   while(1)
  207. ……………………

  208. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
组态王单片机ASCII协议编程.rar (25.66 KB, 下载次数: 102)


评分

参与人数 1黑币 +30 收起 理由
2bsheep + 30 赞一个!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:380052 发表于 2018-8-29 23:22 | 只看该作者
非常感谢楼主的分享
回复

使用道具 举报

板凳
ID:343192 发表于 2019-7-6 14:40 | 只看该作者
组态王的那部分怎么做,想知道组态王怎么和Proteus连接起来
回复

使用道具 举报

地板
ID:728133 发表于 2020-4-13 13:03 | 只看该作者
是我需要的
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表