View previous topic :: View next topic |
Author |
Message |
Study
Joined: 09 Apr 2009 Posts: 29
|
make int16 from two int8? |
Posted: Sat Nov 06, 2010 11:51 pm |
|
|
Hi firneds
I give 16 bit data from a device in 2 byte ( MSB and LSB ) and save them in 2 variable, now what's the best way to merge them again to get 16bit again in single int16 var?
Regards _________________ Sorry if i have much mistakes, my english is not good.
Thanks a lot for your helps.
Have a good time |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Sun Nov 07, 2010 3:12 am |
|
|
Check the online help for the make16() built-in function. There are also other methods using standard C syntax, but make16 is most convenient. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Sun Nov 07, 2010 3:19 am |
|
|
Three routes.
1) make16. CCS function to do exactly this. Codes efficiently.
2) Arithmetic. Copy the MSB into an int16, and shift it eight times, then add the LSB. Least efficient solution. However the compiler does 'know' that if you cast an int8 to int16, and then multiply by 256, it'll perform this with a single byte move. Advantage will work on any chip with the same byte ordering.
3) Union. You declare a union like:
Code: |
union {
int8 b[2];
int16 w;
} fred;
|
Then you can write/read fred.b[0], and fred.b[1] for the two bytes, and write/read fred.w for the whole word.
This codes as efficiently as the make16, and has the advantages, that again it is not 'CCS specific', is _more_ efficient, in that the data never actually needs to move, if you write the bytes directly into the byte locations, and works in both directions.
You can even create a structure with two bytes 'named' as LSB/MSB, and a union between this and the int16, so that the code becomes much more 'self documenting'. Putting a value into 'fred.MSB' or fred.LSB, does make it very obvious what is going on. Even better, you only have to reverse the declarations in the structure to handle a processor that has the bytes in the opposite order.....
Best Wishes |
|
|
Study
Joined: 09 Apr 2009 Posts: 29
|
|
Posted: Sun Nov 07, 2010 4:03 am |
|
|
Thanks a lot my friends
very complete and usefull answer Ttelmah, than you.
i didn't understand well in 3rd method ( union ) what should i do with them to do my work? can you show me simple example code in both direction please? ( 8and8 to 16 and inverse )
Thanks again _________________ Sorry if i have much mistakes, my english is not good.
Thanks a lot for your helps.
Have a good time |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Sun Nov 07, 2010 5:26 am |
|
|
A 'union', is a standard bit of C. It allows you to have two variables, that are put into the same location in memory.
So:
Code: |
struct parts {
int8 LSB;
int8 MSB;
};
//Declares a two byte 'structure', containing 'LSB', and 'MSB' - does not actually create it though
union {
int16 wholething;
struct parts bytes;
} value;
//declares a union, containing an int16, and the structure just declared
//Then in the code.
value.wholething = 0x1234; //puts 16bit value into the int16 in the union
printf("%02x\n\r",value.bytes.MSB); //Prints '12' - MSB
printf("%02x\n\r",value.bytes.LSB); //Prints '34' - LSB
value.bytes.LSB=1; //Puts 8bit value into the LSB
value.bytes.MSB=2; //and another into the MSB
printf("%04Lx\n\r",value.wholething); //Prints '0201' from the int16
|
Here I have done the structure, so the bytes have logical names, but you can equally just use the byte array I originally showed.
As you can see, it goes 'bothways', allowing you to write an int16, and then access the bytes, or write bytes and then access the int16.
The same method can be used with larger types too, such as float, or int32.
Best Wishes |
|
|
bkamen
Joined: 07 Jan 2004 Posts: 1615 Location: Central Illinois, USA
|
|
Posted: Sun Nov 07, 2010 8:15 am |
|
|
If I plan on reading/writing bytes/words in/out, I like the union method the best...
(as Ttelmah's already explained)
It's standard C and portable...
-Ben _________________ Dazed and confused? I don't think so. Just "plain lost" will do. :D |
|
|
Study
Joined: 09 Apr 2009 Posts: 29
|
|
Posted: Sun Nov 07, 2010 3:04 pm |
|
|
Thanks a lot again, very useful help.
with best wishes _________________ Sorry if i have much mistakes, my english is not good.
Thanks a lot for your helps.
Have a good time |
|
|
John P
Joined: 17 Sep 2003 Posts: 331
|
|
Posted: Sun Nov 07, 2010 3:50 pm |
|
|
It doesn't have to be complicated:
Code: |
int16 myvariable;
#byte myv_low = myvariable
#byte myv_high = myvariable+1
|
Once you've done this, you can just refer to myv_low and myv_high as though they were declared as int8's in the usual way. |
|
|
andrewg
Joined: 17 Aug 2005 Posts: 316 Location: Perth, Western Australia
|
|
Posted: Sun Nov 07, 2010 7:08 pm |
|
|
bkamen wrote: | I like the union method the best... It's standard C and portable... | It's not portable, it's dependent on CPU byte ordering. Standard C and portable is option 2. I tend to use option 1 (make16) and when I need the code to run on my PC for testing purposes write a macro that implements option 1 (make16) as option 2 (<< and |). _________________ Andrew |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Mon Nov 08, 2010 3:02 am |
|
|
The union is potentially portable. As I said in the last line of my original post. All you do, is have a #define and #if, that swaps the order of MSB/LSB in the struct. It is so much more efficient to code than the arithmetic version, that this is really the 'best' solution.
So, if you want a portable solution:
Code: |
#define MSBFIRST
#ifdef MSBFIRST
struct parts {
int8 MSB;
int8 LSB;
};
#else
struct parts {
int8 LSB;
int8 MSB;
};
#endif
|
Best Wishes |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Nov 09, 2010 12:05 am |
|
|
For me, the portability issue is not important. I very rarely re-use code
between projects with different types of processors. I think it happened
only a couple times in my career. The projects are just too different.
The main things of importance for me are rapid development, reliability
of the code, and easy readability of the code for later maintenance.
Probably in that order. Also, I should say that I'm probably the only
one who ever looks at the code.
For these reasons, "make16" is one I use. Even if I forgot what it means
(which I would not do) the function name is self-documenting and strongly
hints at what it does. |
|
|
|