most efficient method to set and clear specific bits in register

Hi!
I try to find an efficient and cler method to set specific bits 0 or 1. I want to use registry and port names.
For example, i want in PORTB to set bit 1 to 0 and bit 2 to 1. At moment work with this:

PORTB = (PORTB | B00000100) ^ B00000010;

I know hot to set bit or clear bit,

PORTB |= (1<<PORTB2); //set bit 2
PORTB &= ~(1<<PORTB1); //clear bit 1

but how to get the same result as in first command using a single line.

Thanks!

But the first command is using a single line...

I don't think you can make it more efficient, but this sounds kinda like an XY problem. Why do you want it more efficient?

My mistake. Yes first is in one line. I want to say, more readable, using port bit names. I want to be easily to heck and debug.
I think that i found an solution:
For example, next sequence set PORTB2 (D10) to 1 and clear PORTB1 (D9)

PORTB = (PORTB | (1<<PORTB2)) & ~(1<<PORTB1);

Thanks for reply!

Here is an easy to debug method of setting and clearing bits in 1 line. It should be just as efficient as the other method for setting and clearing bits.

#define BITSET(bit) _BV(bit)
#define BITCLEAR(bit) 0
#define setPort(port, bitsToSet, value) port = (port & ~bitsToSet) | (value & bitsToSet);


//Trying to change PORTB, which is currently B00001101 to B00001110, here is how:
//As you can see above, we want to set bit1 and clear bit0, so we get...
//Side Note: _BV(bit) means bit value, all it is is (1 << bit)

setPort(PORTB, _BV(0) | _BV(1), BITSET(0) | BITCLEAR(1));

Here is how it works:

B00001101 port
B00000011 bitsToSet = _BV(0) | _BV(1)
B00000010 value = BITSET(0) | BITCLEAR(1)

B00001101 port
B11111100 & ~bitsToSet
B00001100 (port & ~bitsToSet) This clears the bits we are about to set

B00010010 value, bit 4 is set as an example of what would happen if you had a bit that shouldn't be there
B00000011 & bitsToSet
B00000010 (value & bitsToSet) This clears any bits that we are not changing in 'value', as you can see bit 4 is no longer set

B00001100 (port & ~bitsToSet)
B00000010 | (value & bitsToSet)
B00001110 result, as expected

vlad2005:
My mistake. Yes first is in one line. I want to say, more readable, using port bit names. I want to be easily to heck and debug.
I think that i found an solution:
For example, next sequence set PORTB2 (D10) to 1 and clear PORTB1 (D9)

PORTB = (PORTB | (1<<PORTB2)) & ~(1<<PORTB1);

Thanks for reply!

The first command is one line but still multiple instructions and assembly level. It’s not going to be executed magically with one assembly code magic operation.

So I’d recommend to stick to your 2 liner

PORTB |= (1<<PORTB2); //set bit 2
PORTB &= ~(1<<PORTB1); //clear bit 1

and the best way to get that in one line is thisPORTB |= (1<<PORTB2);  PORTB &= ~(1<<PORTB1); //set bit 2 and then clear bit 1 :slight_smile:

Really more readable that way in my opinion and most probably not less efficient

@J-M-L
I think you are right.

@Ps991
It is a good solution. I will try to see how it goes.