CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Help With Struct/Union of Bits

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
jecottrell



Joined: 16 Jan 2005
Posts: 559
Location: Tucson, AZ

View user's profile Send private message

Help With Struct/Union of Bits
PostPosted: Sat Nov 04, 2006 3:38 am     Reply with quote

3.236


I'm trying to store status bits in a byte. Id like to have a structure so that I can declare a variety of variables in this fashion. I've done the following to declare a single variable in the way I'd like, but I'm unsure of how to convert this into a structure... or if a union is necessary.

Code:
int8 unit_status_byte        = 0b00000000;
#bit status_bat       = unit_status_byte.0   //unit has low battery
#bit status_dead_bat  = unit_status_byte.4   //unit has dead battery, will be shutting down
#bit status_tampered  = unit_status_byte.1   //unit has been tampered with
#bit status_bad_comms = unit_status_byte.2   //some failed packets or bad acks
#bit status_off_air   = unit_status_byte.3   //unit is not communicating


I had read: http://www.ccsinfo.com/forum/viewtopic.php?t=25068 but I don't understand if that's what I need.

Can I make the #bit declarations in the structure?

Thanks for any help,

John



EDIT:


I think I've got the solution. Is this the correct approach:

Code:
typedef struct t_status_byte {
   int1 status_bat       : 1;   //unit has low battery
   int1 status_dead_bat  : 1;   //unit has dead battery, will be shutting down
   int1 status_tampered  : 1;   //unit has been tampered with
   int1 status_bad_comms : 1;   //some failed packets or bad acks
   int1 status_off_air   : 1;   //unit is not communicating
   int1 unused1          : 1;
   int1 unused2          : 1;
   int1 unused3          : 1;
}


Will this guarantee that t_status_byte is actually a byte and those bits will occur in the came locations in each instance declared?

Thanks again.
Ttelmah
Guest







PostPosted: Sat Nov 04, 2006 8:24 am     Reply with quote

The syntax should be:
Code:

typedef struct t_status_byte {
   int8 status_bat       : 1;   //unit has low battery
   int8 status_dead_bat  : 1;   //unit has dead battery, will be shutting down
   int8 status_tampered  : 1;   //unit has been tampered with
   int8 status_bad_comms : 1;   //some failed packets or bad acks
   int8 status_off_air   : 1;   //unit is not communicating
   int8 unused1          : 1;
   int8 unused2          : 1;
   int8 unused3          : 1;
};

The ':' declaration, makes the variable a 'bit field', _in_ a larger storage location (int8). The 'int1' declaration, itself defines a single bit.

Best Wishes
jecottrell



Joined: 16 Jan 2005
Posts: 559
Location: Tucson, AZ

View user's profile Send private message

PostPosted: Sat Nov 04, 2006 10:14 am     Reply with quote

Thanks.

I'm going to be using this to send statuses back and forth by radio between units and need to have the bits in the same place in each system and each instance of the variable. I'll have the declarations in a common header file. Will the compiler always put the bits in the same place in the byte?

John

EDIT:

OK. I've had a chance to start playing with this. I'm trying this:

Code:
typedef struct {
   int8 status_bat       : 1;   //unit has low battery
   int8 status_dead_bat  : 1;   //unit has dead battery, will be shutting down
   int8 status_tampered  : 1;   //unit has been tampered with
   int8 status_bad_comms : 1;   //some failed packets or bad acks
   int8 status_off_air   : 1;   //unit is not communicating
   int8 unused1          : 1;
   int8 unused2          : 1;
   int8 unused3          : 1;
} t_status_byte;

t_status_byte   unit_status_byte        = 0b00000000;
t_status_byte   unit_prev_status_byte   = 0b00000000;


And it says the value that I'm trying to initialize the variable with has to evaluate to a constant. Will I be able to access both the individual bits and the byte as a whole with this scheme?

Thanks.

John

EDIT part deux:

I've just done some quick reading. It sounds like I don't want to use bitfields. How should I go about putting status bits in a byte for a TYPEDEF so I can declare a bunch of variables with the same structure?
Ttelmah
Guest







PostPosted: Sat Nov 04, 2006 11:00 am     Reply with quote

Code:

struct bfield {
   int8 status_bat       : 1;   //unit has low battery
   int8 status_dead_bat  : 1;   //unit has dead battery, will be shutting down
   int8 status_tampered  : 1;   //unit has been tampered with
   int8 status_bad_comms : 1;   //some failed packets or bad acks
   int8 status_off_air   : 1;   //unit is not communicating
};
union t_status_byte {
   struct bfield bits;
   int8 b;
};

union t_status_byte   unit_status_byte;
union t_status_byte   unit_prev_status_byte;


You will have to initialise the values yourself in the code:

unit_status_byte.b=0b00000000;
unit_prev_status_byte.b=0b00000000;

Which accesses the bytes.

The bits are then accessible with:
unit_status_byte.bits.status_bat etc..
You can obviously typedef the final union declaration if required.

Best Wishes
jecottrell



Joined: 16 Jan 2005
Posts: 559
Location: Tucson, AZ

View user's profile Send private message

PostPosted: Sat Nov 04, 2006 11:43 am     Reply with quote

Thanks a bunch. It took me a few minutes to figure out what was happening and do a little reading.

It worked great the way you had it in your post. But when I modified the code to use TYPEDEF it spit out an error: 'Expecting a ('. Anu idea what I'm doing wrong?

Code:
struct bfield {
   int8 bat       : 1;   //unit has low battery
   int8 dead_bat  : 1;   //unit has dead battery, will be shutting down
   int8 tampered  : 1;   //unit has been tampered with
   int8 bad_comms : 1;   //some failed packets or bad acks
   int8 off_air   : 1;   //unit is not communicating
};

typedef union u_status_byte {
   struct bfield bit;
   int8 byt;
};

u_status_byte   unit_status;
u_status_byte   unit_prev_status;


Again, thanks for all your time,

John
newguy



Joined: 24 Jun 2004
Posts: 1907

View user's profile Send private message

PostPosted: Sat Nov 04, 2006 12:01 pm     Reply with quote

This is something I use for human input. A joystick with 4 momentary switches (north, south, east, west) and 3 buttons (top, bottom, trigger) as well as one more switch (compressor off) are connected to port C on a PIC. All of port C's lines are pulled high - closing a switch grounds the line.

Code:
union {
   int8 portc;
   struct {
      int1 s; // c0
      int1 n; // c1
      int1 e; // c2
      int1 w; // c3
      int1 trigger; // c4
      int1 bottom; // c5
      int1 top; // c6
      int1 comp_off; // c7
   } bits;
} input;
#byte portc = 0xf82


A timer interrupt set to go off every 13 ms (roughly) triggers a read of the entire port. That looks like this:

Code:
input.portc = portc;


I then check to see if the value I just read has changed from the last time I read it. Then to test if a particular line is down (active):

Code:
if (!input.bits.trigger) {
   ...
}


etc etc etc
jecottrell



Joined: 16 Jan 2005
Posts: 559
Location: Tucson, AZ

View user's profile Send private message

PostPosted: Sat Nov 04, 2006 12:08 pm     Reply with quote

Newguy,

Thanks. I like that way also. But still, no one has come out and said in either solution whether, there is a guarantee that the bits will always be located in the same location in the byte in each declaration of the byte size variable. These bytes are going to be sent back and forth by radio, in a packet, and the receiving unit has to have each status bit in the same location.... Does that make sense? I'm not sure if I'm explaining it clearly enough?

Thanks.

John
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Nov 04, 2006 12:08 pm     Reply with quote

Quote:
union t_status_byte {
struct bfield bits;
int8 b;
};

union t_status_byte unit_status_byte;
union t_status_byte unit_prev_status_byte;

unit_status_byte.b=0b00000000;
unit_prev_status_byte.b=0b00000000;

You don't need a union. You can zero the whole structure with one
line of code.
Code:

// Create two structures.
t_status_byte unit_status_byte;     
t_status_byte unit_prev_status_byte;

//============================
void main()
{
// Zero both structures.
unit_status_byte = 0;
unit_prev_status_byte = 0;

while(1);
}


Here's the symbol table:
Code:

unit_status_byte        00000021
unit_prev_status_byte   00000022


Here's the .LST file:
Code:
0000            00326 .... unit_status_byte = 0;
0016 01A1       00327 CLRF   21
0000            00328 .... unit_prev_status_byte = 0;
0017 01A2       00329 CLRF   22
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Nov 04, 2006 12:18 pm     Reply with quote

Quote:
But still, no one has come out and said in either solution whether,
there is a guarantee that the bits will always be located in the same
location in the byte in each declaration of the byte size variable

Only CCS would know the answer for certain, because it depends upon
the internal compiler code. All that we could do, is to run a few tests
and then make an assessment based on that.

With regard to portability, I remembered that bitfields can't be
depended upon to be portable across machines. That's not really
your question, but it's still of interest. There are several comments
on this at the end of the bitfields section on this page:
http://icecube.wisc.edu/~dglo/c_class/odds_n_ends.html
jecottrell



Joined: 16 Jan 2005
Posts: 559
Location: Tucson, AZ

View user's profile Send private message

PostPosted: Sat Nov 04, 2006 12:27 pm     Reply with quote

EDIT:

Just caught your second reply. I'll experiment and report back. Any idea on the error during compilation described above?



PCM,

Thanks for the reply. I think I may have confused the issue by assigning 0b00000000 to the variable in the declaration. I'm not having a problem doing that.

I've got a variety of sensors that are communicating with a hub. A number of statuses will be tracked and I thought I'd save room in my comm packet if I just packed them into a single byte. I can use the standard bit set/test/clear functions but I thought I'd try something a little more 'elegant'.... (complex). So I need to be able to send the byte back and forth by radio (standardized bit location required) and I'd like to be able to easily get at each of those status bits.

John
Ttelmah
Guest







PostPosted: Sat Nov 04, 2006 12:42 pm     Reply with quote

You have to give the 'typedef' a name, as opposed to the 'union' a name.
When you define a union or structure, the layout is:
Code:

struct/union struct/union_name {
   declared stuff;
} variable/typedef_name;

So just move the name declaration from where I have it (to declare the union), to the end where you had it (for typedef).
Personally, I slightly prefer to 'know' that I am dealing with a structure or union, so name these, rather than hiding it behind a typedef, but this is purely a 'personal' thing. Smile

Best Wishes
Ttelmah
Guest







PostPosted: Sat Nov 04, 2006 12:46 pm     Reply with quote

Bitfields are meant to declare from LSB upwards, so, the bits will be in the order you expect. You can test this by just looking at the byte value, or the access code. For instance, the line:

unit_status_byte.bits.status_bat=1;

Codes as:

000A4: BSF 05.0

With the symbol table, showing:

005 unit_status_byte

So the behaviour is exactly as expected. Smile

Best Wishes
jecottrell



Joined: 16 Jan 2005
Posts: 559
Location: Tucson, AZ

View user's profile Send private message

PostPosted: Sat Nov 04, 2006 12:50 pm     Reply with quote

Ttelmah wrote:
Personally, I slightly prefer to 'know' that I am dealing with a structure or union, so name these, rather than hiding it behind a typedef, but this is purely a 'personal' thing.


Got both replies. Thanks!

Your approach makes sense and will be helpful in six months when I have to make revisions.

John
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group