Is it possible for a 328P (or any AVR 8-bit) to change 1 bit in a register?

Couldn’t get it all in the Subject line.

My question has to do with setting control registers within the 328p.

My current understanding is the only way to do this is to:

  1. read the register
  2. Change the bit you need to
  3. write the result to the register.

This effectively writes to every bit location in the register. Even though you would be writing the same value that was there it would be rewritten with the same value.

Even the bitSet macro does this: #define bitSet(value, bit) ((value) |= (1UL << (bit)))

Am I correct in this interpretation?

Second:

Does anybody know of any registers that react to the write operation, even if writing the same value as was previously there?

Thanks

John

Specifically I’m looking at the Timer1 register

That is correct

Read-Write-Modify

The Atmegas big brother Xmega has bit level writes

e.g.

Atmega328P (notice the OR operator)
DDRB |= (1<<PORTB1)

Xmega
PORTB_DIRSET = 1<<PORTB1 —> This only affects PORTB1

Special cases applies to flag registers where you write 1 to clear it

e.g.

TIFR1 = 1<<TOV1 → this would only affect the TOV1 bit

Thank you so much....

You said the magic words that made it "click" for me.

"Special cases applies to flag registers"

It clears a lot of confusion I had.

It is a read-modify-write cycle... with one very important exception: The so-called "low I/O space"

This consists of the registers at 0x0000 through 0x001F - On those registers the cbi and sbi instructions (clear bit index and set bit index) can be used. This directly sets or clears the specified bits within that register. On the classic AVR devices (AVR/AVRe/AVRrc) sbi/cpi execute in 2 clock cycles, while it executes in a single clock for the XMega, tinyAVR 0/1/2-series, megaAVR 0-series, and the latest and greatest, the new AVR Dx-series (that is, AVRxm (xmega) and AVRxt (I often refer to the latter as "modern AVR")). Either way, it is not a read-modify-write cycle (there are also two more branch instructions for bit-level tests on these - sbis and sbic (skip if bit in I/O register set or cleared), which skip the following instruction IFF the relevant bit is set or cleared.

avr-gcc is smart enough to use sbi/cbi when possible - but be aware that in order for this to happen the register you're writing to and the bit you are setting or clearing must be compiletime known, and you must be certain that you're only setting or clearing a single bit at a time.

So which registers are in the low I/O space? Except on parts with oodles of pins, such that you can't fit the relevant registers into those 32 magic addresses, PINx, PORTx and DDRx are in the low IO space. The "GPIO" registers (3 or 4 registers of 8-bits eachj that have no special function - they're just for you to use those special instructions with). On AVRxm/AVRxt parts - that's it. On classic AVRs, other registers may be located in the I/O space; see the datasheet (register summary section) to find out for sure on a specific part and register

Hope this was useful :-)

Another important feature where writing the same value to register “does something”: writing 1 to PINx toggles the corresponding pin.

There are resisters that trigger some action when read and/or written.