First SPI Bus

I am new to arduino and microcontrollers in general. Have only recently been introduced to these little gadgets and they seem to multiply on their own!

Working through the learning curve… have been successful getting two to talk with the wire library, and have now attempted the spi library… I have tried everything - my limited knowledge allows for:

Have spend much time reading through the great tutorial on Mr. Gammon’s site and have tried to follow that approach.

Please know that I do not yet understand the details of some of this stuff… but I will, in time… I hope :wink:

As you’ll see, there is no obvious purpose to these initial sketches… simply a blink version over the spi bus… If someone would please review the code below and offer any suggestions to where I am missing the boat… your comments are much appreciated.

The Master:

#include <SPI.h>

#define SCK 13                      // SPI clock
#define MISO 12                     // SPI master in, slave out
#define MOSI 11                     // SPI master out, slave in
#define PFD 10                      // slave select PFD
#define LED 9                       // debugging, local blinker
#define chkf 500                    // check items quickly 500 ms
#define chkm 1000                   // check itemes mediam, 1 sec
#define chks 2000                   // check slowly, every 2 sec
#define chkr 5000                   // check really slow, every 5 seconds
boolean state = false;
unsigned long ticker, last;    
void setup() 
{
  pinMode (SCK, OUTPUT);
  pinMode (MOSI, OUTPUT);
  pinMode (MISO, INPUT);
  pinMode (PFD, OUTPUT);
  pinMode (LED, OUTPUT);
  digitalWrite (SCK, LOW);
  digitalWrite (MOSI, LOW);
  digitalWrite (PFD, HIGH);
  digitalWrite (LED, LOW);

  SPI.begin();
  Serial.begin(9600);
}  // end of setup

void blink_pfd (boolean cstate)
{
// toggle on and off after x millis() 

  if (cstate == true) {
    int x=1;
    digitalWrite(PFD, LOW);
    SPI.transfer (x);
    digitalWrite(PFD, HIGH);
    digitalWrite (LED, HIGH);
  }
  else
  {
    int x=0;
    digitalWrite(PFD, LOW);
    SPI.transfer (x);
    digitalWrite(PFD, HIGH);
    digitalWrite (LED, LOW);
  }
}  

unsigned long getTime (unsigned long timech)
{
unsigned long time1 = millis();
unsigned long time2 = time1 - timech;
return(time2);
}
void loop() 
{
    ticker = getTime(last);
    if (ticker >= chks)
    {
      Serial.print("Check: ");
      Serial.print(ticker);
      Serial.print(" Millis: ");
      Serial.println(millis());
      last = millis();
      blink_pfd(state);
      if (state == true)
        state = false;
      else
        state = true;
    }  
}  // end of loop

and the slave:

#include <SPI.h> // necessary library
#define SCK 13                      // SPI clock
#define MISO 12                     // SPI master in, slave out
#define MOSI 11                     // SPI master out, slave in
#define SS 10                       // slave select ME / PFD
#define LED 9
int del=400; // used for various delays
int data_in; // read servo data
boolean initial = false;
char buf [50];
boolean awake = false;
volatile byte pos;
volatile boolean process_it;

void setup()
{
  pinMode(MOSI, INPUT);  
  pinMode(MISO, OUTPUT);
  pinMode(SCK, INPUT);
  pinMode(SS, INPUT);
  digitalWrite (SCK, LOW);
  digitalWrite (MOSI, LOW);
  digitalWrite (LED, LOW);
  digitalWrite(SS, HIGH);
  
  Serial.begin(9600); // debuggin
  Serial.println("Enable SPI in slave mode");
  SPCR |= _BV(SPE); // Enable SPI in slave mode
  pos = 0; // buffer is empty
  process_it = false;
  SPCR |= _BV(SPIE);
  delay(500);
  Serial.println("Initialisation complete");
}

void wakeup ()
{
awake = true;
for (int i=0; i<3; i++)
  {
  digitalWrite (LED, HIGH);
  delay(del);
  digitalWrite (LED, LOW);
  delay(del);
  }
}

void send_it (int x)
{
    if (x == 1)
    {
    digitalWrite(LED, HIGH);
    }
    else
    {
    digitalWrite(LED, LOW);      
    } 

}    // end receiveEvent

// SPI Interrupt routine
ISR (SPI_STC_vect)
{
byte c = SPDR;  // grab byte from SPI Data Register
  // add to buffer if there is space
  if (pos < sizeof buf)
    {
    buf [pos++] = c;
    // a new line means we are done
    if (c == '\n')
      process_it = true;
    }  // end of room available
} // end interupt routine SPI_STC_vect  


void loop(void) // waiting for interrupt
{
  if (awake == false)
  {
    wakeup();  
  }
  if (process_it == true)
    {
       buf [pos] = 0;
       Serial.println (buf); // debugging 
       data_in = (int)buf;
       pos = 0;
       send_it(data_in);
       process_it = false;
     } // end of if process_it
}

Thanks again for any and all comments and assistance…

Tony

Changed the slave setup section, to allow the SPI pins to float as inputs... still doesn't work, but that is corrected.. I think...

void setup()
{
  pinMode(MOSI, INPUT);  
  pinMode(MISO, INPUT);
  pinMode(SCK, INPUT);
  pinMode(SS, INPUT);
  digitalWrite (LED, LOW);

  
  Serial.begin(9600); // debuggin
  Serial.println("Enable SPI in slave mode");
  SPCR |= _BV(SPE); // Enable SPI in slave mode
  pos = 0; // buffer is empty
  process_it = false;
  SPCR |= _BV(SPIE);
  delay(500);
  Serial.println("Initialisation complete");
}

Don't you need this somewhere?

SPI.begin(); // nothing in () because we are the master

Not sure you need defines & pinModes & digitalwrites for the SCK/MOSI/MISO pins, I believe the SPI library will handle all that for you.

SPI.begin(); // nothing in () because we are the master

Of course, you have to start with the part I am fuzzy on... ;)

As I understand it ( and I know I dont )...

I do have a SPI.begin() in the setup of the master... I do not have that statement in the slave.

Rather I have:

SPCR |= _BV(SPE); (which enables SPI ) SPCR |= _BV(SPIE); (which enables interupts)

this was following the example from Mr. Gammon's site and http://www.arduino.cc/en/Tutorial/SPIEEPROM

I do have a SPI.begin() in the setup of the master... I do not have that statement in the slave.

Rather I have:

SPCR |= _BV(SPE); (which enables SPI ) SPCR |= _BV(SPIE); (which enables interupts)

this was following the example from Mr. Gammon's site and http://www.arduino.cc/en/Tutorial/SPIEEPROM

That is correct. A arduino 'SPI slave" does not use (or need) the SPI library, rather just direct control of the SPI hardware to select slave mode and enable it's interrupt.

Lefty

I believe your problem is that you're running the master at the max rate (both speed bits defaulted to 0).

The slave cannot run that fast, it's throttled to 50% of the master's max. So... you have to slow down the master's clock.

There are 3 speed control bits, 2 in the control register and a half speed bit in the other register.

To see if that is the problem, add:

SPCR |= _BV(SPR0); (low bit of speed select) SPCR |= _BV(SPR1); (high bit of speed select)

to the master. That should slow it down to the minimum speed of 1/128 clock.

Thanks… have added that to the master… still no joy… current master setup section

void setup() 
{
  pinMode (SCK, OUTPUT);
  pinMode (MOSI, OUTPUT);
  pinMode (MISO, INPUT);
  pinMode (PFD, OUTPUT);
  pinMode (LED, OUTPUT);
  digitalWrite (SCK, LOW);
  digitalWrite (MOSI, LOW);
  digitalWrite (PFD, HIGH);
  digitalWrite (LED, LOW);
  
  SPCR |= _BV(SPR0);       // (low bit of speed select)
  SPCR |= _BV(SPR1);       // (high bit of speed select)
                                    // slow it down to the minimum speed of 1/128 clock


  SPI.begin();
  Serial.begin(9600);
}  // end of setup

And I removed the #include <SPI.h> from the slave code…

Not sure there is a lot I can screw up with the actural hardware side… pin 10 M to pin 10 slave…etc etc through 13…

I have a shared power and ground line for th two boards…

pics, just in case you see something…

and

the green light is the master attempting to send every 2 sec…

going to try a couple of different boards, see if there is a hardware issue…

Thanks again for the assistance… much apprecaited… feeling rather incompetant about this…