LINUX.ORG.RU

Помогите с расчетом CRC8 суммы

 ,


0

2

Поможите люди добрые! Сами мы не местные (не ассемблерщики и вообще не очень умные, как видно).

Есть весы, работающие по протоколу Тензо М. В описании протокола для расчета CRC суммы приведен вот такой код на ассемблерной вставке якобы для C++

BYTE CDeviceTestDlg::CRCMaker(BYTE b_input, BYTE b_CRC)
{
__asm
{
  mov al,b_input
  mov ah,b_CRC
  mov cx,8
mod1:
  rol al,1
  rcl ah,1
  jnc mod2
  xor ah,69h
mod2:
  dec cx
  jnz mod1
  mov b_CRC,ah
}
return b_CRC;

Мать их, 16 битный ассемблер в 2021!!! Да чтоб они так жили.

В эту функцию, насколько я понял, надо подставить байты пакета по очереди и в итоге на последнем байте получится CRC. Как это сделать толком тоже не понятно, но ладно - мне бы сначала просто скомпилировать эту функцию! Подскажите, как вообще при помощи gcc собрать такой код на современной системе?

Что делал. В лоб конечно не собирается. Добавлял .code16, .intel_syntax noprefix - ругается все равно что таких инструкций асма нет.

Пример гарантированно правильных кадров с верной CRC суммой, сдамплено сниффером с фирменной утилиты

0xFF 0x02 0xC3 0xE6 0xFF 0xFF
0xFF 0x01 0xC3 0xE3 0xFF 0xFF

Третий с конца байт - это CRC. 0xFF - разделители, и вот тут вообще не понятно, надо ли их пихать в расчет контрольной суммы. Если кто имеет опыт с протоколом Тензо М, подскажите пожалуйста.

Но основной вопрос - что делать с ассемблерной вставкой.

Ответ на: комментарий от James_Holden

Помогите с контрольной суммой, ПД308 от Тензо-М

Здравствуйте. Есть прибор ПД308 от Тензо-М, он непрерывно шлет посылку 22 байта: 255 3 204 151 15 15 16 0 0 0 0 0 0 0 0 0 0 0 0 70 255 255,(1 - разделитель, 2 - адрес, 3 - команда, 4-19 - коды ацп, 20 -crc, 21-22 - разделитель, много нулей это потому что подключены 2 датчика из 8) пытаюсь рассчитывать CRC для проверки целостности пакетов. вот мой код на C# (писал по примеру который есть на сайте Тензо-М да и в этой ветке он выше описан с пометкой рабочий):

private static int getCRC(byte[] InputData, int BytesNumber, int Offset) { int i, j;

        byte Data, CrcCode = 0, Polinom = 105; 

        for (i = Offset; i < BytesNumber + Offset; i++)
        {
            Data = InputData[i];

            
            for (j = 0; j < 8; j++)
            {
                if ((CrcCode & 128) >  0)
                {
                    CrcCode = (byte)(CrcCode * 2);

                    if ((Data & 128) > 0)
                    {
                        CrcCode++;
                    }
                    CrcCode = (byte)(CrcCode ^ Polinom);
                }
                else 
                {
                    CrcCode = (byte)(CrcCode * 2);
                    if ((Data & 128) > 0)
                    {
                        CrcCode++;
                    }
                }
                
                Data = (byte)(Data * 2);
            }  
        }
           
        return CrcCode;
    } 

В функцию передаю буфер байт без разделителей и байта контрольной суммы то есть: 3 204 151 15 15 16 0 0 0 0 0 0 0 0 0 0 0 0

У меня получается: 136

Товарищи, второй день сижу, что я делаю не так так?

killla
()
Ответ на: комментарий от James_Holden

эх молодежжжжжжжжжжж, опять весы

def Crc_8(n, poly, crc = 0):
    n = n ^ crc
    for bitnumber in range(0,8):
        if  n & 0x80:
            n = ( n << 1) ^ poly
        else:
            n = n << 1
    return n & 0xFF
  
message = [0xcc, 0xc3, 0x0f, 0x3f, 0x12, 0x6c, 0x26, 0xe0, 0x34, 0x12, 0x36, 0x72, 0x2e, 0xb1, 0x1c, 0xfa, 0x19]
crc = 0
for i in message:
    crc = Crc_8(n = i, poly = 0x69, crc = crc )
print(hex(crc))

написано как решение алгоритма в лоб, обычно делают на таблицах, если места много

только не говори что не знаешь как проверить контрошку :) я этого не переживу

Morin ★★★★★
()
Ответ на: комментарий от Morin

Извини, а ты вообще о чем?

Вот в целом, на какой вопрос ты сейчас отвечал?

И почему ты решил, что я чего-то там не могу проверить? А?

James_Holden ★★★★
() автор топика
Ответ на: комментарий от Morin

Погоди, тут интересная вещь.

Твой код правильно считает контрольную сумму на пакете @killla !

То есть то что мы в самом конце обсуждаем.

А «мой» код, считает неправильно, так же как и его код на C# выше. Но - правильно на пакетах от моих весов.

Твой код неправильно считает на моих пакетах.

Где-то то тут подвох.

Вот что у меня

uint8_t crc8(uint8_t input, uint8_t crc)
{
  for (int i=0; i<8; ++i) {
    int major = (crc & 0x80);
    crc <<= 1;
    if ((input & (1<<(7-i)))!=0)
      crc |= 1;
    if (major)
      crc ^= 0x69;
  }
  return crc;
}
James_Holden ★★★★
() автор топика
Ответ на: комментарий от James_Holden

насколько помню у разных весов которые я видел контрошка иногда считается только с данных, но не с управляющих символов. хотя на мой взгляд это косяк проектирования

иными словами, откидываем старт стоп пакета, считаем контрошку всей посылки либо только данных, но не управляек

дай бог памяти, сейчас попытаюсь найти утилу которой ломал контрольку. либо сам погугли, там сразу увидишь что в выхлопе не нулевое смещение помимо полинома будет, это значит есть статичные данные

Morin ★★★★★
()
Последнее исправление: Morin (всего исправлений: 3)
Ответ на: комментарий от James_Holden

3 204 146 16 1 17 0 0 0 0 0 0 0 0 0 0 0 0 PD_crc=101 | my_crc= 204

3 204 146 16 0 17 0 0 0 0 0 0 0 0 0 0 0 0 PD_crc=154 | my_crc= 9

3 204 146 16 255 254 16 0 0 0 0 0 0 0 0 0 0 0 PD_crc=0 | my_crc= 102

3 204 146 16 254 16 0 0 0 0 0 0 0 0 0 0 0 0 PD_crc=48 | my_crc= 143

3 204 146 16 254 16 0 0 0 0 0 0 0 0 0 0 0 0 PD_crc=48 | my_crc= 143

3 204 147 16 254 16 0 0 0 0 0 0 0 0 0 0 0 0 PD_crc=88 | my_crc= 169

3 204 148 16 255 254 16 0 0 0 0 0 0 0 0 0 0 0 PD_crc=0 | my_crc= 178

3 204 149 16 0 17 0 0 0 0 0 0 0 0 0 0 0 0 PD_crc=235 | my_crc= 251

3 204 149 16 2 17 0 0 0 0 0 0 0 0 0 0 0 0 PD_crc=124 | my_crc= 24

3 204 150 16 4 17 0 0 0 0 0 0 0 0 0 0 0 0 PD_crc=20 | my_crc= 62

3 204 150 16 6 17 0 0 0 0 0 0 0 0 0 0 0 0 PD_crc=131 | my_crc= 221

3 204 149 16 9 17 0 0 0 0 0 0 0 0 0 0 0 0 PD_crc=154 | my_crc= 9

3 204 148 16 11 17 0 0 0 0 0 0 0 0 0 0 0 0 PD_crc=101 | my_crc= 204

3 204 148 16 11 17 0 0 0 0 0 0 0 0 0 0 0 0 PD_crc=101 | my_crc= 204

3 204 147 16 12 17 0 0 0 0 0 0 0 0 0 0 0 0 PD_crc=59 | my_crc= 183

3 204 146 16 11 17 0 0 0 0 0 0 0 0 0 0 0 0 PD_crc=124 | my_crc= 24

3 204 146 16 10 17 0 0 0 0 0 0 0 0 0 0 0 0 PD_crc=131 | my_crc= 221

3 204 145 16 8 17 0 0 0 0 0 0 0 0 0 0 0 0 PD_crc=172 | my_crc= 84

3 204 145 16 6 17 0 0 0 0 0 0 0 0 0 0 0 0 PD_crc=242 | my_crc= 47

3 204 144 16 4 17 0 0 0 0 0 0 0 0 0 0 0 0 PD_crc=13 | my_crc= 234

killla
()
Ответ на: комментарий от Morin

Ббблиин, ты прав, я - идиот. Можешь начинать не переживать :)))

Проблема была в том, что в «мою» функцию надо подставлять данные + 0 вместо контрольной суммы. Тогда все совпадает. У себя я именно так считаю, а тут сегодня я взял пакет @killla и подставил без этого дополнительного байта.

А твоя функция считает без этого.

То есть, @killla, ты просто добавь в конец еще один 0 байт, и попробуй, все должно работать. Получается 70.

James_Holden ★★★★
() автор топика
Ответ на: комментарий от James_Holden

хм, 0 - знакоместо для crc?

если да, то плохие новости, это не очень правильно :) например при без буферной реализации. хотя наверное это не очень актуально, моя функция тоже не будет работать с битстримом, надо переписывать

Morin ★★★★★
()
Ответ на: комментарий от Morin

если да, то плохие новости, это не очень правильно :)

Согласен. Ну будут проблемы - переделаю.

James_Holden ★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.