7
\$\begingroup\$

I have written a code for 8051 microcontroller, where I used bit type, something like this:

static bit done_flag = 0;    /* bit variable */

bit testfunc (               /* bit function */
  bit flag1,                 /* bit arguments */
  bit flag2)
{
.
.
.
return (0);                  /* bit return value */
}

Now I am porting this to ATmega16 AVR controller. I found that there is no support for
bit type in AVR.

AVR-lib C User Manual says:

� Data types: char is 8 bits, int is 16 bits, long is 32 bits, long long is 64 bits, float and double are 32 bits (this is the only supported floating point format), pointers are 16 bits (function pointers are word addresses, to allow addressing up to 128K program memory space). There is a -mint8 option (see Options for the C compiler avr-gcc) to make int 8 bits, but that is not supported by avr-libc and violates C standards (int must be at least 16 bits). It may be removed in a future release.

So what should I do now?

\$\endgroup\$
4
  • \$\begingroup\$ You can use a bool datatype but I think that gets stored as a byte still though, not 100% sure about that. \$\endgroup\$
    – PeterJ
    Aug 29, 2013 at 10:31
  • \$\begingroup\$ @PeterJ Isn't Boolean bit-packing compiler dependent? \$\endgroup\$ Aug 29, 2013 at 10:51
  • \$\begingroup\$ @AnindoGhosh Yes it is, question is tagged avr-gcc and I don't think that packs them, older version didn't but I'm not sure about the latest versions. \$\endgroup\$
    – PeterJ
    Aug 29, 2013 at 10:55
  • \$\begingroup\$ @PeterJ It wasn't a critique, just curiosity :-) \$\endgroup\$ Aug 29, 2013 at 11:08

4 Answers 4

4
\$\begingroup\$

You can use a struct like this:

typedef struct {
    uint8_t bit0:1;
    uint8_t bit1:1;
    uint8_t bit2:1;
    uint8_t bit3:1;
    uint8_t bit4:1;
    uint8_t bit5:1;
    uint8_t bit6:1;
    uint8_t bit7:1;
} BitField;

typedef union {
    BitField asBits;
    uint8_t asByte;
} BitByte;

BitByte mBitField; 

And to access one bit at once you only have to

mBitField.asBits.bit3 = 1
\$\endgroup\$
5
  • 3
    \$\begingroup\$ Use this with care. One compiler I know produces very inefficient code for bitfield manipulation (many left & right shifts where simple masking & testing would have done). \$\endgroup\$
    – MikeJ-UK
    Aug 29, 2013 at 10:55
  • \$\begingroup\$ Which compiler? Just to know. \$\endgroup\$
    – Naeriel
    Aug 29, 2013 at 11:27
  • \$\begingroup\$ The Keil C51 compiler - although if time-critical code is written in assembler it's not an issue anyway. \$\endgroup\$
    – MikeJ-UK
    Aug 29, 2013 at 13:25
  • 2
    \$\begingroup\$ @Naeriel: Compilers are generally going to have bad performance with bitfields except in cases where the hardware can help and the compiler knows about it. Compiler vendors generally focus their efforts on optimizing patterns which are likely to be used by programmers seeking good performance. People seeking good performance on the 8x51 will use the bit or bdata spaces; since bitfields can't work as well, the compiler writers may not have thought optimizing them was a priority. \$\endgroup\$
    – supercat
    Aug 29, 2013 at 15:35
  • 2
    \$\begingroup\$ Last time I checked avr-gcc wasn't good at optimizing bit fields either. Advice: If you have enough RAM for multiple bools instead of a bit field, use bools. If you want to "pack" those bits instead and want best performance, consider using "handmade" ones, e.g. via #defines: #define MY_BIT_VALUE_1 _BV(0) #define MY_OTHER_BIT_VALUE _BV(1) ... stored inside a single uint8_t variable. \$\endgroup\$
    – JimmyB
    Aug 29, 2013 at 16:31
3
\$\begingroup\$

As PeterJ already mentioned in his comment, I would suggest using bool.

You need to include the stdbool library.

#include <stdbool.h>

As already pointed out, in AVRGCC, bool is 8-bit and only an abstraction of an uint8_t. If you can't live with that and need to save every single bit or have tons of global "yes/no" flags (which could indicate bad coding practice), you can consider what Naeriel posted in his answer.

However, using bool and proper variable naming (using the "is"-prefix) produces much cleaner code. For example use

bool IsOperationCompleted;

instead of "done_flag". That way is more obvious to someone who doesn't know the code what exactly the state signals.

\$\endgroup\$
0
\$\begingroup\$

Use unsigned char instead. This will use whole byte instead of a bit though.

\$\endgroup\$
2
  • \$\begingroup\$ so instead of static bit done_flag = 0;, if I do static unsigned char done_flag = 0; there should not be any problem (assuming I have sufficient memory)? \$\endgroup\$
    – gpuguy
    Aug 29, 2013 at 10:39
  • \$\begingroup\$ yes. please note that for conditional comparison 0 is false and anything that is not zero is true. so if(done_flag){do_mores_tuff();} is totally valid \$\endgroup\$
    – miceuz
    Aug 29, 2013 at 12:47
0
\$\begingroup\$

You can use something like this:

#define bit_get(p,m) ((p)&(m)) #define bit_set(p,m) ((p)|=(m)) #define bit_clear(p,m) ((p)&=~(m)) #define BIT(x) (0x01<<(x))

Usage example:

bit_set(DDRB,BIT(4))

sets PB4 as an output pin.

Source: http://www.avrfreaks.net/

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.