Introduction to SPI

SPI communication is known as Serial Peripheral Interface. SPI is a form of Serial Communication that uses three pins to transfer data. Serial communication provides a means to communicate with external hardware devices. In SPI communication the connected devices act as master and slave in order to establish a connection and carry out the transfer of data. 

USICR – USI Control Register

The bits USIWM1 AND USIWM0 are used to set the USI module to operate in the various protocols as follows

USIWM1USIWM0Description
00Outputs, clock hold, and start detector disabled
01Three-wire mode. Uses DO, DI and USCK pins.
10Two-wire mode. Uses SDA (DI) and SCL (USCK) pins.
11Two-wire mode. Uses SDA and SCL pins.

In order to operate the USI model in SP mode, the USIWM1 and USIWM0 bits are set to ‘0’ and ‘1’ respectively. 

The remaining bits namely, USICS0, USICS1 and USICLK are used to select the clock that will be used for SPI communication. These bits can be configured to various clock sources as shown below:

USICS1USICS0USICLKClock Source4-bit Counter-Clock Source
000No ClockNo Clock
001Software clock strobeSoftware Clock Strobe
01XTimer/Counter0 Compare MatchTimer/Counter0 Compare Match
100External, positive edgeExternal, both edges
110External, negative edgeExternal, both edges
101External, positive edgeSoftware clock strobe
111External, negative edgeSoftware clock strobe

Here, these bits will be configured to use a Software generate clock strobe. Hence, when the USICLK bit will be set to ‘1’, a single clock transition will be generated internally to power SPI communication. This sends or receives a single bit of data. This has to be written high (‘1’) 16 times to send or receive a single byte of data. 

USIDR – USI Data Register

This register actually holds the data that has to be transferred or is to be received from other externally connected devices. This is done by writing an 8-bit data to this register and then the data is transmitted by activating the clock pulses so as to perfectly synchronize the transfer of data.

USIBR – USI Buffer Register

This acts very similar to Data Register. When a single byte of data is transferred completely, the data stored in the USIDR register is then further copied to the USIBR register. This gives a time gap to the user to easily read the data given the transfer time is very sensitive.

USISR – USI Status Register

This register is used to obtain the status of the USI peripheral. The bits USICNT0, USICNT1, USICNT2 and USICNT3 are associated with counter bits that keep the count of the data that is transferred. After every rising and falling edge of the clock pulse, these bits count is incremented by one.

Circuit Diagram – ATtiny85 as Master and Slave

Here, the first ATtiny85 module acts as a Master and the second ATtiny85 module acts as a slave. The master device is responsible for generating the clock pulse that is to be synchronized with SPI protocol communication.

Configuring ATtiny85 as SPI Master and Slave

  1. Data direction register is used to set the pins PO (PB0), DI (PB1) and USCK (PB2) as output, input and input pins respectively for both the ATtiny85 to work as master and slave respectively.
  2. The bits USIWM1 and USIWM0 in USICR Register are configured to elect the Three-wire mode i.e. SPI Protocol in both the ATtiny85 modules.
  3. The data byte that is to be transferred is placed on the USIDR register.
  4. As Software strobe is used as a clock, the bits USICS1, USICS0 and USICLK are configured to 0, 0 and 1 respectively to work the ATtiny85 as master. 
  5. The clock source to serve as a slave, USITC bit is written as high to toggle USICLK pin.
  6. Repeat the above two steps until the USIOIF flag is raised to indicate one complete byte of data transferred.
  7. The next byte that is to be transferred is written further on USIDR.
  8. And 4th and 5th steps are repeated in a similar fashion to transfer this byte.
  9. The clock source is chosen as External positive edge and external at both edges for the 4-bit counter for the ATtiny85 module to serve as a slave.
  10. When the USIOIF flag goes high, it indicates that one byte of data has been received completely on the slave module.
  11. This data is then copied to the USIBR register for further processing.
  12. These two steps are repeated on the slave module to receive the next byte of data in a similar fashion.

Code for configuring ATtiny as SPI Master device

Below is the code for ATTiny as the SPI Master module and Slave module. The steps mentioned above in the configuration are translated in the form of code as shown in the comments

#include<avr/io.h>
string to_send="Test";

void spi_setup()
{
	DDRB=(1<<PB1)|(1<<PB2);		//Setting PB1 and PB2 as output (Step 1)
    	USICR=(1<<USIWM0);		//Choosing SPI i.e. three wire mode (Step 2)
}

int main()
{
  	short int counter=0;
  	spi_setup();
  	for(counter=0;counter<=3; counter++)
  	{
   		USIDR=to_send[i];		//Writing data bytes in Data register (Step 3)
   		while(USIOIF==0)		//Checking USI data overflow flag to detect
the end of transmission every byte (Step 5)
   	{
   		 USICR|=(1<<USICLK)|(1<<USITC); 	//generating clock for slave device
  	 }
   	USISR|=(1<<USIOIF);             	//Clearing counter overflow flag
  	}
}

Code for configuring ATtiny as SPI Slave device

#include<avr/io.h>
string received;

void spi_setup()
{
  	DDRB=(1<<PB1);     			//Setting direction of PB1 (Step 1)
  	USICR=(1<<USIWM0);          	//Choosing SPI aka three wire mode (Step 2)
}

int main()
{
 	 int counter;
  	spi_setup();
  	while(1)
  	{
   		if(USIOIF==1)         		//Checking USI data counter overflow flag to 
detect the end of transmission every byte (Step 10)
   		{
    			received[i]=USIBR;  	//Reading received byte from USIBR buffer 
register (Step 11)
    			counter++;   
    			USISR|=(1<<USIOIF);  //Clearing counter overflow flag (Step 12)
   		}             
  	}
}

Also read – 8051 Microcontroller
8086 Microcontroller

Spread knowledge

Leave a Comment

Your email address will not be published. Required fields are marked *