请问你有组态王与单片机通讯的实例么?

2021-11-04 科技 226阅读
*组态协议:字头设备地址标志数据地址数据字节数数据…异或CR
*字头:1字节1个ASCII码,40H
*设备地址:1字节2个ASCII码,0—255(即0---0x0ffH)
*标志:1字节2个ASCII码,bit0~bit7,//把接收值将它发出即可
*bit0=0:读,bit0=1:写。
*bit1=0:不打包。
*bit3bit2=00,数据类型为字节。
*bit3bit2=01,数据类型为字。
*bit3bit2=1x,数据类型为浮点数。
*数据地址:2字节4个ASCII码,0x0000~0xffff//把接收值将它发出即可
*数据字节数:1字节2个ASCII码,1—100,实际读写的数据的字节数。//把接收值将它发出即可
*数据…:为实际的数据转换为ASCII码,个数为字节数乘2。
*异或:异或从设备地址开始异或,到异或字节前结束得异或值,异或值转换成2个ASCII码
*//如得0x4b,对应Ascll为0x34和0x42.
*CR:0x0d。
*/////////
//读格式为:字头设备地址标志数据地址数据字节数异或CR
//写格式:字头设备地址标志数据地址数据字节数数据…异或CR

#include"reg52.h"
#defineucharunsignedchar
#defineCTH00xfe
#defineCTL00x0c

sbitled1=P2^7;//定义LED.
sbitled2=P2^6;
sbitled3=P2^5;
sbitled4=P2^4;
//unsignedchari10=0;//收数据标

//unsignedintj=0;//动态显示数据用
unsignedchari=0;//动态显示用
intj=0;////调试用
unsignedchark=0;////调试用1~100.
//unsignedchark4=0;//K4为发送的数据;K6为组态下传数据标志。k6=0;
intk2=0;//接收死机保护。
ucharduan_tabled[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//需要显示的段选码

charpp1[22]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0a,0x0a,0x0a,0x0a,
0x0a,0x0a,0x0a,0x0a,0x0a,0x0a};//接收上位机读写暂存
charpp2[10]={0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d};//数据发送暂存

ucharpp3[8]={0x40,0x00,0x00,0x2a,0x2a,0x00,0x00,0x0d};//ucharpp4[8]={0x40,0x00,0x00,0x23,0x23,0x37,0x36,0x0d};//

delay(unsignedinti)//延时子程序。
{
unsignedintj=0;
for(;j<=i;j++);;;
}

voidInit()//初始化
{
//TMOD=0x01;
TMOD=0X21;//设置T1为方式2
TH0=CTH0;//1MS
TL0=CTL0;
ET0=1;
TR0=1;

EX0=1;
IT0=1;

TH1=0Xfd;//设置波特率为9600
TL1=0Xdf;
SCON=0X50;//设置串口位方式1
PCON=0X00;
//SPCTL=0x4d;
TR1=1;//定时器1开始计数
ES=1;
EA=1;
}

voidtimer0()interrupt1//显示中断;前两位调试用,
//第三位显示——接收上位机读写暂存——的第几位.
{//第四位显示对比。
TH0=CTH0;
TL0=CTL0;
i++;
if(i==5)
{
P0=duan_tabled[pp1[21]%10];//第二位显示上面传下来的数据的个位
P1=0xfd;
}
if(i==10)
{

P0=duan_tabled[pp1[21]/10];//第一位显示上面传下来的数据的十位
P1=0xfe;
}

if(i==15)
{
P0=duan_tabled[k%10];//第三位////K调试用1~100显示
P1=0xf7;
}
if(i==20)
{
P0=duan_tabled[k/10];//第四位
P1=0xfb;
i=0;

if(j++>=100){j=0;k++;}////j调试用
}
if(k>=100)k=0;////K调试用,1~100显示
}

voidUART()interrupt4//接收中断,只接收
{

ucharii;
unsignedinttemp;
if(RI)
{
if(SBUF==0x40)//简单判断是否为组态发送数据,否则RI=0。
{
for(ii=0;ii<18;ii++)//不管发多少Bit,按最多收18个Bit。
{
pp1[ii]=SBUF;
RI=0;
if(pp1[ii]==0x0d){k2=1;return;}//也可用break;跳出for语句
temp=0;
while(RI==0&&temp<1000)temp++;//while(!RI&&temp)temp--;也可退出
if(temp>=1000)return;
}
}

}
RI=0;//
}

voidwrite(uchark5)//写子程序,写的格式为:字头设备地址标志数据地址数据字节数异或CR
{
ucharii;//变量
ucharyihou1,yihou2,yihou3;//计算暂存变量
yihou1=pp1[1]^pp1[2]^pp1[3]^pp1[4]^pp1[5]^pp1[6]^pp1[7]^pp1[8]^pp1[9]^pp1[10];
//异或较验;组态协议。
yihou2=yihou1;//转换成ACall码。如73的AsAALL为0x37和0x33
yihou1=yihou1>>4;
yihou2=yihou2&0x0f;
if(yihou2>0x09)yihou2=yihou2-9+0x40;
elseyihou2=yihou2+0x30;
if(yihou1>0x09)yihou1=yihou1-9+0x40;
elseyihou1=yihou1+0x30;///转换
if(yihou1==pp1[11]&&yihou2==pp1[12])//较验
{
pp2[1]=pp1[1];pp2[2]=pp1[2];//放入需发送的内容。
pp2[3]=pp1[9];pp2[4]=pp1[10];//组态协议。
pp2[5]=pp2[6]=k5;//把数据转换成Asall码
pp2[5]=(pp2[5]>>4)&0x0f;
pp2[6]=pp2[6]&0x0f;
if(pp2[5]>=0x0a)
pp2[5]=pp2[5]-9+0x40;//0x0a~0x0f的转换,a对应Ascll值为0x40。
else
pp2[5]=pp2[5]+0x30;//0~9的转换。
if(pp2[6]>=0x0a)
pp2[6]=pp2[6]-9+0x40;
else
pp2[6]=pp2[6]+0x30;
yihou3=pp2[1]^pp2[2]^pp2[3]^pp2[4]^pp2[5]^pp2[6];//取得异域较验值。
pp2[7]=yihou3>>4;
pp2[8]=yihou3&0x0f;
if(pp2[7]>=0x0a)
pp2[7]=(pp2[7]-9)+0x40;
else
pp2[7]=pp2[7]+0x30;
if(pp2[8]>=0x0a)
pp2[8]=(pp2[8]-9)+0x40;
else
pp2[8]=pp2[8]+0x30;
for(ii=0;ii<10;ii++)//发送。
{
SBUF=pp2[ii];
while(!TI);
TI=0;
}
}
else//错误发送见组态协议。
{
pp3[1]=pp1[1];pp3[2]=pp1[2];
yihou3=pp3[1]^pp3[2];//错误代码的较验
pp3[5]=yihou3>>4;//Aacll转换。
pp3[6]=yihou3&0x0f;
if(pp3[5]>=0x0a)
pp3[5]=pp3[5]-9+0x40;
else
pp3[5]=pp3[5]+0x30;
if(pp3[6]>=0x0a)
pp3[6]=pp3[6]-9+0x40;
else
pp3[6]=pp3[6]+0x30;
for(ii=0;ii<8;ii++)
{
SBUF=pp3[ii];
while(!TI);
TI=0;
}
}
}

read()//读程序。读格式:字头设备地址标志数据地址数据字节数数据…异或CR
{
ucharii;
ucharyihou1,yihou2,yihou3;
yihou1=pp1[1]^pp1[2]^pp1[3]^pp1[4]^pp1[5]^pp1[6]^pp1[7]^pp1[8]^pp1[9]^pp1[10]^pp1[11]^pp1[12];
yihou2=yihou1;
yihou1=yihou1>>4;
yihou2=yihou2&0x0f;

if(yihou2>0x09)yihou2=yihou2-9+0x40;
elseyihou2=yihou2+0x30;

if(yihou1>0x09)yihou1=yihou1-9+0x40;
elseyihou1=yihou1+0x30;

if(yihou1==pp1[13]&&yihou2==pp1[14])
{

pp4[1]=pp1[1];//取设备地址
pp4[2]=pp1[2];//取设备地址
yihou3=pp1[1]^pp1[2];//异或效验
pp4[5]=yihou3>>4;//异或效验结果转换成ASCII码。
pp4[6]=yihou3&0x0f;

if(pp4[5]>=0x0a)
pp4[5]=pp4[5]-9+0x40;
else
pp4[5]=pp4[5]+0x30;

if(pp3[6]>=0x0a)
pp4[6]=pp4[6]-9+0x40;
else
pp4[6]=pp4[6]+0x30;

for(ii=0;ii<8;ii++)
{
delay(100);
SBUF=pp4[ii];
while(!TI);
TI=0;
}
}
else
{
pp3[1]=pp1[1];
pp3[2]=pp1[2];
yihou3=pp3[1]^pp3[2];
pp3[5]=yihou3>>4;
pp3[6]=yihou3&0x0f;

if(pp3[5]>=0x0a)
pp3[5]=pp3[5]-9+0x40;
else
pp3[5]=pp3[5]+0x30;

if(pp3[6]>=0x0a)
pp3[6]=pp3[6]-9+0x40;
else
pp3[6]=pp3[6]+0x30;

for(ii=0;ii<8;ii++)
{
SBUF=pp3[ii];
while(!TI);
TI=0;
}
}
}

main()
{
unsignedchark4=0;
//delay(1000);
//ucharii;
Init();//初始化
while(1)
{
if(k2==1)//
{
k2=0;
if(pp1[4]==0x30)//pp1[4]判断组态是要读还是写数据
{
k4=k;
if(pp1[8]==0x31)//
write(k4);
if(pp1[8]==0x32)
write(pp1[21]);
}
if(pp1[4]==0x31)/
{
read();//
pp1[19]=pp1[11];//
pp1[20]=pp1[12];

if(pp1[19]>=0x41)
pp1[19]=pp1[19]-0x37;
else
pp1[19]=pp1[19]-0x30;

if(pp1[20]>=0x41)
pp1[20]=pp1[20]-0x37;
else
pp1[20]=pp1[20]-0x30;

pp1[19]=pp1[19]<<4;
pp1[21]=(pp1[19]&0xf0)|(0x0f&pp1[20]);
}
}
}
}
声明:你问我答网所有作品(图文、音视频)均由用户自行上传分享,仅供网友学习交流。若您的权利被侵害,请联系fangmu6661024@163.com