Assigning quint16_t to QByteArray while sending serial data frame from PC to device
Hi,
My structure contains a variable of type quint16_t and before sending to a device through serial port, I am appending it to a QByteArray. As QByteArray holds byte, I see only one byte is sent. Actually I want len field should hold 2 bytes.
Code:
typedef struct x_hdr
{
....
quint16_t len;
}x;
{
tx_msg->append(sizeof(x));
}
serial data frame is : SOF (1 byte)| seq (1 byte) | len (2 bytes) [holds length of data] | payload (n bytes)| chksum (2 bytes) | eof (1 byte)
When I send this, only one byte is allocated for len & chksum field.
How can append 2 bytes in the serial frame. Could someone help me on this ?
Best Regards,
Anita
Re: Assigning quint16_t to QByteArray while sending serial data frame from PC to devi
Quote:
When I send this, only one byte is allocated for len & chksum field.
If struct x_hdr's size is less than 256 bytes, then only one byte is needed to hold the size. I think you are confusing the sizes of the variables in the struct with the size of the struct itself. Just because one of the data members is 16 bits long, that adds only 2 bytes to sizeof( x ).
If you need to write a 2-byte size to your buffer, then store sizeof( x ) in a quint16_t variable and write that variable out. Same thing for your checksum.
Re: Assigning quint16_t to QByteArray while sending serial data frame from PC to devi
Quote:
Originally Posted by
d_stranz
If struct x_hdr's size is less than 256 bytes, then only one byte is needed to hold the size. I think you are confusing the sizes of the variables in the struct with the size of the struct itself. Just because one of the data members is 16 bits long, that adds only 2 bytes to sizeof( x ).
If you need to write a 2-byte size to your buffer, then store sizeof( x ) in a quint16_t variable and write that variable out. Same thing for your checksum.
I am trying to explain briefly, with pseudo code
serial data frame Format:
--------------------------------------------------------------------------------------------------------------------
(1 byte) | (1 byte) | (2 bytes) | (n bytes) | (2 bytes) | (1 byte)
-------------------------------------------------------------------------------------------------------------------
SOF | seq | len [holds length of payload] | payload | checksum | EOF
---------------------------------------------------------------------------------------------------------------------
Code:
typedef struct x_hdr
{
uint16_t id;
uint16_t type;
} X_HDR;
void MainWindow
::build_msg (uint8_t seq,
QByteArray *tx_msg
) {
uint16_t checksum;
X_HDR hdr;
switch(seq)
{
case 1:
/* update the command ID, 1byte long
tx_msg->append(seq);
/* update data to frame */
hdr.id = 0x1234;
hdr.type = 0x0;
/* update data len field, which is of 2bytes. as my struct is of 4 bytes, this field will be filled with a value 4*/
tx_msg->append(sizeof(hdr));
/* append data of nbytes, here in this case it's 4 bytes */
tx_msg->append((char *) &hdr,sizeof(hdr));
break;
}
/* Again checksum field is of 2 bytes long in the serial frame */
checksum = add_chksum(&hdr, sizeof(hdr));
tx_msg->append(checksum);
}
void MainWindow::button_pressed()
{
/* Appending SOF 0xAF (1 byte) to the serial frame */
command.append(0xAF);
build_msg (1,&command);
/*Appending EOF 0xFF (1 byte) to the serial frame */
command.append(0xFF);
/* Function writes command to serial port */
writeData(command);
}
My question is How can I make sure irrespective of value in the "len" and "checksum", I want to allocate 2bytes for each fields in the serial frame.
Is this possible with above approach? What needs to be corrected here.
Best Regards,
Anita
Re: Assigning quint16_t to QByteArray while sending serial data frame from PC to devi
I have twice edited your posts in this thread to add CODE tags to your source code listings. Please use them for your future posts. See my signature below if you don't know how.
Quote:
My question is How can I make sure irrespective of value in the "len" and "checksum", I want to allocate 2bytes for each fields in the serial frame.
I told you in my previous answer: Do not append "sizeof( hdr )", append a quint16_t variable which contains the sizeof( hdr ) value. sizeof() will return the smallest representation of the number of bytes in the argument (in your case 4 for "hdr"), which fits into a single byte, so a single byte is what gets appended. If you want 2 bytes to be appended, then you have to append a 2 byte variable.
Re: Assigning quint16_t to QByteArray while sending serial data frame from PC to devi
There is no QByteArray function to append() anything other than chars (bytes).
The sizeof(hdr) is a size_t with the value 4 (probably). size_t is variously defined, but must be at least 16-bits long and often an unsigned 32 or 64-bit integer.
At line 27 you append a single char with the value stored in the size_t (it is an implied cast). One byte in the array is what you get. As a length value it will be broken if the hdr ever exceeds 255 bytes.
If you want to write a multi-byte integer using only QByteArray then you need to code breaking it into bytes and appending them in the correct order (whichever way round that is). Something like:
Code:
size_t hdrlen = sizeof(hdr);
tx_msg->append(hdrlen & 0xff)
hdrlen = hdrlen >> 8;
tx_msg->append(hdrlen & 0xff)
or you can go this way (making the result platform architecture sensitive... your other code already is):
Code:
uint16_t hdrlen = sizeof(hdr);
tx_msg->append((char *) &hdrlen, sizeof(hdrlen));
You could also (carefully) use QDataStream.
Re: Assigning quint16_t to QByteArray while sending serial data frame from PC to devi
Quote:
Originally Posted by
ChrisW67
There is no QByteArray function to append() anything other than chars (bytes).
The sizeof(hdr) is a size_t with the value 4 (probably). size_t is variously defined, but must be at least 16-bits long and often an unsigned 32 or 64-bit integer.
At line 27 you append a single
char with the value stored in the size_t (it is an implied cast). One byte in the array is what you get. As a length value it will be broken if the hdr ever exceeds 255 bytes.
If you want to write a multi-byte integer using only QByteArray then you need to code breaking it into bytes and appending them in the correct order (whichever way round that is). Something like:
Code:
size_t hdrlen = sizeof(hdr);
tx_msg->append(hdrlen & 0xff)
hdrlen = hdrlen >> 8;
tx_msg->append(hdrlen & 0xff)
or you can go this way (making the result platform architecture sensitive... your other code already is):
Code:
uint16_t hdrlen = sizeof(hdr);
tx_msg->append((char *) &hdrlen, sizeof(hdrlen));
You could also (carefully) use QDataStream.
Thanks Chris. I could figure out the first approach mentioned above.