Код CRC8 не работает должным образом
Мне нужно отправить строку, за которой следует ее полином CRC8, 0x31 (= X^8 + X^5 + X^4 + 1), я успешно закодировал это после некоторых проблем, но, похоже, это не так. работать правильно, когда я проверяю результаты. Я использовал некоторые онлайн-калькуляторы CRC, поэтому проверьте, в порядке ли мои результаты, но я не получаю одинаковых результатов, независимо от того, что я пытаюсь сделать.
На самом деле разные калькуляторы CRC дают разные результаты, что меня беспокоит... Вот мои испытания онлайн-калькуляторов CRC, всегда использующие: CRC8, полином 0x31, данные = TEMPS; (начало моей строки)
На http://www.sunshine2k.de/coding/javascript/crc/crc_js.html :
На https://www.lddgo.net/en/encrypt/crc:
На http://zorc.breitbandkatze.de/crc.html:
Не кажется нормальным получать разные результаты при одинаковых входных параметрах, это меня сильно смущает. Я что-то упустил?
Что бы я ни пытался, я не получаю ни одного из этих результатов с моим собственным кодом. Вот мой код расчета CRC с использованием библиотеки CRC RobTillaart (https://github.com/RobTillaart/CRC):
String crcData = "TEMPS;";
int crcDataLength = crcData.length();
char arrayForCrc[crcDataLength+1];
crcData.toCharArray(arrayForCrc, crcDataLength+1);
crcTrame = CRC8(0x31,0,0,false,false);
crcTrame.add((uint8_t *)arrayForCrc, crcDataLength+1);
String stringCrcNoHex = String(crcTrame.getCRC());
String stringCrc = String(crcTrame.getCRC(), HEX);
Шестнадцатеричный результат этого примера кода – 0xBA (186 десятичных знаков). Я проверил все входные параметры с помощью get и print, все они верны:
arrayForCrc = "TEMPS;" полином = 0x31 Начальное исключающее ИЛИ = 0 Исключающее ИЛИ=0 Обратный=ложь Реверсаут=ложь
Буду очень признателен за помощь, так как я застрял и не знаю, что еще попробовать. Спасибо :)
@Myst, 👍0
Обсуждение1 ответ
Шестнадцатеричный результат этого примера кода: 0xBA (186 десятичный)
Насколько я могу судить, нет; это 0xB5, что ожидается по простой причине, которую вы увидите. И при небольшом изменении он соответствует значению 0x49. Я склонен полагать, что ваш код верен, насколько вы его показали, но ваш отчет о том, что происходит, неверен.
Я проверил все входные параметры с помощью gets и prints, все они правильные
Ну, нет. Как я уже упоминал в комментариях к вопросу, я получаю ожидаемый 0x49 на первом сайте, который вы упомянули, с правильными настройками. Я не уверен, почему вы показываете 0x6E. Но угадайте, что произойдет, если я нажму Enter после "TEMPS;"? 0x6Е. Символ новой строки имеет значение. Кроме того, я действительно получаю 0xBA, если использую правильный ввод, но не могу установить CRC8 на пользовательский и изменить 0x07 на 0x31 в полиноме. Возможно, именно так вы нашли это значение.
Если вы переключитесь в байтовый режим, сайт будет ожидать последовательность значений кодов символов и игнорировать пробелы (кроме того, что они будут рассматриваться как разделители). Вы можете поместить в него 0x54 0x45 0x4d 0x50 0x53 в байтовом режиме, чтобы также увидеть результат 0x49. Затем вы можете добавить 0x0D (перевод строки), чтобы увидеть, что это приводит к 0x6E из предыдущего.
Что касается среднего сайта, настройки неверны (настройка reverse включена для ввода и вывода), и я не вижу, как сделать их правильными ; у них, кажется, нет пользовательской опции. Однако вы можете включить параметры отражения на первом сайте, чтобы получить тот же результат, что и на втором сайте, чтобы убедиться, что это именно то, что происходит. Вывод третьего сайта соответствует тому, что вы в него вложили. Это просто не соответствует тому, что на самом деле делает ваш код.
Ваша основная проблема заключается в +1
в этой строке:
crcTrame.add((uint8_t *)arrayForCrc, crcDataLength+1);
Вы включили в расчет завершающий нуль. Это 7 байтов: 'T', 'E', 'M', 'P', 'S', ';', '\0'. Эти веб-сайты просто не делают этого; они не добавляют автоматически нулевой терминатор в конце всего, что вы вводите в строковом режиме. В качестве альтернативы, если вы хотели использовать нулевой терминатор в вычислении CRC, ваш код в порядке, но вам нужно будет переключиться на режим ввода HEX на веб-сайте и ввести в него 0x00 после шестнадцатеричного значения для других символов в TEMPS;, чтобы они совпадали. И это будет соответствовать, я проверил это. Также можно: перевести первый сайт в байтовый режим и поставить "0x54 0x45 0x4d 0x50 0x53 0x3b 0x00" в него, и вы увидите, что теперь он выдает 0xB5, как и ваш текущий код.
В противном случае вам просто нужно не вводить нулевой терминатор в расчет:
crcTrame.add((uint8_t *)arrayForCrc, crcDataLength);
Это приведет к тому, что 0x49
выйдет из crcTrame.getCRC()
вместо 0xB5
:
#include "CRC8.h"
void setup() {
Serial.begin(9600);
}
void loop() {
String crcData = "TEMPS;";
int crcDataLength = crcData.length();
char arrayForCrc[crcDataLength+1];
crcData.toCharArray(arrayForCrc, crcDataLength+1);
auto crcTrame = CRC8(0x31,0,0,false,false);
crcTrame.add((uint8_t *)arrayForCrc, crcDataLength);
String stringCrcNoHex = String(crcTrame.getCRC());
String stringCrc = String(crcTrame.getCRC(), HEX);
Serial.println(stringCrc);
}
Если вы также хотите проверить правильность того, что произошло с выводом 0x6E ранее, вы можете изменить crcData
на String crcData = "TEMPS;\n"
(добавив новую строку) и посмотрите, как он начнет печатать 6E.
В String есть функция .getBytes()
, которая в значительной степени является тем, что у вас есть без необходимости в приведении:
crcTrame.getBytes(arrayForCrc, crcDataLength);
Я не уверен, есть ли у вас веская причина для "TEMPS;" чтобы начать жизнь в String
или затем получить ее в массиве символов. Если вы делаете это только для того, чтобы затем вызвать crcTrame.add()
, вам не нужно:
#include "CRC8.h"
void setup() {
Serial.begin(9600);
}
void loop() {
String crcData = "TEMPS;";
int crcDataLength = crcData.length();
auto crcTrame = CRC8(0x31,0,0,false,false);
crcTrame.add(
(const uint8_t *)crcData.c_str(),
crcData.length() // <- Does not count null terminator.
);
String stringCrcNoHex = String(crcTrame.getCRC());
String stringCrc = String(crcTrame.getCRC(), HEX);
Serial.println(stringCrc);
}
Примечание. Я создаю stringCrc
только для того, чтобы отразить то, что вы делали. Здесь это может быть просто Serial.println(crcTrame.getCRC(), HEX);
и, возможно, в любом контексте, в котором вы это делаете. Приведение также может быть выполнено в более C++ одобрено (хотя более уродливый способ с crcTrame.add(reinterpret_cast<const uint8_t *>(crcData.c_str()), crcData.length());
Любая последовательность из любого количества вызовов add()
, которая передает одни и те же данные в том же порядке для вычисления, даст один и тот же CRC. Существует также перегруженная функция add()
, которая принимает отдельный символ. вообще без указателя. Таким образом, ваши данные не обязательно должны поступать из String
, быть строкой с завершающим нулем или массивом символов или полностью помещаться в памяти.
- Обеспечиваем более быстрое и точное обнаружение MindWave Mobile
- Какие есть другие IDE для Arduino?
- Плата для разработки STM8 с Arduino IDE
- Как изменить переменную при нажатии кнопки, подключенной к контакту 2
- Bluetooth-модуль HC-05 не принимает AT-команды
- как отправить данные в Adafruit Bluefruit Feather (32u4) через Bluetooth?
- Как прервать соединение HM10 Bluetooth?
- Что именно делает возвращаемый тип в функции?
Я мог бы объяснить это, если бы вы получали 0xB**5**, но не 0xBA. Это помогает иметь полностью компилируемый код., @timemage
Я только что заполнил ваш код догадками до такой степени, что он скомпилирован с последней версией этой библиотеки, и у меня он _is_ печатает 0xB5, а не 0xBA. Так что либо мы оба запутались, либо вы ошиблись номером в своем вопросе., @timemage
Еще раз проверьте свой снимок экрана с солнечным светом, потому что, если я вставлю в него именно то, что у вас есть, и вычислю, я не получу 0x6E; [Я получаю ожидаемое значение 0x49](https://imgur.com/a/btfECVA). Что касается теста скриншота «lddgo», он не совсем действителен. Настройки реверса включены. Как только вы правильно получите 0x49 на солнечном свете, включите обе опции отражения, и вы увидите, что вы [теперь получите 0x73](https://imgur.com/a/LFlGuCu), который соответствует тому, что у вас есть в lddgo. Итак, я бы удалил его, потому что это не имеет ничего общего с проблемой, с которой вы столкнулись с библиотекой., @timemage