|
|
View previous topic :: View next topic |
Author |
Message |
pilar
Joined: 30 Jan 2008 Posts: 197
|
How to go from decimal to hexadecimal array |
Posted: Thu Feb 08, 2024 6:19 pm |
|
|
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: 19539
|
|
Posted: Fri Feb 09, 2024 2:25 am |
|
|
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: 19539
|
|
Posted: Fri Feb 09, 2024 7:47 am |
|
|
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
|
|
Posted: Fri Feb 09, 2024 11:33 am |
|
|
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: 19539
|
|
Posted: Fri Feb 09, 2024 11:40 am |
|
|
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. |
|
|
|
|
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
|