# SPI between ATmega32 and ATmega328 is not working

I have been trying to accomplish connecting ATmega32 and ATmega328 using SPI

Hardware connections:

ATmega328     ATmega32
master        slave
------------------
MISO    ->   MISO
MOSI    ->   MOSI
SCK    ->   SCK
SS    ->   SS


I have added some code to blink LEDs after each step to recognize if a particular step is completed.

When connected, the LED connected to master blinks once while LED connected to the slave doesn't blink at all.

What have I done wrong?

Thanks for any advice.

Code for atmega328 master

#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>

//Initialize SPI Master Device
void spi_init_master (void)
{
DDRB = (1<<PORTB5)|(1<<PORTB3)|(1<<PORTB2);   // Set MOSI, SCK , SS as Output
SPCR = (1<<SPE)|(1<<MSTR);                    // Enable SPI, Set as Master
}

//Function to send and receive data
unsigned char spi_tranceiver (unsigned char data)
{
PORTB &= ~(1<<PINB2); //sending low signal to activate slave
SPDR = data;                         // Load data into the buffer

while(!((SPSR)&(1<<SPIF)));          // wait till transmission complete

PORTC |= (1<<PINC4);
_delay_ms(1000);
PORTC &= ~(1<<PINC4);
_delay_ms(1000);

return(SPDR);                        // Return received data
}

//Main
int main(void)
{
DDRC |= (1<<PINC4);
spi_init_master();
unsigned char t = spi_tranceiver(6);
for(unsigned char i=1;i<=t;i++){
PORTC = (1<<PINC4);
_delay_ms(500);
PORTC &= ~(1<<PINC4);
_delay_ms(500);
}
}


Code for ATmega32 slave

#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>

void spi_init_slave (void);
unsigned char spi_tranceiver (unsigned char data);

unsigned char lo;

int main(void)
{
DDRD |= (1<<PD7);
spi_init_slave();
while (1)
{
lo = spi_tranceiver(3);
for(unsigned char i=1;i<=lo;i++) {
PORTD |= (1<<PD7);
_delay_ms(100);
PORTD &= ~(1<<PD7);
_delay_ms(100);
}
}
}

// Initialize SPI Slave Device
void spi_init_slave (void)
{
DDRB &= ~(1<<PINB5);   // Set MOSI as input
DDRB |=  (1<<PINB6);   // Set MISO as output
DDRB &= ~(1<<PINB4);   // SS as input
SPCR  =  (1<<SPE);     // Enable SPI
}

unsigned char spi_tranceiver (unsigned char data)
{
// Load data into the buffer
SPDR = data;
//Wait until transmission complete
while(!(SPSR & (1<<SPIF) ));
PORTD |= (1<<PD7);
_delay_ms(100);
PORTD &= ~(1<<PD7);
_delay_ms(100);
// Return received data
return(SPDR);
}


## 2 Answers

After posting my problem on AVR Freaks, I was able to solve the problem. I hadn't set SCK on slave as input and SPI clock rate was not set properly. I set clock rate to f/64 where f refers to the CPU frequency of the master. I would like to mention couple of things here for being noted by future visitors.

• If your SPI is not working, first check what is the SPI clock rate. If it's too fast or slow, it won't work.
• Check if you have declared the pins of the SPI module correctly on the master and slave. MISO should be set to input and the rest to output on the master. On the slave, MISO should be set as output and the rest as input.
• If both these don't work for you, then focus on more advanced things like CPOL, CPHA. Using a logic analyzer to debug will help in this case.

SS must be LOW for the SPI Slave hardware to be active. I don't see you setting this I/O in your master code at all.

• I edited the code as you said.but it still doesn't work.Am I dealing with ss correctly now? or is there any error?If its incorrect, please be kind to show me how to do that correctly. – පවිඳු Oct 28 '18 at 12:35