瑾熙JXD电磁流量计网络通讯协议
(瑾熙JXD CP V1.1)
通讯协议针对瑾熙JXD电磁流量计工业应用设计,版本:瑾熙JXD CP V1.1,该版本主要用于实时数据采集、流量测量及流量累计控制。
一、主机系统通讯部件要求
国际标准RS-485通讯接口部件,不小于10 Bytes 的通信缓冲区(FIFO),支持600、1200、2400、4800、9600、14400通讯波特率,支持半双工通讯模式。通讯程序应允许FIFO,从机要求主机FIFO不小于10Bytes。
二、协议结构
瑾熙JXD CP V1.1协议遵从基本开放系统互连(OSI)参考模型,基本开放系统互连参照模型提供通讯系统基本结构和要素,但瑾熙JXD CP V1.1协议使用简化的OSI参照模型,仅采用1、2和7层。
基本开放系统互连参考模型
层号 | 层名 | 功能 | 瑾熙JXDCP V1.1 |
7 | 应用层 | | L-magCP 命令 |
6 | 表示层 | | |
5 | 会话层 | | |
4 | 传输层 | | |
3 | 网络层 | | |
2 | 链路层 | 数据链路连接 | L-mag CP Link |
1 | 物理层 | 设备连接 | RS-485 |
三、瑾熙JXDCP V1.1物理结构
瑾熙JXD电磁流量计的网络通讯接口在物理结构上采用电气隔离方式,隔离电压1500伏。通讯数据传输接口为半双工方式,标准通讯速率大于250khz,通讯方向转换时间3.5uS。通讯接口电气标准遵从RS-485国际标准。
瑾熙JXD CP V1.1协议可用于星型式网络结构和总线式网络结构。标准通讯连接介质为屏蔽双绞线。
四、瑾熙JXD CP V1.1主机信息结构
瑾熙JXD CP V1.1协议为主从扫描式通讯协议,每次通讯过程均由主机发起,然后从机进行响应,回传规定的信息,完成一次通讯过程。
主机至从机信息结构
从机地址编码(byte) | 数据分类命令(byte) |
主机发送至从机的信息由两字节组成,**字节为从机地址,其编码:0---127(*高二进制位另有定义),**字节为数据分类命令(下表定义)。从机通讯缓冲区(FIFO)为两字节,因此,主机发送至从机的两字节可连续发送,不必留时间间隔。
从机工作在多机通讯方式,因此,主机应使用11位串行数据格式,并且不使用奇偶校验,将奇偶校验位作多机通讯寻址标志使用。主机发送**个字节时,奇偶校验位强制为1,发送**个字节时,奇偶校验位强制为0。(见附录一)
数据分类命令
命令编码 | 命令定义 | 命令编码 | 命令定义 |
00 | 瞬时流量 | 05 | 反向流量累积值 |
01 | 瞬时流速 | 06 | 流量计报警状态 |
02 | 瞬时流量百分比 | 07 | 流量计管道直径 |
03 | 流体电导比(空管) | 08 | 禁止流量累计 |
04 | 正向流量累积值 | 09 | 启动流量累计 |
10~13 | 备用 | 09 | 连发六次切换到设置状态 |
数据分类命令指示从机回送的数据类型,数据分类命令编码:0---127,瑾熙JXD CP V1.1 仅使用0—9号编码,其他编码暂时保留。
五、 瑾熙JXD CP V1.1从机信息结构
从机接受到主机命令信息后,按命令要求回传测量数据。
从机响应信息数据结构
从机地址 | 命令 | D0 | D1 | D2 | D3 | D4 | D5 | 校验和 | 结束标志 |
从机响应主机命令,回送10个字节数据,分为命令段、数据段、校验和、结束标志四部分。
1、 命令段
命令段由两字节组成:从机地址和数据分类命令,该段是将主机发来的信息直接返回,用于主机校验从机对主机传送信息中地址和命令响应的正确性。
2、 数据段
由于流量计各测量数据长度、单位、符号等信息各不相同,因此,从机回传的数据段按各命令具体定义。
1)流量信息定义
数据段的D4、D3、D2、D1、D0五个字节组成十位流量测量数据,每字节表示两位十进制数,每字节表示的十进制数值范围:0----99。
数据字节 | D4 D3 D2 D1 D0 |
十进制位 | B9B8 B7B6 B5B4 B3B2 B1B0 |
主机恢复流量测量值十进制数据的算法:
a) 流动方向
将D4D3D2D1D0 恢复成十六进制数据 DATA_HEX;
若:DATA_HEX < 80000000H 则 流动方向为正;
若:DATA_HEX >= 80000000H 则 流动方向为负;
b) 原数据
将DATA_HEX中的*高位(符号位)消掉,得到无符号原数据;
即:原数据 = DATA_HEX 与 7FFFFFFFH;
流量测量数据*大值为:99999
D5字节以段位方式定义流量单位、小数点位置:
D5位定义
D5的二进制位 | B7 | B6 B5 B4 | B3 B2 B1 B0 |
位段定义 | 0 | 流量单位 | 小数点位置 |
流量单位定义: 0----L/S(升/秒);
1----L/M(升/分);
2----L/H(升/时);
3----M3/S(立方米/秒);
4----M3/M(立方米/分);
5----M3/H(立方米/时)。
小数点位置: 4 -------±.00000;
5 -------±0.0000;
6 -------±00.000;
7 -------±000.00;
8 -------±0000.0;
9 -------±00000;
10 -------±00000 * 10;
.
.
.
13-------±00000 * 10000;
2)流速信息定义
数据段的D4、D3、D2、D1、D0五个字节组成十位流速测量数据,每字节表示两位十进制数,每字节表示的十进制数值范围:0----99。
数据字节 | D4 D3 D2 D1 D0 |
十进制位 | B9B8 B7B6 B5B4 B3B2 B1B0 |
主机恢复流速十进制数据的算法:
a) 流动方向
将D4D3D2D1D0 恢复成十六进制数据 DATA_HEX;
若:DATA_HEX < 80000000H 则 流动方向为正;
若:DATA_HEX >= 80000000H 则 流动方向为负;
b) 原数据
将DATA_HEX中的*高位(符号位)消掉,得到无符号原数据;
即:原数据 = DATA_HEX 与 7FFFFFFFH;
流量测速数据*大值为:19.999
D5无定义:
流速单位固定: M/S(米/秒);
数点位置固定: ±00.000。
3)流量百分比信息定义
数据段的D4、D3、D2、D1、D0五个字节组成十位流量百分比测量数据,每字节表示两位十进制数,每字节表示的十进制数值范围:0----99。
数据字节 | D4 D3 D2 D1 D0 |
十进制位 | B9B8 B7B6 B5B4 B3B2 B1B0 |
主机恢复流量百分比十进制数据的算法:
a) 流动方向
将D4D3D2D1D0 恢复成十六进制数据 DATA_HEX;
若:DATA_HEX < 80000000H 则 流动方向为正;
若:DATA_HEX >= 80000000H 则 流动方向为负;
b) 原数据
将DATA_HEX中的*高位(符号位)消掉,得到无符号原数据;
即:原数据 = DATA_HEX 与 7FFFFFFFH;
流量测量百分比数据*大值为:999.99
D5无定义:
流体方向定义:0-----流体正向流动;
1-----流体反向流动。
流量百分比单位固定: ﹪
数点位置固定: ±0000.0﹪
4)流体电导比信息定义
数据段的D4、D3、D2、D1、D0五个字节组成十位电导比测量数据,每字节表示两位十进制数。
数据字节 | D4 D3 D2 D1 D0 |
十进制位 | B9B8 B7B6 B5B4 B3B2 B1B0 |
主机恢复流体电导比十进制数据的算法:
原数据 = 10000 * D2 + 100 * D1 + D0;
流体电导比测量数据*大值为:999.9
D5无定义。
流体电导比单位固定: ﹪;
小数点位置固定: 000.0﹪。
5)正向流量累积信息定义
数据段的D4、D3、D2、D1、D0五个字节组成十位正向流量测量数据,每字节表示两位十进制数。
数据字节 | D4 D3 D2 D1 D0 |
十进制位 | B9B8 B7B6 B5B4 B3B2 B1B0 |
主机恢复流量十进制数据的算法:
原数据 = 100000000 * D4 + 1000000 * D3 + 10000 * D2 + 100 * D1 + D0;
流量累积数据*大值为:4294967296(十六进制0FFFFFFFFH)。
D5字节以段位方式定义流量单位、小数点位置:
D5字节位定义
D5的二进制位 | B7 B6 B5 B4 | B3 B2 B1 B0 |
位段定义 | 无定义 | 小数点位置及单位 |
小数点位置及单位: 0 ------- 1L;
1 ------- 0.1L;
2 ------- 0.01L;
3 ------- 0.001L
4 ------- 1m³;
5 ------- 0.1 m³
6 ------- 0.01 m³
7 ------- 0.001 m³
6)反向流量累积信息定义
反向流量累积信息定义同正向流量累积信息定义。
7)报警状态信息定义
数据段的D1、D0两个字节组成二进制报警状态。
数据字节 | D4 D3 D2 D1 D0 |
十进制位 | 无 定 义 BD6…….BD0 |
主机恢复报警状态二进制数据的算法:
原数据(二进制) = D0;
报警状态定义
数据位 | BD7 | BD6 | BD5 | BD4 | BD3 | BD2 | BD1 | BD0 |
定义 | 0 | 0 | 0 | 0 | 励磁 | 空管 | 下限 | 上限 |
8)流量计管径信息定义
数据段的D0字节指示流量计管径。
管径定义 (单位mm)
D0数值 | 代表管径 | D0数值 | 代表管径 | D0数值 | 代表管径 |
00 | 3 | 14 | 200 | 28 | 1600 |
01 | 6 | 15 | 250 | 29 | 1800 |
02 | 10 | 16 | 300 | 30 | 2000 |
03 | 15 | 17 | 350 | 31 | 2200 |
04 | 20 | 18 | 400 | 32 | 2400 |
05 | 25 | 19 | 450 | 33 | 2500 |
06 | 32 | 20 | 500 | 34 | 2600 |
07 | 40 | 21 | 600 | 35 | 2800 |
08 | 50 | 22 | 700 | 36 | 3000 |
09 | 65 | 23 | 800 | | |
10 | 80 | 24 | 900 | | |
11 | 100 | 25 | 1000 | | |
12 | 125 | 26 | 1200 | | |
13 | 150 | 27 | 1400 | | |
9)禁止流量累积信息定义
从机接到该命令后,立即停止流量累积,并回送命令认可信息。停止流量累积延续时间为20秒,20秒后从机自动恢复流量累积计算。因此,若想连续禁止流量累积计算,必须以小于20秒的间隔,向从机发送该命令。该功能可用于断续过程计量。
回送的命令认可信息由数据段的D4、D3、D2、D1、D0五个字节组成。
数据字节 | D4 D3 D2 D1 D0 |
十进制位 | B9B8 B7B6 B5B4 B3B2 B1B0 |
主机恢复命令认可信息码的算法:
命令认可信息码=100000000*D4 + 1000000*D3 + 10000*D2 + 100*D1 + D0;
正确的命令认可信息码 = 2A3A4A5AH(十六进制)。
10)启动流量累积信息定义
从机接到该命令后,立即启动流量累积计算,并回送命令认可信息。该功能可用于断续过程计量。
命令认可信息由数据段的D4、D3、D2、D1、D0五个字节组成。
数据字节 | D4 D3 D2 D1 D0 |
十进制位 | B9B8 B7B6 B5B4 B3B2 B1B0 |
主机恢复命令认可信息码的算法:
命令认可信息码=100000000*D4 + 1000000*D3 + 10000*D2 + 100*D1 + D0;
正确的命令认可信息码 = 5A4A3A2AH(十六进制)。
3.校验和
从机回传的数据校验和为前八个字节的异或和。
异或和(byte8) = byte0 ⊕ byte1 ⊕ byte2 …………byte6 ⊕ byte7;
4.信息块结束标志
从机以结束标志表示本次回传信息块完毕。结束标志编码为:0AAH(通讯结束命令,十六进制格式)。
六、 瑾熙JXD CP V1.1通讯过程时序
通讯过程时序指编制通讯软件时应遵从的时间间隔、延时、等待时间等。
1. 主机发送时序
主机发送的两个信息字节间的时间间隔*小为0,*大时间间隔为20毫秒,大于20毫秒,从机认为发送超时。
2. 从机回传时序
从机*小回传响应时间为0,*大为10毫秒 + 11位传送时间。
从机每个回传字节时间间隔*大为10毫秒 + 11位传送时间。
(11位传送时间根据选用波特率计算出)
3. 从机允许的通讯频度
从机允许的通讯频度为20次/每秒,大于该值,可能影响从机其他功能。
七、 瑾熙JXD CP V1.1通讯波特率
瑾熙JXD CP V1.1支持的通讯波特率为:600、1200、2400、4800、9600、14400。
八、瑾熙JXD CP V1.1通讯数据块侦错信息
1. 从机地址和数据分类命令回传,主机可用于校对从机是否正确响应;
2. 从机回传字节异或和校验,主机可用于校对是否有数据位错误;
3. 从机回传字节中B7 = 0为数据字节,B7 = 1为命令字节;
4. 从机回传字节中的数据字节值不大于99;
5. 从机回传字节数长度固定,共十字节长度,主机可做长度检验;
6. 从机回传结束标志,主机可用于长度检验和数据字节定位。
九、标准通讯网络连接图
2010年10月12日
附录一 通讯实验程序
(MSDOS TURBO C)
#incLude<stdio.h>
#incLude<io.h>
/* MODE setting */
#define BIT_5 0x00 /* Word 兰申Length define */
#define BIT_6 0x01
#define BIT_7 0x02
#define BIT_8 0x03
#define STOP_1 0x00 /* Stop bits define */
#define STOP_2 0x04
#define P_EVEN 0x18 /* Parity define */
#define P_ODD 0x08
#define P_SPC 0x38 /* Set tb = 0 */
#define P_MARK 0x28 /* Set tb = 1 */
#define P_NONE 0x00
#define I_RDA 0x01 /* EnabLe recieve-data-avaiLabLe interrupt */
#define I_TRE 0x02 /* EnabLe transmitter-hoLding-register-empty interrupt */
#define I_RLS 0x04 /* EnabLe recieve-Line-status interrupt */
#define I_MS 0x08 /* EnabLe modem-status interrupt */
#define I_NON 0x00 /* DisabLe interrupt */
#define B600 0xc0
#define B1200 0x60
#define B2400 0x30
#define B4800 0x18
#define B9600 0x0C
#define B14400 0x08
#define COM1_ADDR 0x3e8
unsigned char COMM_Buf[100];
unsigned char baud_rate;
unsigned int error_cnt;
void SioInit_1(void)
{
outportb(COM1_ADDR + 2, 0xcf); /* EnabLe FIFO and cLear FIFO */
outportb(COM1_ADDR + 3, 0x80); /* Set DLAB = 1 */
/* Set bps */
outportb(COM1_ADDR, baud_rate % 256);
outportb(COM1_ADDR + 1, baud_rate / 256);
outportb(COM1_ADDR + 3, BIT_8 | STOP_1 | P_MARK); /* 11 bits mode & P = 1 */
outportb(COM1_ADDR + 1, I_NON); /* disabLe interrupt */
}
void SioInit_0(void)
{
outportb(COM1_ADDR + 2, 0xcf); /* EnabLe FIFO and cLear FIFO */
outportb(COM1_ADDR + 3, 0x80); /* Set DLAB = 1 */
/* Set bps */
outportb(COM1_ADDR, baud_rate % 256);
outportb(COM1_ADDR + 1, baud_rate / 256);
outportb(COM1_ADDR + 3, BIT_8 | STOP_1 | P_SPC); /* 11 bits mode & P = 0 */
outportb(COM1_ADDR + 1, I_NON); /* disabLe interrupt */
}
int SioRecieve()
{ unsigned k;
for (k=0;k<10000;k++)
{if((inportb(COM1_ADDR + 5) & 1) == 1)
{ return inportb(COM1_ADDR); }
deLay(1);
}
return 0;
}
void SioSend(unsigned char data)
{ outportb(COM1_ADDR,data); /* Send data */
whiLe((inportb(COM1_ADDR + 5) & 0x40) == 0){}
}
main()
{ int i;
unsigned char ch_n;
unsigned char ch;
int cnnt;
baud_rate = B14400;
cnnt=0;
error_cnt = 0;
ch_n = 0;
for(;;) {
SioInit_1();
cnnt++;
cprintf("%03d ",cnnt);
cprintf("Send Data ");
ch = 0x03;
SioSend(ch);
outportb(COM1_ADDR + 3, BIT_8 | STOP_1 | P_SPC);
SioSend(ch_n);
ch_n = (ch_n + 1) & 7;
for (i=0;i<10;i++) { COMM_Buf[i] = SioRecieve(); }
de兰申Lay(20);
for (i=0;i<10;i++) { cprintf("%03d ",COMM_Buf[i]); }
if ((COMM_Buf[9] != 0xaa) && (COMM_Buf[9] != 0)) { error_cnt++; }
cprintf("%05d\n\r",error_cnt);
deLay(20);
}
}