通用单片机通讯协议组态王与单片机协议 附通用单片机hexWord下载.docx
《通用单片机通讯协议组态王与单片机协议 附通用单片机hexWord下载.docx》由会员分享,可在线阅读,更多相关《通用单片机通讯协议组态王与单片机协议 附通用单片机hexWord下载.docx(23页珍藏版)》请在冰豆网上搜索。
3.组态王与单片机通讯的命令格式:
读写格式(除字头、字尾外所有字节均为ASCII码)
字头
设备地址
标志
数据地址
数据字节数
数据…
异或
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码
CR:
0x0d。
通讯尝试恢复命令(COMERROR),请求地址为0的一个BYTE数据
3.1.上位机发送读命令
下位机应答:
若正常:
若不正常:
**
例1:
读15号仪表,数据地址为15的数据。
其中数据为100,数据类型为字节,不打包。
组态王所发数据为:
40
30
46
43
31
37
32
0d
设备地址15
读操作
字节型
不打包
数据地址15
数据字节数1
若正确:
36
34
35
数据100
若不正确:
2a
例2:
其中数据为100,数据类型为字节,打包。
打包
3.2.上位机发送写命令
##
写15号仪表,数据地址为15。
写数据255,数据类型为字,不打包。
写操作
字型
数据字节数2
数据255
23
写数据65535,数据类型为浮点型,打包。
浮点型
数据字节数4
数据65535
5.浮点数格式:
4字节浮点数=第一字节高4位ASCII码+第一字节低4位ASCII码
+第二字节高4位ASCII码+第二字节低4位ASCII码
+第三字节高4位ASCII码+第三字节低4位ASCII码
+第四字节高4位ASCII码+第四字节低4位ASCII码
第1字节低4位第2字节低4位第3字节低4位第4字节低4位
XXXX
第1字节高4位第2字节高4位第3字节高4位第4字节高4位
★四字节浮点数格式:
(1)第一字节
(2)第二字节
(3)第三字节
(4)第四字节
注:
数符=0——正,数符=1——负阶符=0——正,阶符=1——负
D7D6D5~D0
★浮点数可表示范围:
-1×
232~1×
232
★数符:
1位阶符:
1位阶码:
6位
例:
流量积算控制仪表瞬时流量测量值数据=100.210
转换成浮点数:
100.210=27´
0.7828125=0716+C816+6616+6616
=30ASCII+37ASCII+43ASCII+38ASCII+36ASCII+36ASCII+36ASCII+36ASCII
小数部份:
0.7828125Þ
0.7828125´
256=200.4Þ
0.4´
256=102.4Þ
0.4´
256=102.4
10进制:
第一字节
第二字节
第三字节
第四字节
十六进制:
ASCII码:
传输格式如下:
38
3、注:
仪表内部数据为十六进制表示的十进制数。
如:
实时测量值为500,则用十六进制表示为1F4H。
仪表通讯传输是将上述十六进制数据转化为标准ASCII码(即一字节的16进制数转化为2个ASCII码──高4位ASCII码+低4位ASCII码)。
如:
上述数据1F4H(16进制),传输时,转化为ASCII码则为30H、31H、46H、34H。
6.此浮点数格式的转换:
1)ASCII码到浮点数:
/*
in:
char*c
要转化的ASII码字符,应为4个字符。
Return:
转换后的浮点数。
*/
floatC4toD(char*c)
{
BYTEHd[30],Jiema[30];
floatDTc[30];
floatDecimal=0;
memset(Hd,0,sizeof(Hd));
memset(Jiema,0,sizeof(Jiema));
memset(DTc,0,sizeof(DTc));
floatreturnflo=0;
BOOLShuFU=FALSE,JieFU=FALSE;
if((c[7]>
0x40)&
&
(c[7]<
0x47))
Hd[7]=((c[7]-0x37)&
0x0f);
elseif((c[7]>
0x60)&
0x67))
Hd[7]=((c[7]-0x57)&
else
Hd[7]=((c[7]-0x30)&
if((c[6]>
(c[6]<
Hd[6]=((c[6]-0x37)&
elseif((c[6]>
Hd[6]=((c[6]-0x57)&
Hd[6]=((c[6]-0x30)&
DTc[2]=(float)(((float)(Hd[6]*16.0)+(float)(Hd[7]))/256.0);
if((c[5]>
(c[5]<
Hd[5]=((c[5]-0x37)&
elseif((c[5]>
Hd[5]=((c[5]-0x57)&
Hd[5]=((c[5]-0x30)&
if((c[4]>
(c[4]<
Hd[4]=((c[4]-0x37)&
elseif((c[4]>
Hd[4]=((c[4]-0x57)&
Hd[4]=((c[4]-0x30)&
DTc[1]=(float)((((float)(Hd[4]*16.0)+(float)Hd[5])+DTc[2])/256.0);
if((c[3]>
(c[3]<
Hd[3]=((c[3]-0x37)&
elseif((c[3]>
Hd[3]=((c[3]-0x57)&
Hd[3]=((c[3]-0x30)&
if((c[2]>
(c[2]<
Hd[2]=((c[2]-0x37)&
elseif((c[2]>
Hd[2]=((c[2]-0x57)&
Hd[2]=((c[2]-0x30)&
Decimal=(float)(((float)(Hd[2]*16)+(float)(Hd[3])+DTc[1])/256.0);
if((c[1]>
(c[1]<
Jiema[1]=((c[1]-0x37)&
elseif((c[1]>
Jiema[1]=((c[1]-0x57)&
Jiema[1]=((c[1]-0x30)&
if((c[0]>
(c[0]<
Jiema[0]=((c[0]-0x37)&
elseif((c[0]>
Jiema[0]=((c[0]-0x57)&
Jiema[0]=((c[0]-0x30)&
ShuFU=((Jiema[0]&
0x08)>
>
3)>
0;
JieFU=((Jiema[0]&
0x04)>
2)>
Jiema[2]=(Jiema[0]&
0x03)*16+Jiema[1];
if(JieFU)
returnflo=(float)pow(2,(-1)*Jiema[2])*Decimal;
else
returnflo=(float)pow(2,Jiema[2])*Decimal;
if(ShuFU)
returnflo=(-1)*returnflo;
returnreturnflo;
}
2)浮点数到ASCII码:
char*c:
存储浮点数转换后的ASCII码字符。
Floatd:
要转换的浮点数。
无。
voidD4toC(char*c,floatd)
BYTEi=0,Jiema=0;
charinbyte1[30];
BOOLShuFu=FALSE,JieFu=FALSE;
intinbyte2=0,inbyte3=0,inbyte4=0;
charafterbyte2[30],afterbyte3[30],afterbyte4[30];
floatF_afterbyte2=0,F_afterbyte3=0,F_afterbyte4=0;
memset(inbyte1,0x30,sizeof(inbyte1));
memset(afterbyte2,0x30,sizeof(afterbyte2));
memset(afterbyte3,0x30,sizeof(afterbyte3));
memset(afterbyte4,0x30,sizeof(afterbyte4));
inbyte1[10]=0x0;
afterbyte2[10]=0x0;
afterbyte3[10]=0x0;
afterbyte4[10]=0x0;
if(d==0)
{
for(intj=0;
j<
8;
j++)
c[j]=0x30;
return;
}
if(d<
0)
ShuFu=TRUE;
d=(-1)*d;
while(d>
1)
d=(float)(d/2.0);
i++;
while(d<
=0.5)
JieFu=TRUE;
d=(float)(d*2.0);
if(d==1)
for(intj=2;
c[j]=0x46;
}
{
inbyte2=(int)(d*256);
F_afterbyte2=(d*256)-(int)(d*256);
inbyte3=(int)(F_afterbyte2*256);
F_afterbyte3=(F_afterbyte2*256)-(int)(F_afterbyte2*256);
inbyte4=(int)(F_afterbyte3*256);
F_afterbyte4=(F_afterbyte3*256)-(int)(F_afterbyte3*256);
itoa(inbyte2,afterbyte2,16);
itoa(inbyte3,afterbyte3,16);
itoa(inbyte4,afterbyte4,16);
if(inbyte2==0)
{
c[2]=0x30;
c[3]=0x30;
}
elseif(inbyte2<
16)
c[3]=afterbyte2[0];
else
c[2]=afterbyte2[0];
c[3]=afterbyte2[1];
if(inbyte3==0)
c[4]=0x30;
c[5]=0x30;
elseif(inbyte3<
c[5]=afterbyte3[0];
c[4]=afterbyte3[0];
c[5]=afterbyte3[1];
if(inbyte4==0)
c[6]=0x30;
c[7]=0x30;
elseif(inbyte4<
c[7]=afterbyte4[0];
c[6]=afterbyte4[0];
c[7]=afterbyte4[1];
if(JieFu)
if(i>
0x3f)
i=0x3f;
elseif(i>
0x32)
i=32;
if(ShuFu)
i=i|0x80;
i=i|0x40;
itoa(i,inbyte1,16);
if(inbyte1==0)
c[0]=0x30;
c[1]=0x30;
elseif(i<
c[1]=inbyte1[0];
c[0]=inbyte1[0];
c[1]=inbyte1[1];
for(i=0;
i<
i++)
if((c[i]>
(c[i]<
c[i]=c[i]-0x20;
c[8]=0x00;
一、通讯参数:
通讯参数包括数据位,停止位,波特率、校验方式。
数据位、停止位、波特率由单片机决定。
组态王中的设定和单片机一致即可。
校验方式参照“数据传输格式”中相关部分。
二、数据传输格式:
格式1、组态王发送地址请求格式:
(此时检验位为1)
ENQ
Sta
EOT
CRC
格式2、单片机应答地址格式:
(此时检验位为0)
ACK
ETX
格式3、组态王读数据请求格式:
R
DataType
DataAddr
DataNum
格式4、单片机应答读数据格式(正确):
DataLong
Data….
格式5、单片机应答读数据格式(错误):
NAK
ErrorCode
格式6、组态王写数据请求格式:
W
格式7、单片机应答写数据格式(正确):
三、时序:
读数据:
组态王
单片机
第一步:
格式1
第二步:
格式2
第三步:
格式3
第四步:
格式4或格式5
第五步:
如果第四步单片机执行格式4,结束。
否则,执行格式1。
第六步:
第七步:
第八步:
写数据