Форум РадиоКот https://radiokot.ru/forum/ |
|
CRC-16/MCRF4XX https://radiokot.ru/forum/viewtopic.php?f=21&t=174996 |
Страница 1 из 1 |
Автор: | uwrtey [ Сб янв 16, 2021 03:35:38 ] |
Заголовок сообщения: | CRC-16/MCRF4XX |
Дратути. ![]() Всю голову уже сломал в попытках посчитать контрольную сумму. По условию* контрольная сумма - CRC-16/MCRF4XX Есть пакет: FE 1C F5 01 01 1E 5B 59 00 00 5F C3 4F 3B 69 2E 0F BD DB 33 22 40 EF 8A 4A 3A 7A FF 74 B9 51 37 06 BA 33 67 В котором последние 2 байта - контрольная сумма 0x3367 ( хотя, скорей всего, они записаны младшим байтом вперед, и в итоге контрольная сумма = 0x3367 ) Первый байт FE - заголовок, и по условию* он не считается в контрольную сумму. Остается: 1C F5 01 01 1E 5B 59 00 00 5F C3 4F 3B 69 2E 0F BD DB 33 22 40 EF 8A 4A 3A 7A FF 74 B9 51 37 06 BA Но если посчитать контрольную сумму, то она будет равна 0x1503 что не равно нашей контрольной сумме.. (рассчитываю калькулятором - https://crccalc.com/ ) В условии* CRC включает байт CRC_EXTRA. Цитата: Когда отправитель вычисляет контрольную сумму для сообщения, он добавляет CRC_EXTRA_байт в конец данных, по которым вычисляется контрольная сумма. Получатель вычисляет контрольную сумму для полученного сообщения и добавляет свою собственную CRC_EXTRA для конкретного идентификатора сообщения. Если CRC_EXTRA для отправителя и получателя разные, контрольные суммы не будут совпадать. Такой подход гарантирует, что будут декодированы только сообщения, в которых отправитель и получатель используют одну и ту же структуру сообщения (или, по крайней мере, это делает ошибку гораздо менее вероятной, как для любого приложения контрольной суммы). В условии* не сказано как рассчитывать CRC_EXTRA. Предполагается использование стандартных библиотек (Си, Си++, Си# и Python). Я же хочу написать небольшую программу на AVR-ассемблере, позволяющую декодировать данные сообщения, соответственно мне понадобится подпрограмма расчета контрольной суммы для данного типа сообщений. **************************** Пытался заглянуть в код библиотеки https://github.com/mavlink/c_library_v2 ... checksum.h Но ни черта не понял. Особенно не понятно откуда взялось число 0xf0b8.. ![]() ![]() **************************** |
Автор: | uwrtey [ Сб янв 16, 2021 21:00:44 ] |
Заголовок сообщения: | Re: CRC-16/MCRF4XX |
Нашел кое чего ( Лоренц Майер - один из создателей данного протокола ) https://github.com/mavlink/mavlink/issues/30 Цитата: Экстракция CRC защищает пакет от декодирования другой версии того же пакета, но с другими переменными. Это средство гарантировать, что случайное смешение диалектов или версий MAVLink никогда не приведет к неверной интерпретации данных. Они определены в каждом файле диалекта, например, в common.h или pixhawk.h. Это пример из common.h: #ifndef MAVLINK_MESSAGE_CRCS #define MAVLINK_MESSAGE_CRCS {50, 124, 137, 0, 237, 217, 104, 119, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 0, 214, 159, 220, 168, 24, 23, 170, 144, 67, 115, 39, 246, 185, 104, 237, 244, 222, 212, 9, 254, 230, 28, 28, 132, 221, 232, 11, 153, 41, 39, 214, 223, 141, 33, 15, 3, 100, 24, 239, 238, 30, 200, 183, 0, 130, 0, 148, 21, 0, 52, 124, 0, 0, 0, 20, 0, 152, 143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 231, 183, 63, 54, 0, 0, 0, 0, 0, 0, 0, 175, 102, 158, 208, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 204, 49, 170, 44, 83, 46, 0} #endif Это кодировка сообщения: контрольная сумма = crc_calculate ((uint8_t *) & msg-> len, length + MAVLINK_CORE_HEADER_LEN); #if MAVLINK_CRC_EXTRA crc_accumulate (crc_extra, & контрольная сумма); #endif mavlink_ck_a (msg) = (uint8_t) (контрольная сумма & 0xFF); mavlink_ck_b (msg) = (uint8_t) (контрольная сумма >> ![]() Вы видите, что к контрольной сумме добавляется полная полезная нагрузка плюс заголовок, так как все, начиная с поля "len", берется в контрольную сумму: typedef struct __mavlink_message { uint16_t контрольная сумма; /// отправлено в конце пакета uint8_t magic; /// <магический маркер протокола uint8_t len; /// <Длина полезной нагрузки uint8_t seq; /// <Последовательность пакета uint8_t sysid; /// <ID системы отправителя сообщения / самолета uint8_t compid; /// <ID компонента отправителя сообщения uint8_t msgid; /// <ID сообщения в полезной нагрузке uint64_t payload64 [(MAVLINK_MAX_PAYLOAD_LEN + MAVLINK_NUM_CHECKSUM_BYTES + 7) / 8]; } mavlink_message_t; Таким образом, вы должны вычислить контрольную сумму по полному заголовку, всем байтам полезной нагрузки и, наконец, добавить байт CRC_EXTRA. Это должно дать вам тот же результат. Но пока это не понятно... |
Автор: | mont-oriol [ Вс янв 17, 2021 02:00:01 ] |
Заголовок сообщения: | Re: CRC-16/MCRF4XX |
crc_extra - судя по исходникам, на которые вы сами ссылаетесь - это байт из таблицы MAVLINK_MESSAGE_CRCS по смещению пакет[5]. У вас пакет[5] == 0x1E. MAVLINK_MESSAGE_CRCS[0x1E] == 0x27. crc_extra = 0x27 Вот пошагово, как получена ваша контрольная сумма 0x6733. http://codepad.org/uKXxxpac |
Автор: | uwrtey [ Вс янв 17, 2021 05:55:59 ] |
Заголовок сообщения: | Re: CRC-16/MCRF4XX |
Ого, спаибо большущее !!!! ![]() А я пытался брать из этой таблицы значение #30 = 115, но и подумать не мог, что нужно смещение делать... ( выходит #30+1 ) |
Автор: | uwrtey [ Ср янв 27, 2021 05:27:06 ] |
Заголовок сообщения: | Re: CRC-16/MCRF4XX |
Появился еще один вопросик по данной теме. Решил тут же спросить, что бы не дублировать.. Хочу библиотечку свою написать на асме для AVR, позволяющую рассчитывать CRC-16/MCRF4XX смотрю в ВикиПедию https://ru.wikipedia.org/wiki/%D0%A6%D0 ... 0%BE%D0%B4 Пишут следующее: Производящий полином (poly) = 0x1021 ( 0b 0001 0000 0010 0001 ) Стартовые данные (init)= 0xFFFF Флаг (RefIn), = True — с младшего (LSB-first); Флаг (RefOut), = True, инвертируется порядок битов регистра при входе на элемент XOR; Число (XorOut), с которым складывается по модулю 2 полученный результат = 0x00 Пытаюсь рассчитать CRC, для числа 0x00 Должно получится 0x0F87 ( 0b 0000 1111 1000 0111 ) Но что то у меня не выходит: ( вопрос решаю методом побитового сдвига - научили тут https://soltau.ru/index.php/themes/dev/item/461-kak- ) тут инвертирую последовательность битов в регистре Вложение: А тут инвертирую последовательность битов в многочлене Вложение: 1) Что делаю не так? 2) Как в обще этот метод? удобен ли? 3) Может есть готовая библиотека, чтоб не мучатся? |
Автор: | akl [ Ср янв 27, 2021 06:41:08 ] |
Заголовок сообщения: | Re: CRC-16/MCRF4XX |
Как вариант для подсчета CRC MODBUS. Не думаю, что сильно большие отличия, кроме полинома. Вложение: CRC_MODBUS.TXT
|
Автор: | uwrtey [ Ср янв 27, 2021 13:17:41 ] |
Заголовок сообщения: | Re: CRC-16/MCRF4XX |
Спасибо! ![]() Мельком глянул код - для подпрограммы не годится. Не хватает меток и переменных. ( например BUF_COMAND и ERROR_MODBUS ) Комментариев почти нет.. Порылся в сети и вот что нашел: Код: ;****************************************************************************** ; Загрузка 16-битового регистра CRC числом FFFF. CRC_Modbus: movlw 0xFF ; W <- 0xFF (DEC 255) movwf CRC16_H ; CRC16_H <- W movwf CRC16_L ; CRC16_L <- W ;****************************************************************************** ; XOR байта с содержимым CRC. Результат в CRC. VXOD: movf Byte_X, W ; W <- Byte_X xorwf CRC16_L, F ; CRC16_L <- W(Byte_X) xor CRC16_L ;****************************************************************************** ; Предустановка счетчика циклов для прокрутки 1 байта movlw 0x08 ; W <- 0x08 (DEC 8) movwf Cycle_I ; Cycle_I <- W(0x08) ;****************************************************************************** ; Сдвиг регистра CRC вправо (к младшему биту) на 1 бит, ; старший заполнить нулями. CRC_SDVIG: bcf STATUS, C ; очистка флага С в "0" rrf CRC16_H, F ; CRC16_H <- (C>> CRC16_H >> 1 бит >>C) rrf CRC16_L, F ; CRC16_L <- (C>> CRC16_L >> 1 бит >>C) ;****************************************************************************** ; Проверка условия: если младший бит был "0", то перейти к "CRC_SDVIG" ; если младший бит был "1", то CRC xor A001. btfss STATUS, C ; если мл. бит БЫЛ = "0", то PC+1, иначе PС+2 goto CRC_PER5 ; PC+1: переход на метку CRC_PER5 movlw 0xA0 ; PC+2: W = 0xA0 (DEC 160) xorwf CRC16_H, F ; CRC16_H <- W(0xA0) xor CRC16_H movlw 0x01 ; W = 0x01 (DEC 1) xorwf CRC16_L, F ; CRC16_L <- W(0x01) xor CRC16_L ;****************************************************************************** ; 5.Шаги №3 и №4 повторяются 8 раз. CRC_PER5: decfsz Cycle_I,F ; Cycle_I <- Cycle_I - 1. Если "0", то PC+2 goto CRC_SDVIG ; PC+1: переход на метку CRC_SDVIG ; PC+2: дальшейшее выполнение программы ;****************************************************************************** ; 6.Шаги №2, №3, №4, №5 повторить для всех байт сообщения. goto VXOD ; Переход на метку VXOD Правда это не AVR ассемлер - не пойму что за код... ![]() Зато комментариев полно. Можно переделать как надо |
Автор: | uwrtey [ Чт янв 28, 2021 02:44:30 ] |
Заголовок сообщения: | Re: CRC-16/MCRF4XX |
Нашел документацию на MODBUS - Вложение: смотрим страницы с 40 по 44 на 41 странице есть пример вычисления методом побитового сдвига Вложение: MODBUS полином 0x8005 > 0b 1000 0000 0000 0101 , если ивертировать порядок битов, то получим 0b 1010 0000 0000 0001 > 0xA001 Мало того, что порядок битов в полиноме инвертирован, так сдвигать нужно вправо а не влево. и во вторых "число" из которого нужно получить CRC нужно XOR-ить, а не пытаться его вдвинуть на место стартового числа в третьих сдвигать нужно всего 8 раз - кратно одному байту В общем тут статья кривая, как мне кажется... Ну либо написано оооочень непонятным языком. https://soltau.ru/index.php/themes/dev/item/461-kak- ![]() ![]() ![]() Можно не высчитывать CRC вовсе, а просто брать табличные значения. Точнее значения из массива. Вычисление гораздо быстрее получится, вот только памяти сожрет такой массив многовато.. Придется хранить 65536 значений. Хотя можно 256, и отдельно смотреть старший байт и младший.. |
Автор: | uwrtey [ Пн фев 01, 2021 00:00:07 ] |
Заголовок сообщения: | Re: CRC-16/MCRF4XX |
![]() |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |