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

struct definition problem

Hi,

I'm using KEIL uVision2 V2.20a, This definition doesn't work, anyone know why ?

Usually I'm using this to access each bit separatly in a byte, rather than using shifting ans masking. In my MPLAB C its working fine. But when using this declaration in KEIL I get the error:

ERROR C150 'b0' bit member in struct/union

My struct definition is:

struct structSplitByte
{
bit b0;
bit b1;
bit b2;
bit b3;
bit b4;
bit b5;
bit b6;
bit b7;
};

union unionSplit
{
struct structSplitByte Split;
char cValue;
};



Or does anyone know a better and easy way to access the value of one bit in a byte ?

Thank you,

Aldrin,


  • "bit" is not a standard C type. Even if two different compilers both happen to choose that word as a keyword for an extension, they will most likely implement their extensions in different ways. If you use non-standard extensions, then you'll have to do a bit of work to port between compilers.

    With Keil C, the "bit" type is a way to declare an individual variable that resides in the bit-addressable memory region of the 8051. Variables of "bit" cannot be members of a structure. As the manual says for error 150, "A union-aggregate may not contain members of type bit". (Seems pretty clear to me, if blunt.) Other limitations of the bit type are discussed in the manual in Chapter 3, "Bit Types", page 98.

    If you want to access data as either a byte or bits, and want to use the 8051's bit-addressable memory to hold that byte, you probably want to use the Keil "bdata" memory type and "sbit" extensions. The "badata" memory qualifer locates variables in the bit-addressable memory. The "sbit" type is a way to declare a bit that is part of an object in bdata. So, one possible port of your code might look something like:

    char bdata cValue;
    sbit cValueBit0 = cValue ^ 0;
    sbit cValueBit1 = cValue ^ 1;
    sbit cValueBit2 = cValue ^ 2;
    sbit cValueBit3 = cValue ^ 3;
    sbit cValueBit4 = cValue ^ 4;
    sbit cValueBit5 = cValue ^ 5;
    sbit cValueBit6 = cValue ^ 6;
    sbit cValueBit7 = cValue ^ 7;
    

    The bdata and sbit types are discussed in the manual right after the bit types, in the "Bit-addressable Objects" section. You'll want to read carefully to note the bit ordering if you want to declare multi-byte words in bdata and access those bits.

    There's also the standard ways in C to access bits in a byte, which have nothing to do with the 8051 architecture. Bitwise "and" and "or" operations work just fine. And you could use C bitfields, though those have their own portability problems. If the data you want to access doesn't reside in the bit addressable memory (or an SFR), but is just an "ordinary" variable in data or xdata, then you'll need to use those mechanisms instead of "bit" or "sbit".

  • "If the data you want to access doesn't reside in the bit addressable memory (or an SFR), but is just an 'ordinary' variable in data or xdata, then you'll need to use those mechanisms instead of 'bit' or 'sbit'."

    OR copy the data to a bit-addressable temporary location, and work with that?

  • >Usually I'm using this to access each bit
    >separatly in a byte, rather than using
    >shifting ans masking. In my MPLAB C its
    >working fine. But when using this
    >declaration in KEIL I get the error:

    As said by others, the "bit" directive is compiler specific.

    PIC processors can manipulate bits in every register, so naturally the PIC compiler allows you to define bit variables anywhere in memory.

  • does anyone know a better and easy way to access the value of one bit in a byte ?

    Use a bit-field?

    Jon

  • The bit field method would look something like this:

    struct structSplitByte
    {
        unsigned char    b0:1;
        unsigned char    b1:1;
        unsigned char    b2:1;
        unsigned char    b3:1;
        unsigned char    b4:1;
        unsigned char    b5:1;
        unsigned char    b6:1;
        unsigned char    b7:1;
    };
    
    union unionSplit
    {
        struct structSplitByte Split;
        char cValue;
    };
    
    This does give nice neat source code, but is potentially difficult to port as C does not specify the order of the bit fields in memory. Also, Keil is sometimes rather inefficient when accessing 1-bit fields.

    The most portable method is to use masks.

  • "...is potentially difficult to port as C does not specify the order of the bit fields in memory"

    and has its own difficulties in C51, as Keil's implementation can be somewhat unexpected!

    Search the knowledgebase (and this forum) as there are articles on the common pitfalls!

    Another reason to stick with the masks...?