PIC微型控制器的Modbus功能代码1和crc检查

时间:2018-08-14 11:07:07

标签: c crc modbus crc16

在计算功能代码1的Modbus CRC校验时需要帮助,即读取线圈寄存器。我有用于功能码3的CRC校验的示例代码,即用于模拟输入的寄存器。

# Read Coil Status (FC=01)

## Request

此命令请求离散线圈#20至56的ON / OFF状态 从地址为17的从设备。

11 01 0013 0025 0E84

  • 11:从站地址(17 = 11十六进制)
  • 01:功能代码(读取线圈状态)
  • 0013:要读取的第一个线圈的数据地址。 (线圈20-1 = 19 = 13十六进制)
  • 0025:请求的线圈总数。 (线圈20到56 = 37 = 25十六进制)
  • 0E84:用于错误检查的CRC(循环冗余校验)。

响应

11 01 05 CD6BB20E1B 45E6

  • 11:从站地址(17 = 11十六进制)
  • 01:功能代码(读取线圈状态)
  • 05:要遵循的数据字节数(37个线圈/ 8个字节/每个字节= 5个字节)
  • CD:线圈27-20(1100 1101)
  • 6B:线圈35-28(0110 1011)
  • B2:线圈43-36(1011 0010)
  • 0E:线圈51-44(0000 1110)
  • 1B:3个空格和线圈56-52(0001 1011)
  • 45E6:CRC(循环冗余校验)。

读取保持寄存器(FC = 03)

请求

此命令正在请求模拟输出保持寄存器#40108的内容 从设备地址为40的40110。

11 03 006B 0003 7687

  • 11:从站地址(17 = 11十六进制)
  • 03:功能代码(读取模拟输出保持寄存器)
  • 006B:请求的第一个寄存器的数据地址。 (40108-40001 = 107 = 6B十六进制)
  • 0003:请求的寄存器总数。 (读取3个寄存器40108至40110)
  • 7687:用于错误检查的CRC(循环冗余校验)。

响应

11 03 06 AE41 5652 4340 49AD

  • 11:从站地址(17 = 11十六进制)
  • 03:功能代码(读取模拟输出保持寄存器)
  • 06:要跟随的数据字节数(3个寄存器x 2个字节,每个= 6个字节)
  • AE41:寄存器40108的内容
  • 5652:寄存器40109的内容
  • 4340:寄存器40110的内容
  • 49AD:CRC(循环冗余校验)。

对于获得FC3的响应我没有问题。因为我正确发送了2个字节的地址,但是我不知道如何发送单字节并修改FC1的crc功能->读取线圈寄存器

Discription of read coil register

unsigned int crc_fn(unsigned char *dpacket,unsigned int len) { // CRC Function(Error calcualtion)
    unsigned int crc = 0xffff,poly = 0xa001;
    unsigned int i=0;

    for(i=0; i<len; i++) {
        crc^= dpacket[i];
        for(j=0; j<8; j++) {
            if(crc & 0x01) {
                crc >>= 1;
                crc ^= poly;
            } else
                crc >>= 1;
        }
    }
    return (crc);
}

1 个答案:

答案 0 :(得分:0)

通常,CRC首先附加到最高有效字节的消息上。您需要交换两行代码,在低位字节之前发送16位crc的高位字节。尝试此更改:

                Serial_1_Send_byte((unsigned char)(crc1>>8));
                Serial_1_Send_byte((unsigned char)crc1);