CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

How to go from decimal to hexadecimal array

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
pilar



Joined: 30 Jan 2008
Posts: 197

View user's profile Send private message

How to go from decimal to hexadecimal array
PostPosted: Thu Feb 08, 2024 6:19 pm     Reply with quote

Hi, I have the latitude and longitude values ​​in decimal and I need to convert them to a hexadecimal array of 4 bytes each, for this I am using this code:
Code:
#include <18F4620.h>
#fuses HS,WDT32768,PROTECT,NOLVP,MCLR,BROWNOUT,PUT
#use delay(clock=20MHz)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)// RS232 Estándar

#include <stdio.h>

#define HEX_ARRAY_SIZE 4
unsigned char latHex[HEX_ARRAY_SIZE];
unsigned char longHex[HEX_ARRAY_SIZE];
float latitude = -12.0664836;
float longitude = -77.1209702;

// Función para convertir un valor decimal a hexadecimal
void decimalToHex(float value, unsigned char *hexArray) {
    unsigned int intValue = (unsigned int)(value * 10000000); // Multiplicamos por 10000000 para obtener precisión de 7 decimales
    hexArray[0] = (intValue >> 24) & 0xFF;
    hexArray[1] = (intValue >> 16) & 0xFF;
    hexArray[2] = (intValue >> 8) & 0xFF;
    hexArray[3] = intValue & 0xFF;
}

void main() {
    // Convertir latitud y longitud a hexadecimal
    decimalToHex(latitude, latHex);
    decimalToHex(longitude, longHex);
   
    // Imprimir los valores hexadecimales
    printf("Latitud en hexadecimal: %02X%02X%02X%02X\n", latHex[0], latHex[1], latHex[2], latHex[3]);
    printf("Longitud en hexadecimal: %02X%02X%02X%02X\n", longHex[0], longHex[1], longHex[2], longHex[3]);
   
    while(TRUE);
}


But when I compile it I get this error:
Quote:
*** Error 27 "LatLog_Hex1.c" Line 16(61,62): Expression must evaluate to a constant


Can someone tell me how to correct this?.
Ttelmah



Joined: 11 Mar 2010
Posts: 19231

View user's profile Send private message

PostPosted: Fri Feb 09, 2024 2:25 am     Reply with quote

There is a huge problem in your understanding.

You don't have the values 'in decimal'. They are stored in binary, as a
floating point representation. Now at present they will be in Microchip
FP format.
First thing is if you want to send or use this, does the device you are
sending this to, want Microchip format or IEEE?.
Then you have a problem of size. A 4 byte FP value, would need 8
characters in hex. Not going to fit in a 4 character array. Then you
try to use an unsigned int to hold a value times 100million. An int in
CCS can hold a
maximum of 255. Then you are taking the bytes out of this 8bit value,
and trying to rotate these by 24, 16 and 8 bits. Not going to work, You
then refer to the output as 'hexarray', but these are simply binary bytes,
not 'hex'.

You could just use a union, or a memmove.
Code:

#include <18F4620.h>
#fuses HS,WDT32768,PROTECT,NOLVP,MCLR,BROWNOUT,PUT
#use delay(clock=20MHz)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)// RS232 Estándar

#include <stdio.h>

#define HEX_ARRAY_SIZE 4
unsigned char latbytes[HEX_ARRAY_SIZE];
unsigned char longbytes[HEX_ARRAY_SIZE];
float latitude = -12.0664836;
float longitude = -77.1209702;

void main(void)
{
    memmove((int8 *)&latitude, latbytes, 4);
    memmove((int8 *)&longitude, longbytes, 4);
   
    printf("Latitud en hexadecimal: %02X%02X%02X%02X\n", latbytes[0], latbytes[1], latbytes[2], latbytes[3]);
    printf("Longitud en hexadecimal: %02X%02X%02X%02X\n", longbytes[0], longbytes[1], longbytes[2], longbytes[3]);
   
    while(TRUE);
}


However if this is going to another device, unless this too is using CCS
(Microchip FP format), then you will need to be looking at the ieeefloat.c
library to convert before sending.

This as part of it's operation, shows how to use the union to access
the bytes in the FP value.

If you are trying to turn it into a integer representation then you would
need to be using an int32, not a simple 'int' and then access the bytes
using a union, or simply 'make8'.
Ttelmah



Joined: 11 Mar 2010
Posts: 19231

View user's profile Send private message

PostPosted: Fri Feb 09, 2024 7:47 am     Reply with quote

Looking at it again I think what he wants is the four bytes representing the
value * 10000000 as an integer. In which case:

Code:

#include <18F4620.h>
#fuses HS,WDT32768,PROTECT,NOLVP,MCLR,BROWNOUT,PUT
#use delay(clock=20MHz)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)// RS232 Estándar

#include <stdio.h>

#define BYTE_ARRAY_SIZE 4
unsigned char latbytes[BYTE_ARRAY_SIZE];
unsigned char longbytes[BYTE_ARRAY_SIZE];
float latitude = -12.0664836;
float longitude = -77.1209702;

void valtointbytes(float source, unsigned char *byteArray)
{
   union {
      signed int32 timesval;
      unsigned int8 bytes[4];
   } joiner;
   joiner.timesval=source*10000000;
   memmove(bytearray,&joiner.bytes[0],4);
}

void main(void)
{
    valtointbytes(latitude, latbytes);
    valtointbytes(longitude, longbytes);
   
    // Print the bytes as hex
    printf("Latitud en hexadecimal: %02X%02X%02X%02X\n", latbytes[0], latbytes[1], latbytes[2], latbytes[3]);
    printf("Longitud en hexadecimal: %02X%02X%02X%02X\n", longbytes[0], longbytes[1], longbytes[2], longbytes[3]);
   
    while(TRUE);
}

However I have to query the byte order. Remember the output normally
has the most significant byte to the left so will be F8CECD00, while
this will output 00CDCEF8.
Note also the addition of ERRORS in the RS232 setup. You _must_ always
have this with hardware serial, or it can become hung if an error occurs.
pilar



Joined: 30 Jan 2008
Posts: 197

View user's profile Send private message

PostPosted: Fri Feb 09, 2024 11:33 am     Reply with quote

Quote:
Looking at it again I think what he wants is the four bytes representing the
value * 10000000 as an integer

Yes, it was what I needed, thank you
Ttelmah



Joined: 11 Mar 2010
Posts: 19231

View user's profile Send private message

PostPosted: Fri Feb 09, 2024 11:40 am     Reply with quote

as a further comments, you do realise you don't have to do this at all.

Ypu can just use:

printf("Latitud en hexadecimal: %08Lx\n", (signed int32)(latitude*10000000));

This will though order the bytes as F8CECD00.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group