■ FIGURE 4. SPI shift.
void spi0_hard_init_master(void)
{
PORTB |= (1<< MISO_HARDWARE_PIN) \
| (1<< MOSI_HARDWARE_PIN) \
| (1<< SCLK_HARDWARE_PIN) \
| (1<< SS_HARDWARE_PIN);
//Set MOSI, SCK AND SS to outputs
DDRB |= (1<< MOSI_HARDWARE_DDR) \
| (1<< SCLK_HARDWARE_DDR) \
| (1<< SS_HARDWARE_DDR);
// Set Miso to input
DDRB &= ~(1<<MISO_HARDWARE_DDR);
// SPE - SPI Enable
// MSTR – Master\Slave Select
// SPRO - Fosc/16
SPCR = ( 1 << SPE ) | ( 1 << MSTR ) | ( 1
<< SPR0 );
}
SPCR — SPI Control Register
There are also too many choices for the SPCR register.
You’ll have to carefully read the datasheet if you want
your SPI to be different from this one. In our case, we
chose to set the bits as follows:
• SPE – SPI Enable: A write to 1 enables the SPI.
We just leave the other SPI control bits at their default
0 state which selects for the desired options.
Using Our SPI Library
64 December 2010
Using the SPI couldn’t be simpler (or rather, I couldn’t
make it simpler). First, you select the device you are writing
to by setting its slave select (/SS) pin low, then load the data
you want to send into the SPDR (SPI Data Register), then wait
for the SPIF flag in the SPSR to be set. Then, finally load the
data received from the SPDR register. (Note that the data goes
out of and into the same register — as shown in Figure 4.)
This is shown in the spi_hard_master_rw8 function below:
// Simultaneously sends a byte to the slave
// and receives a byte from the slave
uint8_t spi0_hard_master_rw8(uint8_t to_slave)
{
uint8_t from_slave;
// select slave
spi_hard_set_ss();
// Put byte in SPI data register
SPDR = to_slave;
// Poll SPIF-flag until transfer complete
while(!(SPSR & (1<<SPIF)));
// Get the SPI data reg.
from_slave = SPDR;
// deselect slave
spi_hard_clear_ss();
//return it
return from_slave;
}
Rather than go into a lot more detail about the SPI
source code, I invite the reader to look at the two
applications in this month’s Workshop29.zip: one for
Chaser Lights and one for testing the DataFlash.
Atmel DataFlash
Figure 5 is a block diagram of our DataFlash. The
Atmel DataFlash family has from 1 to 128 Mbit (500 Kbyte
to 16 Mbyte) SPI serial memory ICs that come in small
packages and require only four pins for access. They use
on-board SRAM, small page sizes, and flexible opcodes to
facilitate data access. Atmel claims this is the ‘world’s
number one selling serial interface Flash family’ and that
they make the ‘world’s fastest serial Flash’ (go to
www.Atmel.com for more exciting marketing hyperbole).
With 100K guaranteed write cycles, it is unlikely that
we are going to wear out the Butterfly DataFlash, but please
note that for serious — as in commercial — use of the
Atmel DataFlash you should carefully read the datasheets
and get the Atmel DataFlash Sofware Suite (you have to ask
them for it from Atmel) to increase a device’s life span.
Also, to keep from killing it immediately it is important to
remember that on the AVR Butterfly the DataFlash is
restricted to 2. 7 to 3. 6 volts, but the ATmega169 is rated
up to 5. 5 volts. So some folks use a five-volt supply and
then fry their DataFlash. This kind of error is called: ‘You
din’a RTFM!’
The AT45DB041B has 26 opcode commands that
control its actions. These commands provide a variety of
functions but as usual we will only look at a useful subset of
the myriad of possibilities. We will learn how to read the
device status, read and write data to the 264-byte SRAM
buffers, tell it to write a buffer to a Flash page, and tell it