I use SPI on ATmega328 with raw code, data is transferred correctly, but the value return just correct in the second time. I don't know why. I think the data buffer register doesn't update immediately, when I push the button (this is video left is yellow LED, right is red LED: https://drive.google.com/open?id=1bf2XlxRBGCaUo0j2ezB2XFxfSItUmChN and code below)
I use Arduino Uno is a master to send data and get response. Arduino Nano is a slave to receive data and response to master.
Arduino Uno (master) code:
#define DDR_SPI DDRB
#define PORT_SPI PORTB
#define MOSI 3
#define SCK 5
#define SS 2
#define red 2
#define cbi(port, bits) (port) &= ~(1 << (bits))
#define sbi(port, bits) (port) |= (1 << (bits))
volatile uint8_t Data1;
volatile uint8_t Data2;
void setup()
{
Serial.begin(9600); //debug by UART
SPCR = 0; // Reset SPCR = 0
DDR_SPI |= (1<<MOSI)|(1<<SCK)|(1<<SS);// MOSI,SCK,SS - OUTPUT , MISO - INPUT
SPCR |= (1<<SPE)|(1<<MSTR)|(1<<SPR0); // Enable spi , Set master , div/16
pinMode(red,OUTPUT); // led output at pin 2
pinMode(6,INPUT_PULLUP); // internal res input at pin6
pinMode(7,INPUT_PULLUP); // internal res input at pin7
sbi(PORT_SPI,SS); // disable slave
}
uint8_t SPI_MasterTransmit(uint8_t cData)
{
SPDR = cData; // Start transmission
delay(50);
while(bit_is_clear(SPSR,SPIF)); //Wait for transmission complete
return SPDR;
}
void loop()
{
if(bit_is_clear(PIND,6)) // if i push button at pin 6
{
while(bit_is_clear(PIND,6)); // if i still push button at pin 6
cbi(PORTB,SS); // enable slave
Data1 = SPI_MasterTransmit(1); // send value 1 to slave
Serial.print(Data1); // debug
delay(50);
if(Data1 == 2) //if slave response value = 2
digitalWrite(red,LOW); //turnOFF led at pin 2
sbi(PORT_SPI,SS); // disable slave
}
else if(bit_is_clear(PIND,7)) // if i push button at pin 7
{
while(bit_is_clear(PIND,7)); // if i still push button at pin 7
cbi(PORT_SPI,SS); // disable slave
Data2 = SPI_MasterTransmit(3); // send value 3 to slave
Serial.print(Data2); // debug
delay(50);
if(Data2==4) //if slave response value = 4
digitalWrite(red,HIGH); //turnON led at pin 2
sbi(PORT_SPI,SS); // disable slave
}
}
Arduino Nano (slave) code:
#define MISO 4
#define yellow 2
#define cbi(port, bits) (port) &= ~(1 << (bits))
#define sbi(port, bits) (port) |= (1 << (bits))
volatile uint8_t Data;
void setup()
{
SPCR = 0; // reset SPCR = 0
DDRB |= (1<<MISO); // MISO - OUTPUT , SCK,MOSI,SS - INPUT
SPCR |= (1<<SPE)|(1<<SPIE); // enable spi , spi_interrupt
pinMode(yellow ,OUTPUT); // Led output at pin2
}
void SPI_Response(uint8_t cData)
{
SPDR = cData; //Start transmission
while(bit_is_clear(SPSR,SPIF)); //Wait for transmission complete
}
void loop()
{
}
ISR(SPI_STC_vect) // Vector interrupt spi
{
Data = SPDR; // volatile Data = data receive
if(Data == 1)
{
digitalWrite(yellow ,HIGH); // i turnOn led if i receive data = 5
SPI_Response(2); // and response to master a value = 7
delay(10);
}
else if(Data == 3)
{
digitalWrite(yellow,LOW); // i turnOFF led if i receive data = 6
SPI_Response(4); //and response to master a value = 8
delay(10);
}
}