Как использовать 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);
}

Затем, по мере продвижения, мне нужно было отправить несколько выбираемых строк данных с 0x00s. Приведенный выше код не будет отправлять \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 тоже. Последние два байта были усечены.

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

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

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));

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

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

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

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

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

Другие вопросы по тегам