Port manipulation / How to clear old bits?


I calculate a bit pattern which my program code needs to set to the PORTD register.

The Bitmask where values should go to looks like this: 0b10111100

So lets assume PORTD contains old data on any of the bits I want to write my pattern to.
I cant just do an OR because the old bits will stay.

I found this code in the Forum but dont understand if it really does what I need and how:

PORTB = (PORTB & mask) | value ;

Lets say I got:

Port: 0101
Mask: 1110
Value: 1000

Goal: 1001
Assumed Result: 1100

But when I do PORTB = (PORTB & mask) | value ; it should be 1100 right ?
(If I understand correctly it does an AND between Port and Mask, then does an or with the result. Correct?)

So this shouldn't clear old 1's in any of the places I need to write I assume.

Therefore how to write a binary pattern to a Port directly and clear the old Bits (without touching some Bits - Zeros in my example Bitmask)?

Oh, too much time in front of the PC....

I assume I need to invert my Mask to make it work correct?

If I understand you correctly, the 1 bits in the mask are those positions you want to write to.
So, in your example, you want to set the first three bits to a new value, irregardless of their old value.
You want to leave the last bit at whatever value it currently has.

Lets work through your example step by step.

(PORTB & Mask) will Keep any of the first three bits of PORTB which are set and will clear the last bit.
That doesn't seem to be what you want, so we don't Need to go any further.

Port: 0101
Mask: 1110
Value: 1000

Goal: 1001

If you take your value and AND it with your mask, you will get 1000.

If you invert your mask (with the "~" Operator) you can AND the result with the current value of PORTB and Keep the last bit.

~Mask | PORTB

You can then OR those two values.

PORTB = (Value & Mask) // 1000 AND 1110 = 1000
((~Mask) & PORTB) // NOT 1110 = 0001, 0001 AND 0101 = 0001

Put all of that on one line and you get

PORTB = (Value & Mask) | ((~Mask) & PORTB);

Yes you understood me correctly.

So if I invert my mask the term

PORTB = (PORTB & mask) | value ;

should work right?


PORTB = (PORTB & ~mask) | value ;