SPIF does not get set

Hi,

i'm currently trying to set up a SPI via an Arduino Uno (for a prototype that will use an Atmel MCU). For starters, i just want so send out one byte and clear the Flag (activating an LED to indicate). But the programm never gets past waiting for the flag. Any idea what the problem might be?

Here is the code:

#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <avr/io.h>

#define SET_REG_BIT(a,b)    a = a | (1<<b)
#define DEL_REG_BIT(a,b)    a = a & ~(1<<b)
#define FLIP_REG_BIT(a,b)   a = a ^ (1<<b)
#define CHECK_REG_BIT(a,b)  a = ((a & (1<<b))>>b)

void setup()
{
 //LED_PORT PB5 -> Output
 SET_REG_BIT(DDRB, DDB0);
 //SS PB2 -> Output
 SET_REG_BIT(DDRB, DDB2);
 //SS PB2 LOW
 SET_REG_BIT(PORTB, PORTB2);
 //MOSI PB3 -> Output
 SET_REG_BIT(DDRB, DDB3);
 //SCK PB5 -> Output
 SET_REG_BIT(DDRB, DDB5);
 //SPI Enable
 SET_REG_BIT(SPCR, SPE);
 //SPI Interrupt Disable
 DEL_REG_BIT(SPCR, SPIE);
 //SPI Master Mode
 SET_REG_BIT(SPCR, MSTR);
 //Write to SPI Data Register, start transmission
 SPDR = 0x01;
 //Wait for SPI Flag
 while ((SPSR & (1<<SPIF)) == 0);
 //Activate LED
 SET_REG_BIT(PORTB, PORTB0);
}


void loop()
{
}

Please edit your post and insert code tags.

Does it work if you use the library functions?

Looks like you did not properly initialize the SPI module (set the clock rate, etc.). Consult the data sheet.

1. Build the following SPI circuit (Fig-1).

SPIUNONanoZ.png
Figure-1:

2. Upload the following sketch into SPI-Master-UNO.

#include <SPI.h>

void setup (void)
{
  Serial.begin(115200);
  SPI.begin ();
  digitalWrite(SS, LOW);    //Slave is selected
  SPI.setClockDivider(SPI_CLOCK_DIV32);  //500 Kbits/sec
  pinMode(4, OUTPUT);
  digitalWrite(4, LOW);
}

void loop()
{
  SPDR = 0x32;
  while(bitRead(SPSR, SPIF) != HIGH)
  {
    ;   //wait and check the SPIF bit for HIGH state
  }
  digitalWrite(4, HIGH);
  byte x = SPDR;
  Serial.print(x, HEX);  //shows: 0x97
  while(1);
}

3. Upload the flowing sketch into SPI-Slave-NANO.

#include <SPI.h>

void setup ()
{
  Serial.begin(115200);
  pinMode(SS, INPUT_PULLUP);  // ensure SS stays high for now
  pinMode(MISO, OUTPUT);
  SPCR |= _BV(SPE);
  SPCR |= !(_BV(MSTR)); //Arduino is Slave
  SPDR = 0x67;  //test value
}

void loop()
{
  
}

4. Press the Reset button of Slave.

5. Bring in the Serial Monitor of Master at 115200 Bd.

6. Check that LED1 is ON and 67 has appeared on the Serial Monitor of Master (Fig-2).

smbz.png
Figure-2:

7. This is the end of of SPIF check.

smbz.png

SPIUNONanoZ.png

Thank you, this does work. But i still don't understand why it won't work with my code. Besides enabling SPI, setting MOSI, SCK and SS as Outputs and driving SS low, writing into die data register should be enough to get the flag set, even without connecting a slave...

But i still don't understand why it won't work with my code.

Explained in #2. You really need to read the data sheet, look at the power up default values for the registers that must be set correctly, then set them correctly.

Got it solved. The initialization was correct, but MSTR bit must be set before SPI Enable, otherwise SS seems to put it in Slave mode. A bit misleading since the datasheet says:

"If SS is configured as an output, the pin is a general output pin which does not affect the SPI system."

Anyway, thanks for youe answers!

In your original code, which contrary to forum rules, you edited four days later, you failed to set the MSTR bit.

Nice try at covering your basic error, but I'm glad that with our help, you finally read the data sheet and figured it out.

ph13:
[...]writing into die data register should be enough to get the flag set, even without connecting a slave...

1. Without having a connection with a SPI slave, you can not expect that the SPIF flag of the Master would be set.

2. The following diagram (Fig-1) says that the arrival of 8-bit from Slave into the SPDR Register of Master will activate the SPIF flag of Master.

spi328x.png
Figure-1:

spi328x.png