Serial Peripheral interface-SPI of AVR microcontrollers

This is high speed synchronous data transfer between microcontrollers or other peripheral devices. AVR SPI interface:

  • uses three wires for synchronous data transfer;

  • can operate as Master or Slave;

  • allow LSB or MSB first bit transfer;

  • support multiple bit rates;

  • has end of transmission interrupt;

  • has write collision flag protection;

  • wakes up from idle mode;

  • supports double speed master SPI mode

As it was mentioned SPI requires three wires like in picture above SS of slave might be connected to ground what enables SPI of Slave device. But if you want to use sleep mode on slave, then use SS pin to activate SPI as pulling low this pin wakes Slave AVR (or other device) from sleep mode.

AVR SPI pin data direction is overridden according to table bellow.

 SPI interface is mainly tied to three registers: SPCR, SPSR and SPDR; SPCR register is a control register, which is main register to set up SPI interface:

 

Bit 7 SPIE- Enables SPI interrupt. If global interrupt is enabled, then when SPIF bit in SPSR register is set -an interrupt occures.

Bit 6 SPE – setting it enables SPI;

Bit 5 DORD - if bit is set first comes LSB, if cleared MSB;

Bit 4 MSTR – Master/Slave select. If SS input is low level while MSTR is set, MSTR will be cleared and SPIF flag in SPSR will be set (interrupt occures). After this user has to re-enable MSTR to continue in master mode;

Bit 3 CPOL – clock polarity (refer to datasheet);

Bits 1,0 SPR1, SPR0 – Clock rate selection (refer to table in datasheet);

Bellow is and AVR-GCC example of master transmit via SPI interface:

 

#include <avr\io.h>
#define DD_MOSI     PINB3
#define DD_SCK     PINB5
#define DDR_SPI    DDRB
void SPI_MasterInit(void)
{
// Set MOSI and SCK output, all others input
DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK);
// Enable SPI, Master, set clock rate fck/16
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
}
void SPI_MasterTransmit(char cData)
{
/* Start transmission */
SPDR = cData;
/* Wait for transmission complete */
while(!(SPSR & (1<<SPIF)));
}
int main(void) {
SPI_MasterInit();
SPI_MasterTransmit('A');
   while(1) { }
}

 

 

Comments

Am I missing something or this is a mistake:#define [b]DDR_SPI PORTB[/b]// Set MOSI and SCK output, all others input[b]DDR_SPI[/b] = (1hanging the directions?

Something went wrong with the text parsing. What I wanted to say is writing to [b]PORTB[/b] isn't going to change the pin [b]directions[/b], it's going to activate the pull-ups, isn't it?

#define DDR_SPI DDRB !!!

Thank you. Fixed.

It didn't work for my case