验证 MCP3561/2/4R 的校验和

问题描述 投票:0回答:1

我与相关芯片进行 SPI 通信。

https://ww1.microchip.com/downloads/en/DeviceDoc/MCP3561.2.4R-Data-Sheet-DS200006391A.pdf

根据数据表第6.5节,读取我的6个SDO字节后,最后16位是校验和,当没有错误时,这6个字节的CRC16将为0x0000。

我尝试比较 CRC16,我预计它是 0x0000

数据表中未指定校验和的初始化值。

这是一个使用 0x0000 初始化 CRC 值的小转储

13 c8 ef ff 90 b5 crc16 0x204a
13 cb ef ff 90 bf crc16 0x278e
13 ca ef ff 10 ba crc16 0x2412
13 c6 ef ff 10 92 crc16 0x3b02
13 c8 ef ff 90 b5 crc16 0x204a
13 c5 ef ff 10 98 crc16 0x3cc6
13 ca ef ff 10 ba crc16 0x2412
13 c9 ef ff 10 b0 crc16 0x23d6
13 f1 ef ff 90 23 crc16 0x4b56
13 ea 7c ff fa 73 crc16 0x9131

这是一个使用 0xFFFF 来初始化 CRC 值的小转储

13 c2 ef ff 90 89 crc16 0x2bd2
13 bd ef ff 11 88 crc16 0x7166
13 bf ef ff 91 87 crc16 0x753e
13 bc ef ff 91 8d crc16 0x72fa
13 bc ef ff 91 8d crc16 0x72fa
13 bb ef ff 11 9c crc16 0x7eee
13 ca ef ff 10 ba crc16 0x3f12
13 c7 ef ff 90 97 crc16 0x239e
13 cc ef ff 10 ae crc16 0x309a
13 cc ef ff 10 ae crc16 0x309a

这是 6 个字节中每个字节的描述

0 : statusByte
1 : 24 bit high byte
2 : 24 bit middle byte
3 : 24 bit low byte
4 : CRC16 high byte
5 : CRC16 low byte

我也尝试过通过强力查找初始值,但它不起作用:校验和为零的每条消息都不同,除了重复的 vsalues 之外。

我最大的问题是 Microchip 没有为其 CRC 提供参考实现。

代码在STM32嵌入式设备上运行。

我想要的是用于 SPI 读取的 CRC16 的参考实现。

stm32 spi microchip crc16
1个回答
0
投票

根据数据表,CRC 是标准 CRC16,多项式称为

0x8005
。这是我用于所有通信验证的 CRC16 实现。


#define POLY_REVERSED 0xA001  // bit reverse of polynomial 0x8005

uint16_t CRC16(uint8_t* array, uint8_t len, uint16_t crc_init) {

  uint16_t _crc, _flag;
  _crc = crc_init;

  for (uint8_t i = 0; i < len; i++) {
    _crc ^= (uint16_t)array[i];
    for (uint8_t j = 8; j; j--) {
      _flag = _crc & 0x0001;
      _crc >>= 1;
      if (_flag)
        _crc ^= POLY_REVERSED;
    }
  }

  return _crc;

}

uint8_t crcError(uint16_t calculatedCRC, uint8_t crcH, uint8_t crcL) {
    return (calculatedCRC != (uint16_t )((crcH << 8) | crcL));
}

int main() {
    uint8_t data1[] = {0x13, 0xc8, 0xef, 0xff, 0x90, 0xb5, 0x20, 0x4a};
    uint8_t data2[] = {0x13, 0xc2, 0xef, 0xff, 0x90, 0x89, 0x2b, 0xd2};
    
    uint16_t crc = CRC16(data1, 6, 0x0000);
    printf("CRC: %02x %02x\n", crc>>8, crc & 0xff);  // 0x20 0x4a
    
    if (crcError(crc, data1[6], data1[7])) {
        printf("CRC error\n");
    }

    crc = CRC16(data2, 6, 0xFFFF);
    printf("CRC: %02x %02x\n", crc>>8, crc & 0xff);  // 0x2b 0xd2
    
    return 0;
}

CRC16计算的结果也可以通过在线工具验证https://crccalc.com/?crc=0x13,0xc8,0xef,0xff,0x90,0xb5&method=crc16&datatype=hex&outtype=0

使用 0x0000 的 crc init 时检查

CRC16/ARC
行的结果。

https://crccalc.com/?crc=0x13,0xc2,0xef,0xff,0x90,0x89,&method=crc16&datatype=hex&outtype=0

使用0xFFFF的crc init时检查

CRC16/Modbus
线的结果。

© www.soinside.com 2019 - 2024. All rights reserved.