How to extract byte from word?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to extract byte from word?

13,901 Views
pIx
Contributor I
I am using C to programm the HCS12 and wondering how to extract a byte from a word so that I can send the data in two bytes.

Thanks,
Sujith
Labels (1)
0 Kudos
Reply
10 Replies

3,515 Views
Technoman64
Contributor III
Code:
/* Type defines */typedef long  DWORD;typedef int  WORD;typedef char BYTE;typedef unsigned long UDWORD;typedef unsigned int UWORD;typedef unsigned char UBYTE;typedef DWORD INT32;typedef WORD INT16;typedef BYTE    INT8;typedef UDWORD UINT32;typedef UWORD UINT16;typedef UBYTE UINT8;typedef BYTE BOOLEAN;typedef WORD STACK;/************************************************************************ Useful Macros Section ***********************************************************************//* Returns the low byte of the word  */#define LOBYTE(w)  ((BYTE)(w))/* Returns the high byte of the word  */#define HIBYTE(w)  ((BYTE)(((WORD)(w) >> 8) & 0xFF))/* Makes a word from \a low byte and \a high byte. */#define MAKEWORD(low, high) ((WORD)(((BYTE)(low)) | (((WORD)((BYTE)(high))) << 8)))/* Returns the low word of the double word */#define LOWORD(l)  ((UINT16)(UINT32)(l))/* Returns the high word of the double word */#define HIWORD(l)  ((UINT16)((((UINT32)(l)) >> 16) & 0xFFFF))/* Returns the low signed word of the double word */#define LOSWORD(l)  ((WORD)(DWORD)(l))/* Returns the high signed word of the double word */#define HISWORD(l)  ((WORD)((((DWORD)(l)) >> 16) & 0xFFFF))/* Makes a double word from low word and a high word. */#define MAKELONG(low, high) ((UINT32)(((UINT16)(low)) | (((UINT32)((UINT16)(high))) << 16)))

 
Example use with c code
 
WORD Test = 0xAB;
BYTE HiByte, LoByte;
 
HiByte = HIBYTE(Test);
LoByte = LOBYTE(Test);
0 Kudos
Reply

3,515 Views
Anders
Contributor I
Hello.
I'm just wondering, wouldn't it be more efficient to use a union between a word and a struct of two bytes? The processor wouldn't then have to do the rotating and anding for the high byte. Or would the compiled code still result in the same process?
 
I don't remember exactly how to do it, but something like this perhaps:
 
typedef union{
  word Word;
  struct{
    byte HIGHBYTE;
    byte LOWBYTE;
  } Bytes;
} myword;
 
/Anders
0 Kudos
Reply

3,515 Views
sjmelnikoff
Contributor III

Anders wrote:
 
I'm just wondering, wouldn't it be more efficient to use a union between a word and a struct of two bytes?

This is not recommended - especially if portability is required - as the order in which will the bytes will be arranged depends on the compiler. It is safer to use masks and shifts as suggested above.
 
Steve M.
0 Kudos
Reply

3,515 Views
Technoman64
Contributor III
I have found that the compiler is very good at optimizing the code. I have seen register swapping instructions used quite often when inspecting the code generated by the compiler.

You do have a good point with the struct though. A person could generate code usign differant methods and inspect the code to see which method is optimized the best.

Just a thought...
0 Kudos
Reply

3,515 Views
pIx
Contributor I
Just to clarify, I have declared the variable holding the data as an unsigned short, therefore it has a 16 data in it.
0 Kudos
Reply

3,515 Views
mjbcswitzerland
Specialist V

Hi Sujith

There are two ways. The portable and non-portable way.

******************* Non-portable ********************
unsigned char *ptr = &usWord;

send-routine(*ptr++);
send-routine(*ptr);

*****************************************************
This works but the order of the bytes is 'endian' dependent. Big-endian (like HC12) or little-endia (like 80186).
If usWord is 0x1234, the data sent will be 0x12, 0x34 when big-endian or 0x34, 0x12 when little endian.
Generally network ordering (as used by Internet etc.) corresponds to the big-endian ordering.


******************* portable ************************

send-routine((unsigned char)(usWord>>8));
send-routine((unsigned char)(usWord));

*****************************************************
The portable version will give the same results as the non-portable when using the HC12. The portable case also specifically sends in network order.

Regards

Mark Butcher
www.mjbc.ch / www.uTasker.com

0 Kudos
Reply

3,515 Views
kwik
Contributor I
/*-------------------------------------------*/
/* If the word has hex value 1234 then */
/*-------------------------------------------/*
unsigned short usWord=0x1234;

/*-------------------------------------------*/
/* To get the upper char ,just And with 0xF0 */
/* and shift right 8 places.result is 0x12 */
/*-------------------------------------------*/
unsigned char upper = (unsigned char)((usWord & 0xF0) >> 8);

/*-------------------------------------------*/
/* To get the lower char ,just And with 0xF */
/* thats it...result is 0x34 */
/*-------------------------------------------*/
unsigned char lower = (unsigned char)(usWord & 0x0F);
0 Kudos
Reply

3,515 Views
mjbcswitzerland
Specialist V
Hi Kiwi

Careful with the logical arithmetic.
You need to AND with 0xff00 and 0x00ff and not 0xf0 resp. 0x0f.
However the AND operations are also superfluous since the casting to unsigned char chops the 16 bit word to 8 bits and so it really doesn't matter whether the other bits have been set to zero or not.

Regards

Mark
0 Kudos
Reply

3,515 Views
kwik
Contributor I
Yes of course !! he he.
0 Kudos
Reply

3,515 Views
pIx
Contributor I
Ok.... 1 way I figured out to get the MSB is to right or left shift 8 times and then AND it with 0x0F and dump it into the register. Is there an equivalent of assembly LDB, DPB in C for codewarrior that will just extract the upper or lower byte?
0 Kudos
Reply