Здесь принимаются все самые невообразимые вопросы... Главное - не стесняйтесь. Поверьте, у нас поначалу вопросы были еще глупее :)
Ответить

CRC-16/MCRF4XX

Сб янв 16, 2021 03:35:38

Дратути. :beer:
Всю голову уже сломал в попытках посчитать контрольную сумму.

По условию* контрольная сумма - 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..
:shock: :o

****************************

Re: CRC-16/MCRF4XX

Сб янв 16, 2021 21:00:44

Нашел кое чего ( Лоренц Майер - один из создателей данного протокола )
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) (контрольная сумма >> 8);

Вы видите, что к контрольной сумме добавляется полная полезная нагрузка плюс заголовок, так как все, начиная с поля "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.
Это должно дать вам тот же результат.


Но пока это не понятно...

Re: CRC-16/MCRF4XX

Вс янв 17, 2021 02:00:01

crc_extra - судя по исходникам, на которые вы сами ссылаетесь - это байт из таблицы MAVLINK_MESSAGE_CRCS по смещению пакет[5].
У вас пакет[5] == 0x1E.
MAVLINK_MESSAGE_CRCS[0x1E] == 0x27.
crc_extra = 0x27
Вот пошагово, как получена ваша контрольная сумма 0x6733.
http://codepad.org/uKXxxpac

Re: CRC-16/MCRF4XX

Вс янв 17, 2021 05:55:59

Ого, спаибо большущее !!!!
:beer:
А я пытался брать из этой таблицы значение #30 = 115, но и подумать не мог, что нужно смещение делать...
( выходит #30+1 )

Re: CRC-16/MCRF4XX

Ср янв 27, 2021 05:27:06

Появился еще один вопросик по данной теме.
Решил тут же спросить, что бы не дублировать..

Хочу библиотечку свою написать на асме для 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- )

тут инвертирую последовательность битов в регистре
1001.jpg
(189.38 KiB) Скачиваний: 10


А тут инвертирую последовательность битов в многочлене
1002.jpg
(211.75 KiB) Скачиваний: 10


1) Что делаю не так?
2) Как в обще этот метод? удобен ли?
3) Может есть готовая библиотека, чтоб не мучатся?

Re: CRC-16/MCRF4XX

Ср янв 27, 2021 06:41:08

Как вариант для подсчета CRC MODBUS. Не думаю, что сильно большие отличия, кроме полинома.
CRC_MODBUS.TXT

Re: CRC-16/MCRF4XX

Ср янв 27, 2021 13:17:41

Спасибо! :beer:
Мельком глянул код - для подпрограммы не годится.
Не хватает меток и переменных. ( например 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 ассемлер - не пойму что за код... :dont_know:
Зато комментариев полно.
Можно переделать как надо
Последний раз редактировалось uwrtey Чт янв 28, 2021 02:53:20, всего редактировалось 2 раз(а).

Re: CRC-16/MCRF4XX

Чт янв 28, 2021 02:44:30

Нашел документацию на MODBUS -
Modbus_over_serial_line_V1_02.pdf
(257.93 KiB) Скачиваний: 8


смотрим страницы с 40 по 44

на 41 странице есть пример вычисления методом побитового сдвига

MODBUS.jpg
(133.53 KiB) Скачиваний: 11


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-

:idea: :idea: :idea:
Можно не высчитывать CRC вовсе, а просто брать табличные значения.
Точнее значения из массива. Вычисление гораздо быстрее получится, вот только памяти сожрет такой массив многовато..
Придется хранить 65536 значений. Хотя можно 256, и отдельно смотреть старший байт и младший..

Re: CRC-16/MCRF4XX

Пн фев 01, 2021 00:00:07

:beer:
Ответить