一.向仪表读取测量值:
| 1.单回路(单通道系列仪表)指令详解: | |
|---|---|
| 发送指令: | D10A【8Bytes】 |
| 指令详解: | 01(仪表地址)03(功能码)1001(寄存器地址)0001(读取字数WORD)D10A(CRC16-ModBus RTU校验)【8Bytes】 |
| 仪表返回: | FD79C5【7Bytes】 |
| 指令详解: | 01(仪表地址) 03(功能码) 02(返回字节数BYTE) 00 FD(返回的测量值) 79 C5 (CRC16-ModBus RTU校验)【7Bytes】 |
| 解析返回值: | 仪表返回值:00FD(H)=>253(十进制)也就是测量值为253 |
| 2.多回路仪表(如:四路温控仪,16路巡检仪) | |
| A单读指令: | 01(仪表地址)03(功能码)1001(寄存器地址)0001(读取字数WORD)D10A(CRC16-ModBus RTU校验)【8Bytes】 |
| A仪表返回: | 01(仪表地址) 03(功能码) 02(返回字节数BYTE) 00 FE(返回的测量值) 79 C5 (CRC16-ModBus RTU校验)【7Bytes】 |
| A解析返回值: | 00FE(H)=>254(十进制)也就是测量值为254 |
| B多读指令: | 01(仪表地址)03(功能码)1001(寄存器地址)0004(读取字数WORD)D10A(CRC16-ModBus RTU校验)【8Bytes】 |
| B仪表返回: | 01(仪表地址) 03(功能码) 08(返回字节数BYTE) 00 FD 00 FA 00 FC 00 FE(返回的测值量) 20 BC (CRC16-ModBus RTU校验)【13Bytes】 |
| B解析返回值: | 00FD(H)=>253(十进制)通道1=253,00FA(H)=>250(十进制)通道2=250,00FC(H)=>252(十进制)通道3=252,00FE(H)=>254(十进制)通道4=254 |
二.向仪表写入设定值:
| 1.向仪表寄存器0000写入数值250 | |
|---|---|
| 发送指令: | 01(仪表地址) 06(功能码) 00 00(寄存器地址) 00 FA(写入设定值) 09 89(CRC16-ModBus RTU校验)【8Bytes】 |
| 仪表返回: | 原样返回:FA0989【8Bytes】 |
| 解析返回值: | 向寄存器0000写入数值250 |
| 2.向仪表寄存器0001写入数值-128 | |
| 发送指令: | 01(仪表地址) 06(功能码) 00 01(寄存器地址) FF 80(写入数值) 98 5A(CRC16-ModBus RTU校验)【8Bytes】 |
| 仪表返回: | 原样返回:01 06 00 01 FF 80 98 5A【8Bytes】 |
| 解析返回值: | 向寄存器0001写入数值-128 |
三.CRC16-ModBus RTU校验算法:
void CRC16_S(byte[] data, int len)
{
byte CRC16Lo;
byte CRC16Hi; //CRC寄存器
byte CL; byte CH; //多项式码&HA001
byte SaveHi; byte SaveLo;
int Flag;
CRC16Lo = 0xFF;
CRC16Hi = 0xFF;
CL = 0x01;
CH = 0xA0;
for (int i = 0; i < len; i++)
{
CRC16Lo = (byte)(CRC16Lo ^ data[i]); //每一个数据与CRC寄存器进行异或
for (Flag = 0; Flag <= 7; Flag++)
{
SaveHi = CRC16Hi;
SaveLo = CRC16Lo;
CRC16Hi = (byte)(CRC16Hi >> 1); //高位右移一位
CRC16Lo = (byte)(CRC16Lo >> 1); //低位右移一位
if ((SaveHi & 0x01) == 0x01) //如果高位字节位为1
{
CRC16Lo = (byte)(CRC16Lo | 0x80); //则低位字节右移后前面补1
} //否则自动补0
if ((SaveLo & 0x01) == 0x01) //如果LSB为1,则与多项式码进行异或
{
CRC16Hi = (byte)(CRC16Hi ^ CH);
CRC16Lo = (byte)(CRC16Lo ^ CL);
}
}
}
//如果是modbus协议的话,应该是是低位,第二位是高位
data[len++] = CRC16Lo; //CRC低位
data[len] = CRC16Hi; //CRC 高位
}
{
byte CRC16Lo;
byte CRC16Hi; //CRC寄存器
byte CL; byte CH; //多项式码&HA001
byte SaveHi; byte SaveLo;
int Flag;
CRC16Lo = 0xFF;
CRC16Hi = 0xFF;
CL = 0x01;
CH = 0xA0;
for (int i = 0; i < len; i++)
{
CRC16Lo = (byte)(CRC16Lo ^ data[i]); //每一个数据与CRC寄存器进行异或
for (Flag = 0; Flag <= 7; Flag++)
{
SaveHi = CRC16Hi;
SaveLo = CRC16Lo;
CRC16Hi = (byte)(CRC16Hi >> 1); //高位右移一位
CRC16Lo = (byte)(CRC16Lo >> 1); //低位右移一位
if ((SaveHi & 0x01) == 0x01) //如果高位字节位为1
{
CRC16Lo = (byte)(CRC16Lo | 0x80); //则低位字节右移后前面补1
} //否则自动补0
if ((SaveLo & 0x01) == 0x01) //如果LSB为1,则与多项式码进行异或
{
CRC16Hi = (byte)(CRC16Hi ^ CH);
CRC16Lo = (byte)(CRC16Lo ^ CL);
}
}
}
//如果是modbus协议的话,应该是是低位,第二位是高位
data[len++] = CRC16Lo; //CRC低位
data[len] = CRC16Hi; //CRC 高位
}
四.仪表部份寄存器地址列表:
| 仪表部份寄存器地址具体地址参看仪表随机说明书 | |
|---|---|
| 寄存器地址 | 名称 |
| 0X0000 | 仪表设定值 |
| 0X0001 | 报警上限值 |
| 0X000A | 小数点位数 |
| 0X0016 | 通讯地址 |
| 0X0017 | 通讯波特率 |
| 0X1001 | 仪表测量值 |
| 0X1101 | 控制输出百分比 |
| 0X1200 | 报警输出 |
五.精创仪表和西门子PLC通信图例:

