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

toggling port pins through an element in a structure

Here is what I am trying to do:

sbit PORT_1_0 = P1^0;

void main ()
{ PORT_1_0 = 1; while(1) { PORT_1_0 =~ PORT_1_0; }
}

Now this is as simple as it gets.
The question is, is it possible to do the same thing using an element of a struct?

Something like:

struct abc
{ unsigned char bit : 1;
};

struct bit bit_array[24];

bit_array[0].bit = P1^0; //Assign the port pin to be toggled

//and then the toggling here.

Basically, how to assign a port pin to the bit in a struct? I am doing this because based on the address of a frame, I need to decide which pin is to be set.
I hope you get the question.

Parents Reply Children
  • struct abc
    { unsigned char bit : 1;
    };
    
    struct abc bit_array[24];
    

    cant this be implemented using bit padding, instead of declaring an array of 24 bit (which eventually consume 24*8 bytes)?

    eg:

    struct abc
    { unsigned char bit_0:1; unsigned char bit_1:1; unsigned char bit_2:1; ... unsigned char bit_n:1;
    };

    what are the shortcomings?

  • "what are the shortcomings?"

    The basic processor instructions available if wanting indexed access to bit data is by doing things like:

    enum {
        BIT_CHARLIE = 0,
        BIT_BENNY = 1,
        BIT_JOHN = 2,
        ...
    };
    uint8_t my_flags;
    my_flags |= 1u << bit_pos;
    my_flags &= ~(1u << bit_pos);
    if (my_flags & (1u << bit_pos)) {
        ...
    }
    my_flags |= 1u << BIT_BENNY;
    

    So the above is often used together with #define or inlined functions to operate on arrrays of words, to allow longer bit arrays than what will fit in a process-addressable memory unit. i.e.

    uint8_t my_bitarray[100];
    
    my_bitarray[bit_pos >> 3] |= 1u << (bit_pos & 0x07);
    

    The above obviously expands to multiple procesor instructions.

    Why a "bit" variable can be set with a single instruction. Cleared with a single instruction. Tested with a single instruction. All because the instruction contains both what to do "set/clear/test" and which specific bit to do it on. Which also is the reason why there is a very hard limit to the number of bit variables that a 8051 program can have - no more than the addressing range hard-coded in the dedicated bit instructions.

  • cant this be implemented using bit padding,
    You mean bit fields. There is no such thing as bit padding.

    instead of declaring an array of 24 bit
    Not really. Because what you propose loses a major property of what the OP was trying to do. Array elements are addressed by number, struct elements (including bit fields) are addressed by name. The OP wanted an array, so a struct won't work for him. Nor would that struct really offer any benefit over a "bit array" technique, where you use set/clear/query macros to get the values of individual bits out of an array of bytes, as in

    #define BIT_ARRAY_DEFINE(array,nbits) uint8_t array[(nbits + 7)/8];
    #define BIT_ARRAY_SET_BIT(array,n) ((array)[(n)/8] |= (1 << ((n) & 7)))
    

    SFRs (boths as bytes and as bits) in an '51 controller are rather weird by modern standards. You cannot construct a pointer to an SFR, because they do not allow indirect addressing. So no arrays of SFRs or SFR bits, no constructing a pointer to an SFR, ...