SPI of AVR

In the previous article of spi introduction, you have got the idea about the basics of SPI communication. Let’s implement  SPI communication in Atmega 16 of AVR.

Registers of SPI

Till now, you must have got an idea of how things in the embedded world work. There should be a control register which is used to control the modes of the communications, then there should be a data register and of course, there is a status register used to monitor the communication. And it turns out, our guess is right, there are these registers here as well. Let’s see them one by one.

SPCR- SPI Control register

Above image of SPCR telling us all about it. There is bit-7(SPIE) used to enable interrupt, and then there is bit-6(SPE) used to enable SPI. Bit-5(DORD) is used to configure the data order that you can configure according to your need. Bit 4(MSTR) is used to select the device to the master or slave. It is in slave mode when the logic is zero. Bit 3(CPOL) and 2(Clock Phase) used to configure the clock polarity and clock phase. Bit 1 and 0 controls the “clock rate-SCK”.

SPI Status register- SPSR

Above image is the register of SPSR Register. The  7th bit of this register is the flag set when the interrupt is generated. This Flag is already cleared by the hardware while executing the ISR. 6th bit is the WCOL flag and is set when the data transferred successfully. All the else bits are reserved except the last one which is used to double the speed of communication.

SPI Data Register- SDR

SPI of Atmega 16

This register collects or transmits the data. All the data needed to be transmitted or received have to be done through this register.

The Project

In this project, I am going to transfer the data between two microcontrollers using SPI. One device is the master while another one is the slave. By this time, I am assuming that you guys have already know about LCD display interfacing, so you can see your data there or you can send your data over the UART.

The Code

Below is the code of master. This code can send the data to the slave device connected. Here, it is not receiving data from the slave but you can easily do that by reading SPDR.

#include <avr/io.h>
#include<util/delay.h>
#include <string.h>

# define MOSI 3
# define SCK 5
# define SS 2
# define F_CPU 8000000UL
void write(char *data)
{
	for(int i=0; i<20; i++)
	{
	SPDR = data[i];
	while((SPSR&(1<<SPIF))==0);	//waiting for the transfer to complete
	_delay_ms(20);
	}
	
}
void main(void)
{
	
    DDRB=(1<<5)|(1<<7)|(1<<4);						// Declaring MOSI, SCK and SS as output pins
	while(1)
	{
		SPCR=(1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<CPOL);// Declaring this as a master
		write("Hello");								// sending data to the connected device
		_delay_ms(1000);							/
	}
}

Here, is the code of the slave microcontroller connected. This code is only able to read data from the SPI. You can easily write data by writing to SPDR.

#include <avr/io.h>
#include<util/delay.h>
#include <string.h>

char read_spi()
{
	while((SPSR&(1<<SPIF))==0);	//waiting for the transfer to complete
	return SPDR;
	
}
void main(void)
{
	DDRB=(1<<6);		// Declaring MISO as output
	char data;
	while(1)
	{
		SPCR=(1<<SPE);  //enabling the spi 
		data=read_spi();// sending data to the connected device
		_delay_ms(1000);	
	}
}

If you want to enable the interrupt, you can easily activate that too. There is a bit in SPCR that you can “set”, then you can write an ISR for SPI. I am writing the code snippet for doing this here.

ISR(SPI_STC_vect)
{
	// write code to execute when the transfer is done.
}
SPCR=(1<<SPIE);// activating interrupt in spi

That’s it for this article, I hope you guys get to learn about SPI in AVR. If you face any problem, ask us in the comment section, check out other articles as well. See you next time.

 

Share This