|
|
View previous topic :: View next topic |
Author |
Message |
iman_zahari
Joined: 20 Jul 2010 Posts: 15
|
Convert decimal to hex and then change the msb/lsb |
Posted: Sun Oct 10, 2010 2:33 am |
|
|
Good day all,
I'm using 16f877a for voltage/current measurement. However, to feed it into modbus, I need to convert to hex and then change the position of the msb with lsb.
It is a 10 bit adc resulting 1024 samplings. Say convert 502 decimal to 0x01F6 and then change it to 0xF601? It can't be done by shift position command. Lol. I know it's a stupid idea. Anyone got any good suggestion? Thanks in advance :D |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Sun Oct 10, 2010 3:59 am |
|
|
ADC values are neither decimal nor hexadecimal, they are just binary. Decimal or hexadecimal are printable reprentations of the binary value.
Exchanging MSB and LSB of a 16 bit value can be done in different ways, with CCS C, it can be best done with built-in functions
Code: | outvar = make16(make8(invar,0),make8(invar,1)); |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Sun Oct 10, 2010 4:59 am |
|
|
However there may be no point!....
I suspect the actual requirement, is to output the bytes in reverse order in hex, using printf/sprintf. In which case, just send the value as bytes with the order reversed, rather than 're-assembling' the number with the bytes swapped.
So:
Code: |
int16 val;
val=502;
printf("%02X%02X",make8(val,0),make8(val,1));
|
So you output the LSB first as a 2 digit hex value, then the MSB second, rather than changing the number itself.
Best Wishes |
|
|
iman_zahari
Joined: 20 Jul 2010 Posts: 15
|
|
Posted: Sun Oct 10, 2010 5:18 am |
|
|
Ttelmah wrote: | However there may be no point!....
I suspect the actual requirement, is to output the bytes in reverse order in hex, using printf/sprintf. In which case, just send the value as bytes with the order reversed, rather than 're-assembling' the number with the bytes swapped.
So:
Code: |
int16 val;
val=502;
printf("%02X%02X",make8(val,0),make8(val,1));
|
So you output the LSB first as a 2 digit hex value, then the MSB second, rather than changing the number itself.
Best Wishes |
Ohh, I see. Very efficient. I'll try first. Thanks for the suggestion. Really appreciate it. |
|
|
iman_zahari
Joined: 20 Jul 2010 Posts: 15
|
|
Posted: Sun Oct 10, 2010 5:31 am |
|
|
FvM wrote: | ADC values are neither decimal nor hexadecimal, they are just binary. Decimal or hexadecimal are printable reprentations of the binary value.
Exchanging MSB and LSB of a 16 bit value can be done in different ways, with CCS C, it can be best done with built-in functions
Code: | outvar = make16(make8(invar,0),make8(invar,1)); |
|
Thanks for reminding me FvM. Totally forgot about it . Thanks for the suggestion, I'll try it too. |
|
|
iman_zahari
Joined: 20 Jul 2010 Posts: 15
|
|
Posted: Sun Oct 10, 2010 7:55 am |
|
|
FvM wrote: | ADC values are neither decimal nor hexadecimal, they are just binary. Decimal or hexadecimal are printable reprentations of the binary value.
Exchanging MSB and LSB of a 16 bit value can be done in different ways, with CCS C, it can be best done with built-in functions
Code: | outvar = make16(make8(invar,0),make8(invar,1)); |
|
YESSSSS! FvM, I love you so much. You're method worked!!! For Ttelmah, I tried yours but its a bit complicated. A bit mending and it looked similar to FvM's code. Thank you all!~ |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Sun Oct 10, 2010 9:00 am |
|
|
One of the favorite ways in the microchip libraries of manipulating data around like that is to use a structure:
Keep in mind, these are for Microchip compilers, so a little editing might be needed. (like the WORD == unsigned in16 for CCS instead of unsigned short int
Code: |
typedef unsigned char BYTE; /* 8-bit unsigned */
typedef unsigned short int WORD; /* 16-bit unsigned */
typedef union {
WORD Val;
BYTE v[2] __PACKED;
struct __PACKED {
BYTE LB;
BYTE HB;
} byte;
struct __PACKED {
BYTE b0:1;
BYTE b1:1;
BYTE b2:1;
BYTE b3:1;
BYTE b4:1;
BYTE b5:1;
BYTE b6:1;
BYTE b7:1;
BYTE b8:1;
BYTE b9:1;
BYTE b10:1;
BYTE b11:1;
BYTE b12:1;
BYTE b13:1;
BYTE b14:1;
BYTE b15:1;
} bits;
} WORD_VAL, WORD_BITS;
|
And then in their code they'll declare a var:
WORD_VAL adc_result;
And then
adc_result.Val = (command to read ADC)
Then for your printf,
printf("%02X%02X", adc_result.LB, adc_result.HB ); _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Sun Oct 10, 2010 10:14 am |
|
|
Not actually the structure that matters here, it is the union.
Make8 is as efficient, but is 'CCS specific', and it makes it very easy to see what is going on, with something like:
Code: |
union {
int16 word;
int8 b[2];
} value;
#define LSB (0)
#define MSB (1)
value.word=502;
printf("%02X%02X",b[LSB],b[MSB]);
|
The big advantage of this, is that it should work on any C, that defines an int8, and int16 type, and by just swapping LSB/MSB, will still work the same with chips that already have a reversed byte order.
The only advantage of doing it directly (my approach), over FvM's approach, is that you don't need another variable, and potentially it is a 'smidgeon' faster.
Best Wishes |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Sun Oct 10, 2010 10:54 am |
|
|
Yep.
I just thought I'd toss it in so he has additional options, AND in case he looks at Microchip libraries anytime.
CCS makes some things very nice - but not exactly portable. Sometimes that's ok - sometimes it's a rear-cheek biter. But it's all about the tradeoff. So I'm not complaining. Just noting.
Cheers,
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
|
|
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
|