NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » Dont understand the &= and |=

April 05, 2012
by Akeshish
Akeshish's Avatar

Hello everyone,

I understand the functions of AND and OR, i just done understand when you use one over the other in register setting.

It seems to me that you use &= to change from 1 to a 0

                        |= to change from 0 to a 1

is there more to it?

Is there a way in C to just directly change a register example in VHDL we would use something like

PORTC(4) = '1';

or place a logic 1 in register 4 of PORTC.

April 06, 2012
by pcbolt
pcbolt's Avatar

Akeshish -

There's just a little bit more to it. When you use the OR operator with 1, you not only change 0 to 1 but also 1 to 1. So if 'x' is unknown, x | 1 will always be 1. When you use the AND operator with 0, x & 0 will always equal 0. When you use multi-bit numbers, bit 1 of the first number will only interact with bit 1 of the second number. Same with all the other bits that make up the two numbers.

You can certainly make your own "PORTC(4) = 1" type function and use it in your projects. Or go further and create a whole library (like lcd.c/lcd.h) for you to include.

April 06, 2012
by Akeshish
Akeshish's Avatar

Thank you,

I do understand how it works, i was just a bit confused on the last project of the tutorial. In one case the tutorial says to use an OR operation to change the bit and the next time around it says to use an AND operation. It was a bit confusing because both operations where trying to change a single bit in a register. Did i read it wrong?

April 06, 2012
by Rick_S
Rick_S's Avatar

Typically AND is used to clear a bit and OR is used to set a bit. This is because with a simple mask the logic allows for this. Some people make up macros for C to make setting and clearing or register bits a little more similar to what you are used to. I don't do that myself so I'm not going to try to describe that process but if you search the forums here, you'll probably find it. One user that hasn't been around here in a while that had some excellent macro's for this was NOTER. You might try searching for him or looking at his posts in the library section if you are interested.


April 06, 2012
by Ralphxyz
Ralphxyz's Avatar

And then just to add to the confusion:

DDRB = 0xFF;        // Configure PortB as an Output port
DDRB = 0x00;       // Configure PortB as an Input port
DDRC = 0xF0;       // Configure first four pins on PortC as Input pins and the others as Output

As opposed to:

DDRC|=((1<<PC0)|(1<<PC1));        // PC0 and PC1 as output  
DDRB &= ~(1<<PB1);                      // Input


April 06, 2012
by Akeshish
Akeshish's Avatar

Thanks guys

April 06, 2012
by Akeshish
Akeshish's Avatar

Hey Ralph, I tried to google a ASCII code chart but cant seem to find 0xFO types of codes. Im kinda of new to that style of coding. Can you link me to a reference.

April 06, 2012
by pcbolt
pcbolt's Avatar

Akeshish -

Ralph is just using hexadecimal notation to change the port direction pins. The 0x part means "treat what follows as a hexadecimal number". It's much easier to write 0xFF than it is to write 11111111 in binary notation. 0xF0 is the same as 11110000. Keep in mind that when you write to a register you MUST write 8-bits at a time. Since each register controls 8 pins, you have to be careful when you write to that register NOT to disturb the other pins. That is what Rick was referring to as "masking". When you use this code;

DDRC |= (1 << PC3);

This actually expands to;

DDRC = DDRC | (1 << PC3);

Since PC3 is just a symbol for the number 3, we get;

DDRC = DDRC | (1 << 3);


DDRC = DDRC | (00000001 << 3);


DDRC = DDRC | 00001000;

Since you do not know what DDRC is, use x's to indicate its value (x can only be 1 or 0)

DDRC = xxxxxxxx | 00001000;

Now x | 1 = 1 and x | 0 = x, we get;

DDRC = xxxx1xxx;

And the pin is set!

To clear the pin use the following facts x & 1 = x and x & 0 = 0. If we work it backwards, we want;

DDRC = xxxx0xxx;
DDRC = xxxxxxxx & 11110111;   // 11110111 can also be written 0xF7
DDRC = DDRC & ~(00001000);    // ~ is negation operator
DDRC &= ~(00001000);
DDRC &= ~(00000001 << 3);
DDRC &= ~(1 << PC3);

Post a Reply

Please log in to post a reply.

Did you know that interrupts can be used to trigger pieces of code when events happen? Learn more...