Search code examples
c++qtcharqbytearray

How to use Qt QSerialPort to send hex 0x00


I am new to coding. Please bear with me. I learnt from the Qt example Terminal and tried to send raw hex bytes. At first I could send 0x57, 0x04, 0x02 with no problem. Like this

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

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

Then, as I progressed, I needed to send some selectable data strings with 0x00s. The above code would not send \x00 and would erase anything behind it, so I used 'fromRawData' to stop conversion of special character.

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

The above code was okay to send both constant char strings. But now I face a real challenge, I need to send non-constant hex bytes. I created an unsigned char array to store my Hex string and later changed its value. Then casted it to a const char array. But this casting gave wrong size.

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

In case 3, I got 0x45 0x00, 0x08, 0x02, 0x01, 0x00, 0x00, 0x00, total 8 bytes on my MCU board! Then I changed Diff[] size to 10, and again sizeof(cDiff) = 8 too. Last two bytes got truncated.

My first question is, is there a better way to send unsigned char of different array size and values range from 0x00 to 0xFF, determined in runtime using QSerialPort? Second question is, why the cast gave me wrong array size?

Thank you very much for your attention on this DLIU


Solution

  • You don't need to be doing all this messing around, you can enter "binary" data into QByteArray directly, I use this all the time for sending data via serial interfaces on embedded systems.

    Here is an example:

    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;
    

    There is no messing about with casting and using different data types to store the data. Its all in QByteArray, which QSerialPort uses. Its (IMHO) always best to try to keep the data types the same, if using Qt it generally means a Qt based one like QByteArray.

    And you can use data.size() to get the length.

    edit

    One other thing to note (maybe this is where you are going wrong) is that I think you are thinking of QByteArray a string container, but it is also designed to contain bytes (including \0's). Already your variable QByteArray hexString; is kind of wrongly named - I think hexData or just serialData is more descriptive. The thing is you are trying to use strings where you can really be using bytes and bits.

    Also, you do not really even need to cast to char (as I have done) I started doing this by habit because I was doing things like:

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

    Again, its all bytes and bits and not strings.