Reputation: 77
I have a bit field defined like that (it is from a microcontroller library, so it looks a bit different):
typedef union {
byte Byte;
struct {
byte PTAD0 :1;
byte PTAD1 :1;
byte PTAD2 :1;
byte PTAD3 :1;
byte PTAD4 :1;
byte PTAD5 :1;
byte :1;
byte :1;
} Bits;
} PTADSTR;
extern volatile PTADSTR _PTAD @0x00000000;
#define PTAD _PTAD.Byte
#define PTAD_PTAD0 _PTAD.Bits.PTAD0
#define PTAD_PTAD1 _PTAD.Bits.PTAD1
#define PTAD_PTAD2 _PTAD.Bits.PTAD2
#define PTAD_PTAD3 _PTAD.Bits.PTAD3
#define PTAD_PTAD4 _PTAD.Bits.PTAD4
#define PTAD_PTAD5 _PTAD.Bits.PTAD5
So. Let's say that i want a function that sets a bit, like that:
void setbit(bit Bit) {
Bit = 1;
}
Of course, the "bit" declaration doesn't work. I would like a declaration that I could use
setbit(PTAD_PTAD5)
and it would set this bit. I could do
void setbit(byte Byte, byte number) {
Byte |= 1<<(number);
}
and send
setbit(PTAD,5);
That works perfectly, but... that's not what I want, cause I want to do something like Arduino's libraries. Anyone has any idea how to do that in the way I prefered?
Upvotes: 3
Views: 3027
Reputation: 1252
How about this? Using the static const qualifier should make sure the memory overhead is about zero
typedef struct
{
uint8_t* reg;
uint8_t bitnum;
}bit;
void setbit(bit b)
{
*b.reg |= (1 << b.bitnum);
}
void clrbit(bit b)
{
*b.reg &= ~(1 << b.bitnum);
}
static const bit PTAD_PTAD0 = {&PTAD, 0};
static const bit PTAD_PTAD1 = {&PTAD, 1};
static const bit PTAD_PTAD2 = {&PTAD, 2};
static const bit PTAD_PTAD3 = {&PTAD, 3};
static const bit PTAD_PTAD4 = {&PTAD, 4};
static const bit PTAD_PTAD5 = {&PTAD, 5};
static const bit PTAD_PTAD6 = {&PTAD, 6};
static const bit PTAD_PTAD7 = {&PTAD, 7};
int main()
{
printf("PTAD: %02X\n", PTAD);
setbit(PTAD_PTAD0);
printf("PTAD: %02X\n", PTAD);
clrbit(PTAD_PTAD0);
printf("PTAD: %02X\n", PTAD);
}
Upvotes: 0
Reputation: 8053
Because you can access the bits in your bitfield individually setting a bit is very easy:
_PTAD_PTAD5 = 1;
which would, thanks to the #define _PTAD_PTAD5
, evaluate to
_PTAD.Bits.PTAD5 = 1;
Note that due to C being a pass-by-value language,
void setBit(bit Bit){
Bit = 1;
}
doen't do what you expect. Instead it sets the (function-)local variable Bit
to one, leaving the variable you send to it unchanged.
Normally you'd use a pointer to a variable you want to change in a function, but because you can't take the address of a bit in a bitfield you can't do that in this case.
Upvotes: 2
Reputation: 225082
C is a pass-by-value language, so even if you could do:
void setbit(bit Bit) {
Bit = 1;
}
it would be a no-op.
You can do what you're trying with a function-like-macro:
#define setbit(x) do { (x) = 1; } while(0)
If you call this macro with PTAD_PTAD5
, it should work like you expect.
Upvotes: 3
Reputation: 12515
In C, I do not believe it is possible to access a bitfield as an array. One idea would be to pass in a enumerated type or constant and switch off its value into 8 different set functions. Not the cleanest way, but I believe it would work.
#define PTAD5 5
...
void setbit(PTADSTR byte, int bit)
{
switch(bit)
{
...
case PTAD5 : byte.PTAD5 = 1; break;
default: ASSERT_ALWAYS(); break;
}
}
Upvotes: 0