我试图通过RS232串口与一个带有Arduino Duemilanove的EPOS2电机控制器接口(因为它就是我躺在那里)。我让它在大多数情况下工作 - 当我手动计算CRC校验和时,我可以发送和接收数据 - 但我正在尝试动态控制需要更改数据的电机速度,因此,更改校验和。有关计算校验和的文档,请参见第24页:
http://www.maxonmotorusa.com/medias/sys_master/8806425067550/EPOS2-Communication-Guide-En.pdf
我直接从本文档中复制了代码,并将其集成到我的代码中,并且它没有正确计算校验和。下面是我的完整草图的缩短版本(经测试,产生0x527C)。最奇怪的部分是它在我的完整草图中计算的值与下面的值不同,但两者都是错误的。有什么明显的东西我不见了吗?
byte comms[6] = { 0x10, 0x01, 0x03, 0x20, 0x01, 0x02 }; // CRC should be 0xA888
void setup() {
Serial.begin(115200);
}
void loop() {
calcCRC(comms, 6, true);
while(1);
}
word calcCRC(byte *comms, int commsSize, boolean talkative) {
int warraySize = commsSize / 2 + commsSize % 2;
word warray[warraySize];
warray[0] = comms[0] << 8 | comms[1];
Serial.println(warray[0], HEX);
for (int i = 1; i <= warraySize - 1; i++) {
warray[i] = comms[i * 2 + 1] << 8 | comms[i * 2];
Serial.println(warray[i], HEX);
}
word* warrayP = warray;
word shifter, c;
word carry;
word CRC = 0;
//Calculate pDataArray Word by Word
while (commsSize--)
{
shifter = 0x8000;
c = *warrayP ++;
do {
carry = CRC & 0x8000;
CRC <<= 1;
if (c & shifter) CRC++;
if (carry) CRC ^= 0x1021;
shifter >>= 1;
} while (shifter);
}
if (talkative) {
Serial.print("the CRC for this data is ");
Serial.println(CRC, HEX);
}
return CRC;
}
我使用以下链接计算适用于此数据的校验和:
https://www.ghsi.de/CRC/index.php?Polynom=10001000000100001&Message=1001+2003+0201
非常感谢!!
答案 0 :(得分:0)
从哪里开始。
首先,您使用commsSize--
作为循环,当warray
中只有三个单词时,这将循环六次。因此,您正在对warray
进行越界访问,并且必然会得到随机结果(或崩溃)。
其次,你的第一个单词的构建是从你的其他构建向后。您的在线CRC遇到了同样的问题,因此您显然没有可靠的测试用例。
第三个(对于测试用例不是问题),如果你有一个奇数个输入字节,你正在进行comms
的越界访问以填写最后一个字。并且您运行CRC位太多次,除非规范在这种情况下指向某种填充。 (您的文档链接已损坏,因此我无法查看应该发生的事情。)即使这样,您也会使用随机数据进行填充而不是零。
0xa888
(这是你的字节,它们是乱七八糟的顺序,但就像你把它们交给计算器一样):
unsigned char dat[6] = { 0x10, 0x01, 0x20, 0x03, 0x02, 0x01 };
unsigned crc1021(unsigned char *dat, int len) {
unsigned crc = 0;
while (len) {
crc ^= *dat++ << 8;
for (int k = 0; k < 8; k++)
crc = crc & 0x8000 ? (crc << 1) ^ 0x1021 : crc << 1;
len--;
}
return crc & 0xffff;
}