組態王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
|