被寻址下位机通过指令清除SM2,以便正常接收上位机发送来的数据,并向上位机发回接收到的地址以便核实。未被寻址的下位机保持SM2=1,并退出各自的中断服务程序;
完成上位机和被寻址下位机之间的数据通信后,被寻址从机使SM2=1,并退出中断服务程序,等待下次通信。 6 结束语
该系统实现组态王软件与单片机多机的实时通信,已经在实际项目中得到应用。应用的结果表明该设计方法简单有效,实时性好,成本低廉,可以在控制与监控系统中推广应用。
组态王与单片机协议
作者:XueShuWang.com
阅读次数:128次 更新时间:2008-2-3 1:07:13
1.通讯口设置:
通讯方式:RS-232,RS-485,RS-422均可。 波特率: 由单片机决定。 字节数据格式:
起始位、数据位、停止位均由单片机决定。
2.设备地址设置
格式:##.# (前面的两个字符是设备地址,范围为0-255;后面的一个字符是用户设定是否打包,“0”为不打包、“1”为打包。)
3.寄存器设置 寄存器名称 X
上限 65535 下限 0 数据类型 FLOAT/BYTE/UINT
4.格式:读写格式(除字头外所有字节均为ASCII码)
字头 说明; 字头:1字节,40H
设备地址: 2字节,0—255(即0---0x0ffH)
标志:1字节,bit0~bit7,bit0= 0:读,bit0= 1:写。Bit1= 0:不打包, bit3bit2 = 00,数据类型为字节。 bit3bit2 = 01,数据类型为字。 bit3bit2 = 1x,数据类型为浮点数。 数据地址: 2字节,0x0000~0xffff
数据字节数:1字节,1—100,实际读写的数据的字节数。 数据?:为实际的数据
异或:异或从设备地址到异或字节前 CR:0x0d。
5.上位机发送读命令 字头 设备地址 标志 数据地址 数据字节数 异或 CR 设备地址 标志 数据地址 数据字节数 数据? 异或 CR 下位机应答:若正常: 字头 设备地址 数据字节数 数据? 异或 CR 若不正常: 字头
例:读12号仪表,数据地址为15的数据。其中数据为255,数据类型为字节,不打包。所发数据为:
设备地址 ** 异或 CR
40 30 43 30 30 30 30 30 46 30 31 34 34 0d 若正确: 40 30 43 30 30 0x46 0x46 37 33 0d 若不正确: 40 30 43 2a 2a 37 33 0d 4.上位机发送写命令 字头 设备地址 标志 数据地址 数据字节数 数据? 异或 CR 下位机应答:若正常: 字头 设备地址 ## 异或 CR 若不正常: 字头
例:写12号仪表,数据地址为15。其中数据为255,数据类型为字节,不打包。所发数据为: 40 30 43 30 31 30 30 30 46 30 31 46 46 34 35 0d 设备地址 ** 异或 CR 若正确: 40 30 43 23 23 37 33 0d 若不正确: 40
6.浮点数格式: 7.此浮点数格式的转换: 1) ASCII码到浮点数: /* in:char* c
要转化的ASII码字符,应为4个字符。 Return :转换后的浮点数。
30 43 2a 2a 37 33 0d
*/
float C4toD(char * c) {
if((c[6] > 0x40) && (c[6] < 0x47))
Hd[6] = ((c[6] - 0x37) & 0x0f); if((c[7] > 0x40) && (c[7] < 0x47))
Hd[7] = ((c[7] - 0x37) & 0x0f); float returnflo = 0;
BOOL ShuFU = FALSE, JieFU = FALSE; memset(Hd, 0, sizeof(Hd)); memset(Jiema, 0, sizeof(Jiema)); memset(DTc, 0, sizeof(DTc)); BYTE Hd[30], Jiema[30]; float DTc[30]; float Decimal = 0;
else if((c[7] > 0x60) && (c[7] < 0x67))
Hd[7] = ((c[7] - 0x57) & 0x0f);
else
Hd[7] = ((c[7] - 0x30) & 0x0f);
else if((c[6] > 0x60) && (c[6] < 0x67))
Hd[6] = ((c[6] - 0x57) & 0x0f);
else
Hd[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);
else
Hd[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);
else
Hd[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);