This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Accessing bytes of long data type

I know that longs are stored MSB first in memory. I need to access individual bytes of a long in order to send them out the SPI port. There are a number of ways to do this, I'd like your opinion on which approach might be best (from whatever perspective).

Two that come to mind is to simply declare the variable as a long pointer and then access each byte using the pointer. Pretty clean as far as I am concerned, but don't know if there's a better C51 way to handle this task.

Another --more convoluted, maybe even ugly-- is to avoid direct memory access and simply rotate/mask the long and cast into an unsigned char four times to grab each byte. Ugly at best.

Thanks,

-Martin

Parents
  • BTW, portability is of little concern here. Besides, it can be easily handled by encapsulating the byte-select operation into it's own little function:

    unsigned char byte_select(unsigned long value)
    {
    // Whatever technique

    }

    If the code had to be ported to a different device this routine would simply be redone for best results.

Reply
  • BTW, portability is of little concern here. Besides, it can be easily handled by encapsulating the byte-select operation into it's own little function:

    unsigned char byte_select(unsigned long value)
    {
    // Whatever technique

    }

    If the code had to be ported to a different device this routine would simply be redone for best results.

Children
  • Would be the way to access the bytes? Or, should I bite the bullet and do a lot of shifting?
    You could shift, the Keil compiler is smart enough to do "byte picking" when shifts are constant multiples of 8, thus no overhead would result.

    Of course, the "dynamic" way to do it would be with a union, I do that in many places.

    Erik

  • the Keil compiler is smart enough to do "byte picking" when shifts are constant multiples of 8

    Not always, or so I've found. That is, while the U32 shift function might be smart enough to run faster by skipping multiples of 8, the code generator isn't smart enough to avoid the shift entirely. For example:

    U8 nextHighest;
    MultiByte32 val;
    
    nextHighest = val.u8[1];
    

    generates considerably smaller code than

    nextHighest = (U8)(val >> 24);
    

    In this case, the code generator still sets up an entire U32 to run through the library shift function, when it need not be called at all.

    Union details for the curious:
    /// provides access to words/bytes of a U32
    typedef union
        {
        U32 u32;
        U16 u16[2];
        U8  u8[4];
        struct { MultiByte16 msw; MultiByte16 lsw; } words;
        } MultiByte32;
    

    With other compilers on bigger processors I usually just went the pointer route where necessary.

  • I like the "MultiByte32" union approach. Does this work well with function arguments? Can you pass a MultiByte32 as an arg?