Как использовать Qt QSerialPort для отправки шестнадцатеричного значения 0x00

Я новичок в программировании. Пожалуйста, потерпите меня. Я узнал из примера терминала Qt и попытался отправить необработанные шестнадцатеричные байты. Сначала я мог без проблем отправить 0x57, 0x04, 0x02. Нравится

void MainWindow::writeData(const QByteArray &data)
{
    serial->write(data);
}

void MainWindow::myFunction1()
{
    QByteArray ba("\x57\x04\x02");
    writeData(ba);
}

Затем, по мере продвижения, мне нужно было отправить несколько выбираемых строк данных с 0x00. Приведенный выше код не отправлял \ x00 и стирал что-либо за ним, поэтому я использовал fromRawData, чтобы остановить преобразование специального символа.

void MainWindow::myFunction2(int option)
{
    QByteArray hexString;

    switch (option){
    case 1:
        hexString.append(QByteArray::fromRawData("\x00\x01\x02",3);
        break;
    case 2:
        hexString.append(QByteArray::fromRawData("\xFF\x00",2));
        break;
    }
    writeData(hexString);
}

Приведенный выше код подходил для отправки обеих постоянных строк символов. Но теперь я столкнулся с реальной проблемой, мне нужно отправить непостоянные шестнадцатеричные байты. Я создал массив беззнаковых символов для хранения моей шестнадцатеричной строки и позже изменил его значение. Затем преобразовал его в массив const char. Но это отливка дала неправильный размер.

void MainWindow::myFunction3(int option)
{
    unsigned char Diff[] = {0x45, 0x00, 0x01, 0x02};
    ...
    Diff[2] = 0x08;     // runtime change

    const char *cDiff = (const char*)Diff;  // casting

    int size_Diff = sizeof(Diff);           // qDebug shows 4
    int size_cDiff = sizeof(cDiff);         // qDebug shows 8 !!???

    QByteArray hexString;

    switch (option){
    case 1:
        hexString.append(QByteArray::fromRawData("\x00\x01\x02",3);
        break;
    case 2:
        hexString.append(QByteArray::fromRawData("\xFF\x00",2));
        break;
    case 3:
        hexString = QByteArray::fromRawData(cDiff, sizeof(cDiff));
        break;
    }
    writeData(hexString);
}

В случае 3 я получил 0x45 0x00, 0x08, 0x02, 0x01, 0x00, 0x00, 0x00, всего 8 байт на моей плате MCU! Затем я изменил размер Diff [] на 10 и снова sizeof (cDiff) = 8. Последние два байта были обрезаны.

Мой первый вопрос: есть ли лучший способ отправить unsigned char с различным размером массива и диапазоном значений от 0x00 до 0xFF, определенным во время выполнения с помощью QSerialPort? Второй вопрос: почему приведенный пример дал мне неправильный размер массива?

Большое спасибо за внимание к этому DLIU


person DLiu    schedule 11.04.2016    source источник


Ответы (3)


Вам не нужно возиться с этим, вы можете напрямую вводить «двоичные» данные в QByteArray, я все время использую это для отправки данных через последовательные интерфейсы во встроенных системах.

Вот пример:

QByteArray data;

// Add some data
data.append((char) 0xFF);
data.append((char) 0x00);
data.append((char) 0x55);
data.append((char) 0x99);

// Modify some data
data[0] = (char) 0x23;
data[2] = (char) 0x02;

Нет необходимости возиться с кастингом и использованием разных типов данных для хранения данных. Все это в QByteArray, который использует QSerialPort. Его (IMHO) всегда лучше попытаться сохранить типы данных одинаковыми, если вы используете Qt, это обычно означает основанный на Qt, такой как QByteArray.

И вы можете использовать data.size(), чтобы получить длину.

изменить

Еще одна вещь, на которую следует обратить внимание (возможно, здесь вы ошибаетесь), это то, что я думаю, вы думаете о QByteArray как строковом контейнере, но он также предназначен для хранения байтов (включая \ 0). Ваша переменная QByteArray hexString; уже названа неправильно - я думаю, что hexData или просто serialData более наглядно. Дело в том, что вы пытаетесь использовать строки, в которых действительно можно использовать байты и биты.

Кроме того, вам даже не нужно приводить к char (как это сделал я). Я начал делать это по привычке, потому что делал такие вещи, как:

// Serialising uint16 into bytes...
uint16_t val;
   :
msg.append((char) ((val >> 0)  & 0xFF));
msg.append((char) ((val >> 8)  & 0xFF));

Опять же, это все байты и биты, а не строки.

person code_fodder    schedule 11.04.2016
comment
Это именно то, что я ищу. Большое спасибо - person DLiu; 13.04.2016

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

Кроме того, strlen не будет надежным, если ваша строка может содержать встроенные символы NUL. Вам нужно будет отслеживать длину вручную каким-то другим способом.

person Ben Voigt    schedule 11.04.2016
comment
Привет, Бен, есть ли безопасный способ преобразовать весь массив из 'unsigned char' в 'const char' вместо моего кода ‹quote› const char cDiff = (const char) Diff; - person DLiu; 11.04.2016
comment
Этот гипс безопасен, но о размере все равно нужно позаботиться отдельно. - person Ben Voigt; 11.04.2016

используйте std :: extension, чтобы получить размеры массива статического размера:

unsigned char Diff[] = {0x45, 0x00, 0x01, 0x02};
const char *cDiff = (const char*)Diff;
int diffSize = std::extent<decltype(Diff)>::value;
QByteArray ba = QByteArray(cDiff,diffSize);

примечание: для этого требуется c ++ 11

person Andrei R.    schedule 11.04.2016