In AVR Tutorials I often see:

DDRA |= (1 << PA0);
PORTA |= (1 << PA0);

used instead of:

DDRA |= PA0;

What is the purpose of this?

  • 16
    \$\begingroup\$ I don't know much about AVR, but (1 << 2) is not the same as 2. \$\endgroup\$
    – Armandas
    Mar 18, 2016 at 12:14
  • \$\begingroup\$ Because they are programming in C. In assembler you'd use a bit setting instruction directly, in Ada you have several options, for one you can simply assign True or False to one member of a packed array of booleans : PortA(PAO) := True; \$\endgroup\$
    – user16324
    Mar 18, 2016 at 12:14
  • \$\begingroup\$ If PA0 specifies a bit number (such as 0 through 31), then (1 << PA0) represents a bit mask or bit field in which that bit is set. \$\endgroup\$
    – kkrambo
    Mar 18, 2016 at 13:53
  • \$\begingroup\$ It seems that you don't understand bitwise operators. Here is one I used: Bit Manipulation It starts from the basics and goes as far are required. \$\endgroup\$
    – Rojin
    Mar 18, 2016 at 15:20
  • 1
    \$\begingroup\$ As an aside, in AVR C you can typically also use the _BV() macro to get the "bit value" (e.g. PORTA |= _BV(PA0);. I personally think it makes the code more readable, but opinions differ quite a bit in the community. \$\endgroup\$
    – Mels
    Mar 18, 2016 at 15:27

4 Answers 4


PA0 will be defined as 0 so the following line:

DDRA |= (1 << PA0);

Equates to shifting 1 left by zero bits, leaving an OR with the value 1 to set the first bit. Whereas the following line:

 DDRA |= PA0;

Is doing an OR with zero so won't change the registers at all.

  • \$\begingroup\$ That makes me wonder why they wouldn't just use DDRA |= 1. Do they expect PA0 to change across different environments? \$\endgroup\$
    – corsiKa
    Mar 18, 2016 at 15:36
  • 9
    \$\begingroup\$ @corsiKa: which is easier to read and understand: DDRA |= 72; or DDRA |= (1<<PA6) | (1<<PA3);? \$\endgroup\$
    – David
    Mar 18, 2016 at 16:03
  • 1
    \$\begingroup\$ Ah, there are other bits in the pattern. Gotchya. Nope, I like it. \$\endgroup\$
    – corsiKa
    Mar 18, 2016 at 16:07
  • \$\begingroup\$ @corsiKa even when you set only 1 bit, does |= 128 make more sense than |= (1 << 7). How do you know that it'll set the 7th bit when looking at values like 128? \$\endgroup\$
    – phuclv
    Mar 19, 2016 at 11:12
  • \$\begingroup\$ @LưuVĩnhPhúc Of course not. But to someone who doesn't use that framework, it's not clear that they care about "setting a bit" at first glance, hence why I asked. Suffice it say, PA0 isn't very descriptive of what it's actually doing. \$\endgroup\$
    – corsiKa
    Mar 20, 2016 at 21:13

Why do they do this? Likely because everyone else they ask for help or learned from did it that way. And because the standard defines are weirdly done.

Shifting by a number, typically a decimal number, will move that value over by that many binary positions. 1 << PA0 will shift 1 by PA0 to the left. Since PA0 is 0, there is no shift. But given 1 << 6 1 will become 0b1000000. Given13 << 6, it will shift 13, in binary which is 0b1101, over by 6 to become 0b1101000000 or 832.

Now, we need to see what PA0 - PA7 are defined as. These are typically defined in the specific header for your specific microcontroller, included via io.h or portpins.h

#define     PA7   7
#define     PA6   6
#define     PA1   1
#define     PA0   0

They are defined as their numerical position, in decimal!

They cannot be directly assigned, as bits, because they are not single bits.

If you were to do PORTA |= PA7; assuming PORTA is 0b00000000 (all off), you will get:

PORTA = PORTA | PA7; or PORTA = 0 | 7; or PORTA = 0 | 0b111

See the problem? You just turned on PA0, PA1, PA2, instead of PA7.

But PORTA |= (1 << PA7); works as you expect.

PORTA = PORTA | (1 << PA7); or PORTA = 0 | (1 << 7); or PORTA = 0 | 0b10000000;

The Smarter way

The other, better microcontroller, the MSP430, has a standard define of bits as:

#define BIT0                (0x0001)
#define BIT1                (0x0002)
#define BIT6                (0x0040)
#define BIT7                (0x0080)

These are define as their binary position, in hex. BIT0 is 0b0001, not like PA0, which is 0. BIT7 is 0b10000000, not like PA7, which is 0b111.

So direct assignments like P1OUT |= BIT7; will work the same as P1OUT |= (1 << 7); would.

  • \$\begingroup\$ hey, great explanation!!! thanks! anything similar to change the bit and set to 0? thanks \$\endgroup\$
    – aleXela
    Nov 12, 2023 at 19:59
  • \$\begingroup\$ No need, found it. (PORTX >> PXX) & 1 \$\endgroup\$
    – aleXela
    Nov 13, 2023 at 19:04

Your question has already been answered, but I want to present an alternative that was a bit much for a comment. One of the first things I do when I start an embedded project is define my bit set and clear macros.

#define bitset(var,bitno) ((var) |= 1 << (bitno))
#define bitclr(var,bitno) ((var) &= ~(1 << (bitno)))

Using the macros, your code becomes:


The end result is a bit set instruction in assembly.

  • 3
    \$\begingroup\$ You made a typo, the second line should be e.g. "bitclear". \$\endgroup\$
    – jms
    Mar 18, 2016 at 13:37
  • \$\begingroup\$ Your 2nd #define, not your 2nd example. \$\endgroup\$
    – brhans
    Mar 18, 2016 at 13:53

Have a look here: http://nongnu.org/avr-libc/user-manual/FAQ.html#faq_use_bv

Those macros are used when setting particular bits in a register. For example: if PORTA is 8-bits wide, then PA0 is the lowest bit, PA7 is the highest. To set PA0 to 1 you have to write ("or-write") 0x01 to the register. If you want to set PA2, then you need a value that in binary will have a one in the right place, for PA2 that will be 0x04.

People don't want to remember which bit has a particular position (as other registers may have different bit names eg. CS12, CS10, ADSC etc.) so they use more abstract names. Instead of typing: PORTA = 0x04 you type PORTA = _BV(PA2) and you instantly know that it will turn pin PA2 high.


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