Как вы можете вычислить контрольную сумму из шестнадцатеричных значений, хранящихся в QByteArray - PullRequest
0 голосов
/ 23 сентября 2019

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

формат пакета данных, которые я получаю, выглядит следующим образом: // Формат пакета: // // | CHAR1 <1> | CHAR2 <1> | CLASS <1> | ID <1> | LENGTH <2> | PAYLOAD | CK_A <1> | CK_B <1> |

// <--------------------- 4 ----------------------------> |

// <--------------------------------------- 6 -----------------------------> |

// <--------------------------------------- 6 + длина --------------------------------> |

// <--------------------------------------------------------- + 8 длина -------------------------------------------> |

Существует две контрольные суммы CK_A и CK_B.Каждый из них имеет длину в один байт. Алгоритм контрольной суммы - это 8-битный алгоритм Флетчера:

CK_A = 0;
CK_B = 0;
for(i=0,i<n,i++){
  CK_A = CK_A + Buffer[i];
  CK_B = CK_B + CK_A;
}

У меня проблемы с сложением шестнадцатеричных значений, хранящихся в QByteArray.Это код, который я написал. Он рекламирует значения, но они не верны, и код грязный.

for(int I = 4; I < length + 4; I+=2){

        tempHex[0] = serialData[I];
        tempHex[1] = serialData[I + 1];
        tempDec=tempHex.toInt();

        CheckSum_A_int = (CheckSum_A_int + tempDec);
        CheckSum_A_int &= 0xFF;
        CheckSum_B_int = (CheckSum_B_int + CheckSum_A_int);
        CheckSum_A_int &= 0xFF;


        CK_A = CheckSum_A_int;
        CK_B = CheckSum_B_int;

        CK_A = CK_A.toLatin1().toHex();
        CK_B = CK_B.toLatin1().toHex();
}

Кто-нибудь знает правильный или лучший способ сделать это.Или кто-то может объяснить мне, как шестнадцатеричные значения QByteArray можно добавить?Это образец данных: "b56201241400009b4209d25e02009be0f8ffcc020407140d0000bd33".CK_A должно быть "bd", а CK_B должно быть "33".

Большое спасибо за ваше терпение.Привет

1 Ответ

0 голосов
/ 24 сентября 2019

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

#include <QByteArray>
#include <iostream>

int main(int argc, char *argv[])
{
    // Unused function parameters
    (void)argc;
    (void)argv;

    uint16_t csum_a = 0;
    uint16_t csum_b = 0;
    QByteArray ba;

    // Example Receive message
    uint8_t data[] = {
        0xb5, 0x62,              // Preamble
        0x01, 0x24,              // CLASS + ID
        0x14, 0x00,              // Length (Little Endian)
        0x00, 0x9b, 0x42, 0x09,  // Payload
        0xd2, 0x5e, 0x02, 0x00,  // Payload
        0x9b, 0xe0, 0xf8, 0xff,  // Payload
        0xcc, 0x02, 0x04, 0x07,  // Payload
        0x14, 0x0d, 0x00, 0x00,  // Payload
        0xbd,                    // Checksum A
        0x33                     // Checksum B
    };

    // Add receive message to QByteArray
    for (int i = 0; i < static_cast<int>(sizeof(data)); i++)
    {
        ba.append(static_cast<int8_t>(data[i]));
    }
    std::cout << "QByteArray size: " << ba.size() << std::endl;

    // Extract length from receive message
    // According to ublox datasheet, it's little endian.
    uint16_t length = static_cast<uint16_t>(ba[4]) | static_cast<uint16_t>((ba[5]) << 8);
    std::cout << "Message length: " << length << std::endl;

    // Calculate checksum according to ublox datasheet.
    // The checksum is calculated over the Message, starting and including
    // the CLASS field, up until, but excluding, the Checksum Field.
    for (uint16_t offset = 2; offset < (length + 6); offset++)
    {
        csum_a = (csum_a + ba[offset]) & 0x00ff;
        csum_b = (csum_b + csum_a) & 0x00ff;
    }

    std::cout << "Checksum A: " << std::hex << "0x" << csum_a << std::endl;
    std::cout << "Checksum B: " << std::hex << "0x" << csum_b << std::endl;

    return 0;
}
...