# 4.5: Setting, Clearing and Reading Register Bits

Bitwise operations may appear to be somewhat arcane to the uninitiated but are in fact commonly used. A prime use is in setting, clearing and testing specific bits in registers. One example involves configuring bidirectional ports for input or output mode via a data direction register, typically abbreviated DDR. Each bit of the DDR represents a specific output pin. A logic high might indicate output mode while a logic low would indicate input mode. Assuming DDR is an 8 bit register, if you wanted to set all bits except the 0th bit to input mode, you could write1:

DDR = 0x01; // set bit zero to output mode

If sometime later you wanted to also set the 1st and 2nd bits to output mode while keeping everything else intact, the easy way to do it is simply to OR the bits you want:

DDR = DDR | 0x06;

The prior operation may be performed using the more common shorthand:

DDR |= 0x06;

Note that the preceding code does not affect any of the other bits so they stay in whatever mode they were originally. By the way, a set of specific bits (such as the 0x06 above) is often referred to as a bit pattern or bitmask.

To see if a specific bit is set, simply AND instead of OR. So, to see if the 1st bit of DDR is set for output mode, you could use something like:

if ( DDR & 0x02 )       // true if set


Clearing bits requires ANDing with a bitmask that has been complemented. In other words, all 1s and 0s have been reversed in the bit pattern. If, for example, we want to clear the 0th and 4th bits, we’d first complement the bit pattern 0x11 yielding 0xee. Then we AND:

DDR &= 0xee;

Often, it’s easier to just use the logical complement operator on the original bit pattern and then AND it:

DDR &= (~0x11);

If you’re dealing with a single bit, you can use the left shift operator so you don’t even have to bother figuring out the bit pattern in hex. To set the 3rd bit and then clear the 4th bit of DDR, you could use the following:

DDR |= (0x01<<3); DDR &= ~(0x01<<4);

These operations are so common that they are often invoked using an in-line expansion via a #define.

1. In C, bit position counting, like most sequences, starts from position 0 not position 1.