View previous topic :: View next topic |
Author |
Message |
Ttelmah Guest
|
|
Posted: Sat Nov 04, 2006 11:00 am |
|
|
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
|
|
Posted: Sat Nov 04, 2006 11:43 am |
|
|
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: 1909
|
|
Posted: Sat Nov 04, 2006 12:01 pm |
|
|
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
|
|
Posted: Sat Nov 04, 2006 12:08 pm |
|
|
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
|
|
Posted: Sat Nov 04, 2006 12:08 pm |
|
|
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
|
|
Posted: Sat Nov 04, 2006 12:18 pm |
|
|
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
|
|
Posted: Sat Nov 04, 2006 12:27 pm |
|
|
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
|
|
Posted: Sat Nov 04, 2006 12:42 pm |
|
|
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.
Best Wishes |
|
|
Ttelmah Guest
|
|
Posted: Sat Nov 04, 2006 12:46 pm |
|
|
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.
Best Wishes |
|
|
jecottrell
Joined: 16 Jan 2005 Posts: 559 Location: Tucson, AZ
|
|
Posted: Sat Nov 04, 2006 12:50 pm |
|
|
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 |
|
|
|