0

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);
  }
}
gre_gor
  • 6,669
  • 9
  • 47
  • 52

1 Answers1

0

You know the four wire SPI is full duplex, right? The master and the slave are sending the data simultaneously.

The common way how to do what you want is sending control byte and then dummy byte (or bytes) to receive the data.

KIIV
  • 3,534
  • 2
  • 18
  • 23
  • Thanks for your answering , i know i have to sending a dummy byte to receive data but i tried to fix code many times . i'm still stuck :( . Could you test and pass or recommend me any code? :( – Anh Quân Tống Jul 07 '18 at 08:23