Electronic – Why does ATtiny85 example code bit-shift zeros

avrcmicrocontroller

The ATtiny85 datasheet provides the following example C, on page 18.

1  void EEPROM_write(unsigned char ucAddress, unsigned char ucData)
2  {
3     /* Wait for completion of previous write */
4     while(EECR & (1<<EEPE))
5       ;
6     /* Set Programming mode */
7     EECR = (0<<EEPM1)|(0<<EEPM0);
8     /* Set up address and data registers */
9     EEAR = ucAddress;
10    EEDR = ucData;
11    /* Write logical one to EEMPE */
12    EECR |= (1<<EEMPE);
13    /* Start eeprom write by setting EEPE */
14    EECR |= (1<<EEPE);
15  }

(I added line numbers to the code above.)

In line 7, why does the example code not just read:

EECR = 0;

Why bother with all of the bitwise operations for something that ultimately resolves to zero?

Best Answer

In C there's two sane ways to set a given bit to value 1. Either

REGISTER |= BITMASK;

or

REGISTER |= (1<<BITNUMBER);

(The former is the most commonly used style, the latter is less common but favoured by Atmel. Either is fine.)

So if we need to set various bits in a register to 1, we can write code such as

REGISTER = (1<<THIS) | (1<<THAT);

This is good coding practice, as it is perfectly clear what the code does (unlike bad code using "magic numbers").

The only problem with this is that why some bits in the same register are set to zero isn't shown explicitly. Therefore one can write self-documenting code, as was done in this case, to show that you are intentionally writing zero to some register bits.

If we took this one step further still, the code could have been written like this:

EECR = (0<<EEPM1)|(0<<EEPM0) |   // Erase and Write in one operation
       (0<<EERIE) |              // EEPROM Ready interrupt disabled
       (0<<EEMPE) |              // EEPROM Master program disabled
       (0<<EEPE)  |              // EEPROM Program disabled
       (0<<EERE);                // EEPROM Read disabled

Now it is perfectly clear not only what the magic bit masks mean, but what the code does, what the register does and also that the programmer has actually considered every relevant bit in the register.

Compare this with something very badly written like EECR = 0x26;. It doesn't tell us jack - in order to understand it, we will have to sit with our nose in the manual. We also have no idea if the programmer knows what they are doing or if they are writing zero to some bits by accident.