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
USIWM1 | USIWM0 | Description |
0 | 0 | Outputs, clock hold, and start detector disabled |
0 | 1 | Three-wire mode. Uses DO, DI and USCK pins. |
1 | 0 | Two-wire mode. Uses SDA (DI) and SCL (USCK) pins. |
1 | 1 | Two-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:
USICS1 | USICS0 | USICLK | Clock Source | 4-bit Counter-Clock Source |
0 | 0 | 0 | No Clock | No Clock |
0 | 0 | 1 | Software clock strobe | Software Clock Strobe |
0 | 1 | X | Timer/Counter0 Compare Match | Timer/Counter0 Compare Match |
1 | 0 | 0 | External, positive edge | External, both edges |
1 | 1 | 0 | External, negative edge | External, both edges |
1 | 0 | 1 | External, positive edge | Software clock strobe |
1 | 1 | 1 | External, negative edge | Software 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
- 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.
- 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.
- The data byte that is to be transferred is placed on the USIDR register.
- 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.
- The clock source to serve as a slave, USITC bit is written as high to toggle USICLK pin.
- Repeat the above two steps until the USIOIF flag is raised to indicate one complete byte of data transferred.
- The next byte that is to be transferred is written further on USIDR.
- And 4th and 5th steps are repeated in a similar fashion to transfer this byte.
- 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.
- When the USIOIF flag goes high, it indicates that one byte of data has been received completely on the slave module.
- This data is then copied to the USIBR register for further processing.
- 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