crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> [РЕШЕНО]CRC16 для Modbus
larry
  опции профиля:
сообщение 17.11.2017, 21:55
Сообщение #1


Студент
*

Группа: Участник
Сообщений: 55
Регистрация: 16.12.2010
Пользователь №: 2274

Спасибо сказали: 8 раз(а)




Репутация:   0  


Добрый день, форумчане.
Возник вопрос по расчету контрольной суммы для modbus. Нашел такую функцию:

quint16 crc(QByteArray& data, quint8 size)
{
    uint crc = 0xFFFF;
    
    for (int pos = 0; pos < size; pos++)
    {
        crc ^= (quint16)data.at(pos);          // XOR byte into least sig. byte of crc
        
        for (int i = 8; i != 0; i--)
        {    // Loop over each bit
            if ((crc & 0x0001) != 0)
            {      // If the LSB is set
                crc >>= 1;                    // Shift right and XOR 0xA001
                crc ^= 0xA001;
            }
            else                            // Else LSB is not set
                crc >>= 1;                    // Just shift right
        }
    }
    // Note, this number has low and high bytes swapped, so use it accordingly (or swap bytes)
    return crc;
}


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

// crc = 71D9
    const char* data = "01040040000a";


и функция возвращает результат, который закоментирован (в калькуляторе тоже самое, т.е. все верно).

Получаю ответ на этот запрос:

// crc = D0AE
const char* data = "0104143a11e6ee3b16c44d39e24257381730ba3d862437";


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

В чем может быть трабла?
Спасибо.

Сообщение отредактировал larry - 18.11.2017, 9:31
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 17.11.2017, 23:30
Сообщение #2


Профессионал
*****

Группа: Модератор
Сообщений: 1594
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 219 раз(а)




Репутация:   12  


алгоритм верный. я даже проверила по-быстрому. всё правильно он считает. может, ты ему данные как-то неправильно скармливаешь?

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <memory.h>

uint16_t crc(uint8_t *data, uint8_t size)
{
        uint16_t pos;
        uint8_t i;
        uint16_t crc = 0xFFFF;

        for (pos = 0; pos < size; pos++)
        {
                crc ^= (uint16_t)data[pos];          // XOR byte into least sig. byte of crc

                for (uint8_t i = 8; i != 0; i--)
                {    // Loop over each bit
                        if ((crc & 0x0001) != 0)
                        {      // If the LSB is set
                                crc >>= 1;                    // Shift right and XOR 0xA001
                                crc ^= 0xA001;
                        }
                else                            // Else LSB is not set
                        crc >>= 1;                    // Just shift right
                }
        }
        // Note, this number has low and high bytes swapped, so use it accordingly (or swap bytes)
        return crc;
}

void convert(const char *src, uint8_t **dst, size_t *dst_size)
{
        size_t i;
        *dst_size = strlen(src)/2;
        *dst = (uint8_t*)malloc(*dst_size);

        for(i=0; i<*dst_size; i++) {
                sscanf(src+i*2, "%02x", *dst+i);
        }
}

void print_crc(const char *data)
{
        uint8_t *value;
        size_t size;
        size_t i;
        uint16_t val_crc;

        convert(data,&value,&size);

        for(i=0; i<size; i++)
                printf("%02X",value[i]);
        printf("\n");

        val_crc = crc(value,size);
        printf("0x%04X\n",val_crc);

        free(value);
}

int main()
{
        print_crc("01040040000a");
        print_crc("0104143a11e6ee3b16c44d39e24257381730ba3d862437");
        return 0;
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
larry
  опции профиля:
сообщение 18.11.2017, 8:38
Сообщение #3


Студент
*

Группа: Участник
Сообщений: 55
Регистрация: 16.12.2010
Пользователь №: 2274

Спасибо сказали: 8 раз(а)




Репутация:   0  


Спасибо большое за проверку. Буду проверять где лохонулся....тоже пришел к такому варианту, т.к. уже перелопатил много вариантов.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
larry
  опции профиля:
сообщение 18.11.2017, 9:30
Сообщение #4


Студент
*

Группа: Участник
Сообщений: 55
Регистрация: 16.12.2010
Пользователь №: 2274

Спасибо сказали: 8 раз(а)




Репутация:   0  


Передавал ввиде QByteArray, сделал как QVector<quint8>, то все правильно считает. Спасибо
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 10.4.2020, 0:07