Writting to Registers

Writing data to the registers is fairly simple. The x of the register name is replaced with the port letter and then an 8-bit value is written. For example to write to PORTx you would use:

PORTB = 0b01010101

The issue with writing data to a register in this way is that all bits of the register must be updated at once. This would mean potentially altering each bit and each pins state unintentionally. To get around this problem we can use the bit operations we learned earlier.

Bitmasks

To alter a single bit of the register we must first create something called a ‘bitmask’. A bit mask is an 8 bit value that contains a 1 in the place of the bit we wish to alter while all other bits are 0. Why we do this will become apparent in the next step. The bitmask to alter bit 3 of the register looks like so: (Remember we start counting bits at 0)

0b00001000

Once we have constructed this bitmask we can then use our ‘OR’ bit operation to change bit 3 to a 1 while leaving the remainder of the register unaltered. Lets take a look at that:

   0b01010101
OR 0b00001000
-------------
 = 0b01011101

To implement this on the microcontroller in C we use:

PORTB = PORTB | (0b00001000);

Now lets turn bit 4 from a 1 to a 0. The method we just used only works for turning a bit into a 1 and cannot be used to turn the bit into a 0. To do that we need to apply our ‘AND’ bit operator and the ‘NOT’ bit operator. First we begin by again constructing our bitmask for bit 4:

0b00010000

Next we invert the bitmask using our ‘NOT’ operation and then we can then use our ‘AND’ operation to set only bit 5 to zero.

(1)                   (2)    0b01011101
   ! 0b00010000          AND 0b11101111
   ------------          --------------
   = 0b11101111            = 0b01001101

To implement this on the microcontroller in C we use:

PORTB = PORTB & !(0b00010000)

Simplyfying Bitmask Creation

Now that we have a way of altering individual bits of a register we can look for an easier way to create the bit mask. C includes a bit operator called left shit, ‘<<‘. This shifts a bit a specified number of places. Lets have a look at another way to create that bitmask using the left shift operator.

1<<4 = 0b00001000

Here we are saying “take a value of 1, and left shift it 4 places”. This effectivley creates a bitmask where we only have to define the bit we wish to edit! Rewriting our previous C code with this new bitmaks creation method we get:

PORTB = PORTB | (1<<3);
PORTB = PORTB & !(1<<4);

We can further simplify the code by using more compact notation included in the C language:

PORTB |= (1<<3);
PORTB &= ~(1<<4);

The Offset Bit Problem

A common problem encountered in the creation of bitmasks is that on some AVRs the bits are offset from whatever they control (perhaps a pin). Because of this editing bit 4 may actually affect pin 6. This makes the bitmask creation much harder as each time you would need to find the correct bit number to be manipulated and then account for the offset. Luckily Atmel Studio includes predefined words for each AVR that represent the correct bit number for each pin. For example pin 4 on port B would be PORTB4. These words are substituted for the correct number by the compiler. Lets look at inserting that to our C code:

PORTB |= (1<<PORTB3);
PORTB &= ~(1<<PORTB4);