当前位置:文档之家› 组态王与单片机通信协议1

组态王与单片机通信协议1

一、通讯参数:通讯参数包括数据位,停止位,波特率、校验方式。

数据位、停止位、波特率由单片机决定。

组态王中的设定和单片机一致即可。

校验方式参照“数据传输格式”中相关部分。

二、数据传输格式:格式1、组态王发送地址请求格式:(此时检验位为1)ENQ Sta EOT CRC格式2、单片机应答地址格式:(此时检验位为0)ACK Sta ETX CRC格式3、组态王读数据请求格式:(此时检验位为0)ENQ R DataType DataAddr DataNum EOT CRC格式4、单片机应答读数据格式(正确):(此时检验位为0)ACK DataLong Data….ETX CRC格式5、单片机应答读数据格式(错误):(此时检验位为0)NAK ErrorCode ETX CRC格式6、组态王写数据请求格式:(此时检验位为0)ENQ W DataType DataAddrData….EOT CRC格式7、单片机应答写数据格式(正确):(此时检验位为0)ACK ErrorCode ETX CRC三、时序:读数据:组态王单片机第一步:格式1第二步:格式2第三步:格式3第四步:格式4或格式5 第五步:如果第四步单片机执行格式4,结束。

否则,执行格式1。

第六步:格式2第七步:格式3第八步:格式4或格式5写数据:组态王单片机第一步:格式1第二步:格式2第三步:格式6第四步:格式7第五步:如果第四步单片机执行格式7的ErrorCode=0,结束。

否则,执行格式1。

第六步:格式2第七步:格式6第八步:格式7四、协议说明:数据传输:所有数据均为16进制数ENQ(头) H05 询问请求帧的开始代码ACK(头) H06 确认ACK应答帧的开始代码NAK(头) H15 否认NAK应答帧的开始代码EOT(尾) H04 正文的结束请求帧的结束ASCII代码ETX(尾) H03 结束正文应答帧的结束ASCII代码Sta::设备地址1字节R:读标志1字节(0x52)W:写标志1字节(0x57)DataType;需要交换的数据类型,1字节。

1,字节;2,字,3,浮点型。

DataType的值含义1 字节2 字3 浮点数DataNum:要读取的数据的数量,1字节。

DataAddr;为数据偏移地址2字节,低字节在前,高字节在后Data:实际传输的数据,低字节在前,高字节在后DataLong: 单片机返回Data的字节数,2字节,低字节在前,高字节在后CRC:为从第一个字节至CRC前的所有字节的异或值,1字节ErrorCode:ErrorCode数值含义0 正确应答1 数据类型错误2 数据范围超限3 指令无法识别,应为R或W。

4 校验错误1.通讯口设置:通讯方式:RS-232,RS-485,RS-422均可。

波特率:由单片机决定(2400,4800,9600and19200bps)。

字节数据格式:由单片机决定。

起始位数据位校验位停止位注意:在组态王中设置的通讯参数如波特率,数据位,停止位,奇偶校验必须与单片机编程中的通讯参数一致2.在组态王中定义设备地址的格式格式:##.#前面的两个字符是设备地址,范围为0-255,此地址为单片机的地址,由单片机中的程序决定;后面的一个字符是用户设定是否打包,“0”为不打包、“1”为打包,用户一旦在定义设备时确定了打包,组态王将处理读下位机变量时数据打包的工作。

3.在组态王中定义的寄存器格式寄存器名称dd上限dd下限数据类型X dd65535 0 FLOAT/BYTE/UINT斜体字dd代表数据地址,此地址与单片机的数据地址相对应。

注意:在组态王中定义变量时,一个X寄存器根据所选数据类型(BYTE,UINT,FLOAT)的不同分别占用一个、两个,四个字节,定义不同的数据类型要注意寄存器后面的地址,同一数据区内不可交叉定义不同数据类型的变量。

为提高通讯速度建议用户使用连续的数据区。

例如,1、在单片机中定义从地址0开始的数据类型为BYTE型的变量:则在组态王中定义相应的变量的寄存器为X0、X1、X2、X3、X4。

,数据类型为BYTE,每个变量占一个字节2、在单片机中定义从地址100开始的数据类型为UINT型的变量:则在组态王中定义相应的变量的寄存器为X100、X102、X104、X106、X108。

,数据类型UINT,每个变量占两个字节3、在单片机中定义从地址200开始的数据类型为FLOAT型的变量:则在组态王中定义相应的变量的寄存器为X200、X204、X208、X212。

,数据类型FLOAT,每个变量占四个字节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.上位机发送读命令字头设备地址标志数据地址数据字节数异或CR下位机应答:若正常:字头设备地址数据字节数数据…异或CR若不正常:字头设备地址** 异或CR例1:读15号仪表,数据地址为15的数据。

其中数据为100,数据类型为字节,不打包。

组态王所发数据为:40 30 46 43 30 30 30 30 46 30 31 37 32 0d字头设备地址15 标志数据地址15 数据字节数1异或读操作字节型不打包若正确:40 30 46 30 31 36 34 37 35 0d字头设备地址15 数据字节数1数据100 异或若不正确:40 30 46 2a 2a 37 36 0d字头设备地址15** 异或例2:读15号仪表,数据地址为15的数据。

其中数据为100,数据类型为字节,打包。

组态王所发数据为:40 30 46 43 32 30 30 30 46 30 31 37 30 0d字头设备地址15标志读操作字节型打包数据地址15 数据字节数1异或若正确:40 30 46 30 31 36 34 37 35 0d字头设备地址15 数据字节数1数据100 异或若不正确:40 30 46 2a 2a 37 36 0d设备地址15** 异或3.2.上位机发送写命令字头设备地址标志数据地址数据字节数数据…异或CR 下位机应答:若正常:字头设备地址## 异或CR若不正常:字头设备地址** 异或CR例1:写15号仪表,数据地址为15。

写数据255,数据类型为字,不打包。

组态王所发数据为:40 30 46 43 35 30 30 30 46 30 32 30 30 46 46 37 34 0d字头设备地址15标志写操作字型不打包数据地址15 数据字节数2数据255 异或若正确:40 30 46 23 23 37 36 0d字头设备地址15## 异或若不正确:40 30 46 2a 2a 37 36 0d字头设备地址15** 异或例2:写15号仪表,数据地址为15。

写数据65535,数据类型为浮点型,打包。

组态王所发数据为:40 30 46 43 46 30 30 30 46 30 34 31 30 46 46 46 46 30 30字头设备地址15标志写操作浮点型打包数据地址15 数据字节数4数据6553530 30 0d 异或若正确:40 30 46 23 23 37 36 0d## 异或字头设备地址15若不正确:40 30 46 2a 2a 37 36 0d 字头设备地址** 异或153、注:仪表内部数据为十六进制表示的十进制数。

如:实时测量值为500,则用十六进制表示为1F4H。

仪表通讯传输是将上述十六进制数据转化为标准ASCII 码(即一字节的16进制数转化为2个ASCII码──高4位ASCII码+低4位ASCII 码)。

如:上述数据1F4H(16进制),传输时,转化为ASCII码则为30H、31H、46H、34H。

此浮点数格式的转换:1)ASCII码到浮点数:float C4toD(char * c){BYTE Hd[30], Jiema[30];float DTc[30];float Decimal = 0;memset(Hd, 0, sizeof(Hd));memset(Jiema, 0, sizeof(Jiema));memset(DTc, 0, sizeof(DTc));float returnflo = 0;BOOL ShuFU = FALSE, JieFU = FALSE;if((c[7] > 0x40) && (c[7] < 0x47))Hd[7] = ((c[7] - 0x37) & 0x0f);else if((c[7] > 0x60) && (c[7] < 0x67))Hd[7] = ((c[7] - 0x57) & 0x0f);elseHd[7] = ((c[7] - 0x30) & 0x0f);if((c[6] > 0x40) && (c[6] < 0x47))Hd[6] = ((c[6] - 0x37) & 0x0f);else if((c[6] > 0x60) && (c[6] < 0x67))Hd[6] = ((c[6] - 0x57) & 0x0f);elseHd[6] = ((c[6] - 0x30) & 0x0f);DTc[2] = (float)(((float)(Hd[6] * 16.0) + (float)(Hd[7])) / 256.0);if((c[5] > 0x40) && (c[5] < 0x47))Hd[5] = ((c[5] - 0x37) & 0x0f);else if((c[5] > 0x60) && (c[5] < 0x67))Hd[5] = ((c[5] - 0x57) & 0x0f);elseHd[5] = ((c[5] - 0x30) & 0x0f);if((c[4] > 0x40) && (c[4] < 0x47))Hd[4] = ((c[4] - 0x37) & 0x0f);else if((c[4] > 0x60) && (c[4] < 0x67))Hd[4] = ((c[4] - 0x57) & 0x0f);elseHd[4] = ((c[4] - 0x30) & 0x0f);DTc[1] = (float)((((float)(Hd[4] * 16.0) + (float)Hd[5]) + DTc[2]) / 256.0);if((c[3] > 0x40) && (c[3] < 0x47))Hd[3] = ((c[3] - 0x37) & 0x0f);else if((c[3] > 0x60) && (c[3] < 0x67))Hd[3] = ((c[3] - 0x57) & 0x0f);elseHd[3] = ((c[3] - 0x30) & 0x0f);if((c[2] > 0x40) && (c[2] < 0x47))Hd[2] = ((c[2] - 0x37) & 0x0f);else if((c[2] > 0x60) && (c[2] < 0x67))Hd[2] = ((c[2] - 0x57) & 0x0f);elseHd[2] = ((c[2] - 0x30) & 0x0f);Decimal = (float)(((float)(Hd[2] * 16) + (float)(Hd[3]) + DTc[1])/ 256.0);if((c[1] > 0x40) && (c[1] < 0x47))Jiema[1] = ((c[1] - 0x37) & 0x0f);else if((c[1] > 0x60) && (c[1] < 0x67))Jiema[1] = ((c[1] - 0x57) & 0x0f);elseJiema[1] = ((c[1] - 0x30) & 0x0f);if((c[0] > 0x40) && (c[0] < 0x47))Jiema[0] = ((c[0] - 0x37) & 0x0f);else if((c[0] > 0x60) && (c[0] < 0x67))Jiema[0] = ((c[0] - 0x57) & 0x0f);elseJiema[0] = ((c[0] - 0x30) & 0x0f);ShuFU = ((Jiema[0] & 0x08) >> 3) > 0;JieFU = ((Jiema[0] & 0x04) >> 2) > 0;Jiema[2] = (Jiema[0] & 0x03) * 16 + Jiema[1];if(JieFU)returnflo = (float)pow(2, (-1) * Jiema[2]) * Decimal;elsereturnflo = (float)pow(2, Jiema[2]) * Decimal;if(ShuFU)returnflo = (-1) * returnflo;return returnflo;}2)浮点数到ASCII码:void D4toC(char * c,float d){BYTE i = 0, Jiema = 0;char inbyte1[30];BOOL ShuFu = FALSE, JieFu = FALSE;int inbyte2 = 0, inbyte3 = 0, inbyte4 = 0;char afterbyte2[30], afterbyte3[30], afterbyte4[30];float F_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(int j = 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);i ++;}if(d == 1){for(int j = 2; j < 8; j++)c[j] = 0x46;}else{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;}else if(inbyte2 < 16){c[2] = 0x30;c[3] = afterbyte2[0];}else{c[2] = afterbyte2[0];c[3] = afterbyte2[1];}if(inbyte3 == 0){c[4] = 0x30;c[5] = 0x30;}else if(inbyte3 < 16){c[4] = 0x30;c[5] = afterbyte3[0];}else{c[4] = afterbyte3[0];c[5] = afterbyte3[1];}if(inbyte4 == 0){c[6] = 0x30;c[7] = 0x30;}else if(inbyte4 < 16){c[6] = 0x30;c[7] = afterbyte4[0];}else{c[6] = afterbyte4[0];c[7] = afterbyte4[1];}}if(JieFu){if(i > 0x3f)i = 0x3f;}else if(i > 0x32)i = 32;if(ShuFu)i = i | 0x80;if(JieFu)i = i | 0x40;itoa(i, inbyte1, 16);if(inbyte1 == 0){c[0] = 0x30;c[1] = 0x30;}else if(i < 16){c[0] = 0x30;c[1] = inbyte1[0];}else{c[0] = inbyte1[0];c[1] = inbyte1[1];}for(i = 0; i < 8; i ++){if((c[i] > 0x60) && (c[i] < 0x67))c[i] = c[i] - 0x20;}c[8] = 0x00;}。

相关主题