Convert string or word to 4 bytes

Hello ,

I need to convert a value to 8 bytes,
The frequency is LSB. For example
415.75MHz=415750000Hz=0x18C7D770. So the data to be sent are 0x70,0xD7,0xC7,0x18

Is this a word or long ,415750000 , and how can i convert it to 8 HEX bytes.

Any help is deeply appreciated ,
Philip

We get this kind of question a lot, and it's almost always not clear whether you need to send the raw bytes, or an ASCII (text) string containing a hex representation of those bytes.

Another way to say it, there is really no such thing as "hex bytes".

It's helpful, if you explain the entire context in which the data is sent, for example where it is going...

Is this a word or long ,415750000

'word' is not often used in C/C++, the data size may vary. That is true of 'long' as well, but in Arduino argot, it is a better choice. Edit - for this purpose, 'unsigned long' would be best.

It's 4 bytes (0x18C7D770) so it's a long or unsigned long.

0x18C7D770 contains only 4 bytes. You are discussing 8 bytes. Please explain the difference.

Yes sorry 4 bytes , it is a HEX value that is to be sent over serial like this:
byte message3[12]={0x68,0x06,0x01,0x01,0x00,0x00,0x00,0x04,Payload[0],Payload[1],Payload[2],Payload[3]};

Serial2.write(message3,sizeof(message3));

It's not a HEX value; it's just a number in 4 bytes.

You can try the below; it might swap the bytes of yourFrequency in message, I can't test that now.

// note: last 4 bytes not filled
byte message3[12]={0x68,0x06,0x01,0x01,0x00,0x00,0x00,0x04};
long yourFrequency = 0x18C7D770;
// copy the payload
memcpy(&message[8], (byte*)&yourFrequency, sizeof(yourfrequency));
// send it
Serial2.write(message3,sizeof(message3));

Not compiled !!

here's 2 ways..

union
{
   unsigned long ulong;
   byte bytes[4];
} uLongBytes;





void setup() {
  // put your setup code here, to run once:
Serial.begin(115200);

unsigned long value = 12345678;
uLongBytes.ulong = value;
Serial.print("bytes:");
Serial.print(uLongBytes.bytes[0]);
Serial.print(uLongBytes.bytes[1]);
Serial.print(uLongBytes.bytes[2]);
Serial.println(uLongBytes.bytes[3]);
byte arr[4];
arr[0] = value & 0xFF; 
arr[1] = (value >> 8) & 0xFF; 
arr[2] = (value >> 16) & 0xFF; 
arr[3] = (value >> 24) & 0xFF;
Serial.print("bytes:");
Serial.print(arr[0]);
Serial.print(arr[1]);
Serial.print(arr[2]);
Serial.println(arr[3]);

}

void loop() {
  // put your main code here, to run repeatedly:unsigned long valye = 0x12345678;


}

run it here..

have fun ~q

FYI, the method using unions is not guaranteed because the alignment of data (internal representation) of data in a union, is officially undefined.

Here we go again (or hopefully not)...

As you can see, I was completely correct about the "hex bytes" misinterpretation. Always be on the lookout for it on this forum because it happens over and over...

like the union better, more elegant..
curious, is there not a way to pack it, like you can a structure??

A lot of the shine of the elegance, comes off when it fails.

I've used a packed struct inside a union. But the reason was to implement bit fields, not pack the bytes. The compiler is an optimizing compiler, it can be trusted to pack the bytes. :slight_smile: Now I know better, I haven't done this recently but when I do, it will be using the safe memcpy method.

...less correct.

union
{
   unsigned long ulong;
   byte bytes[4];
} uLongBytes  __attribute__((__packed__));

like this??

or this??

#pragma pack(1)  
union
{
   unsigned long ulong;
   byte bytes[4];
} uLongBytes ;

or are unions fundamentally flawed??

never mind..
just read this..
You cannot use a union for type punning because you are not allowed to first write to one member of the union, and then read from a different one.
makes sense..

I get this as output:
bytes:11221519924

Should be 18C7D770.

Serial.print("bytes:");

Serial.print(arr[0],HEX);

Serial.print(arr[1],HEX);

Serial.print(arr[2],HEX);

Serial.println(arr[3],HEX);

bytes:70D7C718
bytes:70D7C718

Thank Gents,

use memcpy() function:

long int y = 415750000;   //18C7D770
byte myData[4];

void setup()
{
  Serial.begin(9600);
  long *ptrS;
  ptrS = (long*)&y;

  byte *ptrD;
  ptrD = (byte*)myData;

  memcpy(ptrD, ptrS, 4);
  for (int i = 0; i < 4; i++)
  {
    Serial.print(myData[i], HEX);
    Serial.print(' ');
  }
}

void loop()
{
}

Output:
70 D7 C7 18

Why two lines?
Why the cast?

Now, I know that I am loading the pointer variable.

ptrD is being loaded with the base address of a byte-organized memory space.

So, why the cast?
And why two lines?

The array is an array of bytes; the pointer is a pointer to a byte. No cast needed.

Sorry, learning..
So could just do??

memcpy(&myData,&y,4);