Converting between bytes/String HEX/ char etc

Since Cpp is not my main language, I struggle to find the best way to convert between types for my needs.
So my starting point is

struct can_frame {
    canid_t can_id;  /* 32 bit CAN_ID + EFF/RTR/ERR flags */
    __u8    can_dlc; /* frame payload length in byte (0 .. CAN_MAX_DLEN) */
    __u8    data[CAN_MAX_DLEN] __attribute__((aligned(8)));
};

So first I needed it bo send to Serial as a hex string, so solution I've found and used was

String frame = "CAN:";
char dataString[1] = {0};
sprintf(dataString, "%03X", can1Msg.can_id);
frame += dataString;
for (int i = 0; i < can1Msg.can_dlc; i++) {  // print the data
  char dataString[1] = {0};
  sprintf(dataString, "%02X", can1Msg.data[i]);
  frame += " " + String(dataString);
}

Doesn't seem elegant byt it did the job.

But then I needed to do some checking of ID and specific bytes
So I've saved all String ins String bytes[8]
So now I could something like

if (id == "2A0" && bytes[0] == "A0") {

And that was almost over, but then I realized that I need to do some checking of Integer number that is saved on 3 bytes.
E.G byte[2] + byte[3] + byte[4] which would something like 0020A0 whih will be 8352 as an Int

But converting things around gave all the problems such us String to const char* etc.
I wanted to convert __u8 to byte array so I can do checks and conversions and eventually convert it to string, but I've failed.
Can anyone suggest best approach for this ?

That’s already a bug - you have only 1 Byte in your char buffer and try to store 4 (3 digits and trailing null).

Same goes in the for loop

Don’t go to string representation, just compare the bytes from the array with && and print items separately to form the ASCII output, you likely don’t need in your code the full representation

How exactly are you planning to fit 3 chars into 1 char

1 Like

Bug noted.

But my starting point is __u8 and thats not a byte. So to compare to byte i still have to convert it right ?

Also i dont need Ascii, i only need integers from hex and hex as a string

So i want to habe a string like "03A 00 01 4A 5A 00 76 88"

But also i want to be able to do if(byte[3) == 0x03)

And i also need to know what is integer stored in e.g byte[3] + byte[4]

Mayne calling it a byte is not clear, But I meant hex byte

It could be anything, provide type definition or this will be anyone's guess.

Ok so I think i have to go back and understand what am I dealing with first.

Usually the __uN (like __u8) are Linux-specific typedefs predating the standard uintN_t (Like uint8_t) that were added later in C and C++ specification but made their ways in many libraries such as the CAN libraries that can be cross platforms

So I think it’s a fair assumption to treat them as unsigned char (bytes).

See for example

1 Like

What for?

Sorry, but every time I read "I need to convert this to hex" - it turns out that the person simply does not understand that 0xFF and 255 are the same

99% for the fact that this is exactly a byte

I want to send it as a hex string for displaying purpose. I am using BT adapter and sending it to my android app via serial.

Sp it's just lack of experience with cpp then, not sur why I assumed that what I receive is not a byte.

I will approach that again with this in mind

if comparing the raw data values, express them in hex or decimal, not ascii

if (id == 0x2A0 && bytes[0] == 0xA0) {

Thank you for help. Like I said stupidly I assumed that data I have are not bytes. Knowing that they are bytes changes everything.

So for operation I can do e.g.

int value = msg.data[5] | (msg.data[4] << 8) | (msg.data[3] << 16);

For Hex string I am still using sprintf but with correct length dataStream

And for comparison like mention above, just byte to byte

if (can1Msg.can_id == 0x2A0 && can1Msg.data[0] == 0x34) {

So that's everything I need.
Thank you

presupposes an int has more than 16 bits, no? implementation dependent.

That's the bit I am not sure about and yeah I got a warning on that, as you can shift it with << 16.
What it should be is speed multiplied by 2 I believe. I will have to check that on the car.
But even then max value of the int would be something like 600 (?) meaning it's 300km/h, so I think byte[3] would always be 00.

But what I don't understand, what if I need such an integer ? what should I use, unsinged long ? That still doesn't silence warning, so am I right to assume that library would have to be adjusted with types ?

or something like
int speed = (uint32_t)msg.data[5] | ((uint32_t)msg.data[4] << 8) | ((uint32_t)msg.data[3] << 16);

You've missed it, or I have - you're still assigning a 32 bit value to the int (left side of the expression), which will depend upon what the native int size is for your particular platform.
C

multiplies whatever was there by 65536 (i.e. 2^16).

Guess I'd better re-read the whole thread, to get the gist of what it is that your trying to do, and where you're confounded. Maybe after dinner.
C

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.