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

make int16 from two int8?

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



Joined: 09 Apr 2009
Posts: 29

View user's profile Send private message

make int16 from two int8?
PostPosted: Sat Nov 06, 2010 11:51 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Nov 07, 2010 3:12 am     Reply with quote

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: 19365

View user's profile Send private message

PostPosted: Sun Nov 07, 2010 3:19 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Nov 07, 2010 4:03 am     Reply with quote

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: 19365

View user's profile Send private message

PostPosted: Sun Nov 07, 2010 5:26 am     Reply with quote

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: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Sun Nov 07, 2010 8:15 am     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Nov 07, 2010 3:04 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Sun Nov 07, 2010 3:50 pm     Reply with quote

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

View user's profile Send private message Visit poster's website

PostPosted: Sun Nov 07, 2010 7:08 pm     Reply with quote

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: 19365

View user's profile Send private message

PostPosted: Mon Nov 08, 2010 3:02 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Nov 09, 2010 12:05 am     Reply with quote

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.
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