在 Arduino 上实现 CRC8 以写入 MLX90614 [英] Implementing CRC8 on Arduino to write to MLX90614

查看:24
本文介绍了在 Arduino 上实现 CRC8 以写入 MLX90614的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新:我什至无法使用这个计算器来重现图示的 SMBus PEC在本数据表!

UPDATE: I can't even get this calculator to reproduce the SMBus PECs illustrated in figures 8 and 9 of this datasheet!

所以我将 arduino 与 Melexis 温度传感器连接起来,一切正常——除了我似乎无法让 CRC 检查工作的事实.

So I'm interfacing an arduino with a Melexis temperature sensor, and it's going okay--aside from the fact that I can't seem to get the CRC check to work.

我已经成功完成了读取操作(尽管我的软件忽略了数据包错误代码),但是我尝试了很多 CRC8 实现来检查 PEC 字节,但无济于事.我现在使用的代码块来自 OneWire:

I've gotten read operations to complete successfully (although my software ignores the packet error code) but I have tried a lot of implementations of CRC8 to check the PEC byte to no avail. The code block I am using now came from OneWire:

uint8_t OneWire::crc8(const uint8_t *addr, uint8_t len)
{
    uint8_t crc = 0;

    while (len--) {
        uint8_t inbyte = *addr++;
        for (uint8_t i = 8; i; i--) {
            uint8_t mix = (crc ^ inbyte) & 0x01;
            crc >>= 1;
            if (mix) crc ^= 0x8C;
            inbyte >>= 1;
        }
    }
    return crc;
}

我重写它只考虑一个字节:

I rewrote it to consider just the one byte:

int smbCRC(int message) {

    uint8_t crc = 0;

  uint8_t inbyte = message & 0xFF;
  for (uint8_t i = 8; i; i--) {
    uint8_t mix = (crc ^ inbyte) & 0x01;
    crc >>= 1;
    if (mix) crc ^= 0x8C;
    inbyte >>= 1;
  }

    return crc;
}

但其 CRC 与 MLX 数据表的 CRC 不匹配(图 8 来自 此处 例如).当我像这样打印带有 CRC8 的 int 时:

But its CRC does not match that of the MLX datasheet (Figure 8 from here for example). When I print an int with its CRC8 like so:

int message = 0x3aD2;
lcd.print(String(message,HEX) + " " + String(smbCRC(message),HEX));

我得到3ad2 eb",尽管数据表说正确的 PEC 是 0x30.我哪里错了?这似乎是由于 CRC 的错误实现或我对 CRC 输入的错误假设造成的,我不确定从哪里开始进行故障排除.

I get back "3ad2 eb", though the datasheet says the correct PEC is 0x30. Where am I going wrong? It seems like this could be caused by a bad implementation of CRC or bad assumptions on my part about the CRC input, and I'm not sure where to start troubleshooting.

推荐答案

我还没有检查您的 CRC 实现,但是 MLX 数据表中有一个错误,或者至少它写得不好.您必须包括用于 PEC 计算的所有 I2C 帧数据,而不仅仅是回复数据.对于读字命令,您必须包含 [SA_W, Command, SA_R, LSB, MSB],对于写字命令 [SA_W, Command, LSB, MSB].

I haven't checked your CRC implementation but there is a mistake in the MLX datasheet or at least it's badly written. You have to include all the I2C frame's data for the PEC's calculation not just the replied data. For a read word command you have to include [SA_W, Command, SA_R, LSB, MSB] and for a write word command [SA_W, Command, LSB, MSB].

因此,对于他们的第一个示例,必须在 [ 0xB4, 0x07, 0xB5, 0xD2, 0x3A ] 上进行计算,而不仅仅是在 [ 0xD2, 0x3A ] 上进行计算,这样您就可以获得预期的 0x30.

So, for their first example the calculation must be made on [ 0xB4, 0x07, 0xB5, 0xD2, 0x3A ] and not just on [ 0xD2, 0x3A ] and this way you get the expected 0x30.

这是带有查找表的 CRC 的简单 C 实现(非 Arduino 但它必须非常容易适应):

Here is a simple C implementation of the CRC with a lookup table (non Arduino but it must be quite simple to adapt):

static const uint8_t crc_table[] = {
    0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 0x38, 0x3f, 0x36, 0x31,
    0x24, 0x23, 0x2a, 0x2d, 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65,
    0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, 0xe0, 0xe7, 0xee, 0xe9,
    0xfc, 0xfb, 0xf2, 0xf5, 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd,
    0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 0xa8, 0xaf, 0xa6, 0xa1,
    0xb4, 0xb3, 0xba, 0xbd, 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2,
    0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, 0xb7, 0xb0, 0xb9, 0xbe,
    0xab, 0xac, 0xa5, 0xa2, 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a,
    0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 0x1f, 0x18, 0x11, 0x16,
    0x03, 0x04, 0x0d, 0x0a, 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42,
    0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, 0x89, 0x8e, 0x87, 0x80,
    0x95, 0x92, 0x9b, 0x9c, 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4,
    0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 0xc1, 0xc6, 0xcf, 0xc8,
    0xdd, 0xda, 0xd3, 0xd4, 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c,
    0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, 0x19, 0x1e, 0x17, 0x10,
    0x05, 0x02, 0x0b, 0x0c, 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34,
    0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 0x76, 0x71, 0x78, 0x7f,
    0x6a, 0x6d, 0x64, 0x63, 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b,
    0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, 0xae, 0xa9, 0xa0, 0xa7,
    0xb2, 0xb5, 0xbc, 0xbb, 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83,
    0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef,
    0xfa, 0xfd, 0xf4, 0xf3
};

uint8_t
crc8(uint8_t *p, uint8_t len)
{
        uint16_t i;
        uint16_t crc = 0x0;

        while (len--) {
                i = (crc ^ *p++) & 0xFF;
                crc = (crc_table[i] ^ (crc << 8)) & 0xFF;
        }

        return crc & 0xFF;
}

这篇关于在 Arduino 上实现 CRC8 以写入 MLX90614的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆