SPI does not work. Please help.

Please help me!
I have already tried everything. Dragon tiers and virgin blood will be the next to try.

I have EEPROM connected Arduino Leonardo MISO, MOSI and CLK and SS pin is defined.
For some reason I cannot get any kind of communication through and it seems that there is not even CLK signal coming from the CLK pin when I checked it with oscilloscope.
So what I’m missing here?
Here is the current code i’m trying with and it is already a mess but as I said, I have tried everyhting.

#include <SPI.h>
//#define DATAOUT 14//MOSI
//#define DATAIN 16//MISO
//#define SPICLOCK 15//sck
#define SLAVESELECT A4//ss // Varmistettu A4 on CE
#define WP 4 //Memory block write protect. High as disabled.
#define HOLD A5

//opcodes
#define WREN 0x06
#define WRDI 0x04
#define RDSR 0x05
#define WRSR 0x01
#define READ 0x03
#define WRITE 0x02
#define JEDECID 0x9F
#define READID 0x90

int receivedSPIVal=0;

void setup()
{
Serial.begin(9600);

// pinMode(DATAOUT, OUTPUT);
// pinMode(DATAIN, INPUT);
// pinMode(SPICLOCK,OUTPUT);
pinMode(SLAVESELECT,OUTPUT);
// pinMode(WP,OUTPUT);
// digitalWrite(WP,HIGH); //disable block protection

SPI.begin();
SPI.setBitOrder(MSBFIRST);
//wait for eeprom to finish writing
delay(3000);
Serial.print(“hi \n”);
delay(1000);
}

void loop()
{
digitalWrite(SLAVESELECT,LOW);
delay(20);
receivedSPIVal = SPI.transfer(JEDECID); // command
Serial.print(receivedSPIVal,HEX);
SPI.transfer(0x00);
SPI.transfer(0x01);
delay(20);
receivedSPIVal = SPI.transfer(0xFF); // response
Serial.print(receivedSPIVal,HEX);
Serial.print("\n");
digitalWrite(SLAVESELECT,HIGH);

/* digitalWrite(SLAVESELECT,LOW);
delay(1000);
SPI.transfer(0x90);
delay(20);
receivedSPIVal = SPI.transfer(0x00);
// Serial.print(receivedSPIVal,DEC);
receivedSPIVal = 1;
// delay(20);
receivedSPIVal = SPI.transfer(0x00);
// Serial.print(receivedSPIVal,DEC);
receivedSPIVal = 1;
// delay(20);
receivedSPIVal = SPI.transfer(0x00);
// Serial.print(receivedSPIVal,DEC);

if(receivedSPIVal == 0)
{
delay(20);
receivedSPIVal = SPI.transfer(0xFF);
Serial.print(receivedSPIVal,DEC);
}

receivedSPIVal = 1;
Serial.print("\n");
digitalWrite(SLAVESELECT,HIGH); //release chip*/

delay(1000); //pause for readability
}

Thanks,
Arto

artokang:
Please help me!
I have already tried everything. Dragon tiers and virgin blood will be the next to try.

I have EEPROM connected Arduino Leonardo MISO, MOSI and CLK and SS pin is defined.
For some reason I cannot get any kind of communication through and it seems that there is not even CLK signal coming from the CLK pin when I checked it with oscilloscope.
So what I’m missing here?
Here is the current code i’m trying with and it is already a mess but as I said, I have tried everyhting.

#include <SPI.h>

//#define DATAOUT 14//MOSI
//#define DATAIN  16//MISO
//#define SPICLOCK 15//sck
#define SLAVESELECT A4//ss // Varmistettu A4 on CE
#define WP 4 //Memory block write protect. High as disabled.
#define HOLD A5

//opcodes
#define WREN  0x06
#define WRDI  0x04
#define RDSR  0x05
#define WRSR  0x01
#define READ  0x03
#define WRITE 0x02
#define JEDECID 0x9F
#define READID 0x90

int receivedSPIVal=0;

void setup()
{
  Serial.begin(9600);

//   pinMode(DATAOUT, OUTPUT);
//   pinMode(DATAIN, INPUT);
//   pinMode(SPICLOCK,OUTPUT);
  pinMode(SLAVESELECT,OUTPUT);
//  pinMode(WP,OUTPUT);
//  digitalWrite(WP,HIGH); //disable block protection

SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  //wait for eeprom to finish writing
  delay(3000);
  Serial.print(“hi \n”);
  delay(1000);
}

void loop()
{
  digitalWrite(SLAVESELECT,LOW);
  delay(20);
  receivedSPIVal = SPI.transfer(JEDECID); // command
  Serial.print(receivedSPIVal,HEX);
  SPI.transfer(0x00);
  SPI.transfer(0x01);
  delay(20);
  receivedSPIVal = SPI.transfer(0xFF); // response
  Serial.print(receivedSPIVal,HEX);
  Serial.print("\n");
  digitalWrite(SLAVESELECT,HIGH);
 
/*  digitalWrite(SLAVESELECT,LOW);
  delay(1000);
  SPI.transfer(0x90);
  delay(20);
  receivedSPIVal = SPI.transfer(0x00);
//   Serial.print(receivedSPIVal,DEC);
  receivedSPIVal = 1;
 // delay(20);
  receivedSPIVal = SPI.transfer(0x00);
//   Serial.print(receivedSPIVal,DEC);
  receivedSPIVal = 1;
 // delay(20);
  receivedSPIVal = SPI.transfer(0x00);
//   Serial.print(receivedSPIVal,DEC);
   
    if(receivedSPIVal == 0)
     {
       delay(20);
     receivedSPIVal = SPI.transfer(0xFF);
     Serial.print(receivedSPIVal,DEC);
     }
 
  receivedSPIVal = 1;
  Serial.print("\n");
  digitalWrite(SLAVESELECT,HIGH); //release chip*/
 
  delay(1000); //pause for readability
}



Thanks,
Arto

Arto,
I need more info before I can give you a useful answer:

  • Which Arduino are you using?
    The Uno has the SPI bus on pins 10…13 and the 6 pin ISP connector.
    The Mega has the SPI bus on pins 50…53 and the 6 pin ISP connector.
  • What is the part number of your EEPROM?
    I need the part number to lookup it’s Datasheet, SPI devices use one of four different incompatible modes. I need to read the manual to identify which mode to select.
  • How is the EEPROM connected to the Arduino?
    Please draw a simple schematic, show the Arduino Pins, and the EEPROM’s pins. post an image of your schematic.

Chuck.

Hi Chuck,

  1. I'm using Arduino Micro
  2. EEPROM is Microchip SST25PF020B and I have verified that the mode is the same set for the Arduino.
  3. https://onedrive.live.com/?id=CC67D364F4F67DBB%21155&cid=CC67D364F4F67DBB

Arduino EEPROM A4 CE aka SS MISO SO DA4 WP Ground VSS 3V3 VDD A5 HOLD SCLK SCK MOSI SI

Hi friend! SPI pins must be set as OUTPUT.

Set it directly like pinMode(13, OUTPUT), use simple sketch (just transfer data in loop) and see oscilloscope.

Not true. Calling SPI.begin() takes care of setting MISO, MOSI and SCK as needed. Only SS must be declared as an output for the device to be SPI MASTER. You will only see SCK toggling during an SPI.transfer, it is not a free-running clock. See 'scope shots here http://www.gammon.com.au/spi

Thank you for the answers. I think I found the root cause of the problem which was loose ground pin on my circuit board which caused that i could not see even a clock with oscilloscope.

CrossRoads: Calling SPI.begin() takes care of setting MISO, MOSI and SCK as needed. Only SS must be declared as an output for the device to be SPI MASTER. http://www.gammon.com.au/spi

That does not seem to be the case on the MEGA 2560 that I've been using. Even when using SPI.begin the SCK and MOSI pins just do nothing until I set them to OUTPUTs myself.

pinMode(SS, OUTPUT); //Avoid being in SPI Slave mode which apparently can happen if this pin is an Input. pinMode(SCK, OUTPUT); // SPI.begin doesn't seem to do this (though it's supposed to) pinMode(MOSI, OUTPUT); // SPI.begin doesn't seem to do this (though it's supposed to)

Maybe this behavior has changed since this original post was written long ago... but I wanted to mention it here so anyone encountering the same problem will at least consider doing this themselves and not counting on SPI.begin

Here is where the Arduino SPI library begin method sets SS, SCK and MOSI to outputs:

void SPIClass::begin()
{
  uint8_t sreg = SREG;
  noInterrupts(); // Protect from a scheduler and prevent transactionBegin
  if (!initialized) {
    // Set SS to high so a connected chip will be "deselected" by default
    uint8_t port = digitalPinToPort(SS);
    uint8_t bit = digitalPinToBitMask(SS);
    volatile uint8_t *reg = portModeRegister(port);

    // if the SS pin is not already configured as an output
    // then set it high (to enable the internal pull-up resistor)
    if(!(*reg & bit)){
      digitalWrite(SS, HIGH);
    }

    // When the SS pin is set as OUTPUT, it can be used as
    // a general purpose output port (it doesn't influence
    // SPI operations).
    pinMode(SS, OUTPUT);

    // Warning: if the SS pin ever becomes a LOW INPUT then SPI
    // automatically switches to Slave, so the data direction of
    // the SS pin MUST be kept as OUTPUT.
    SPCR |= _BV(MSTR);
    SPCR |= _BV(SPE);

    // Set direction register for SCK and MOSI pin.
    // MISO pin automatically overrides to INPUT.
    // By doing this AFTER enabling SPI, we avoid accidentally
    // clocking in a single bit since the lines go directly
    // from "input" to SPI control.
    // http://code.google.com/p/arduino/issues/detail?id=888
    pinMode(SCK, OUTPUT);
    pinMode(MOSI, OUTPUT);
  }

Thanks jr…

For anyone still reading this my problem was calling SPI.begin; (without the parens) and apparently the SPI.begin code was never actually run.

It should be SPI.begin(); which does work on MEGA2560 and I no longer need to set OUTPUT mode on SCK and MOSI myself.

The code has a flaw.

This line:

define SLAVESELECT A4//ss // Varmistettu A4 on CE

causes SLAVESELECT to be defined as A4//ss // Varmistettu A4 on CE

So this line:

pinMode(SLAVESELECT,OUTPUT);

generates;

pinMode(A4//ss // Varmistettu A4 on CE,OUTPUT);

Which should give a compiler error.

Don't include a comment in a #define.

With avr-gcc comments certainly are allowed in #define statements.

Here is what the official documentation for the C++ preprocessor states:

  1. All comments are replaced with single spaces. There are two kinds of comments. Block comments begin with ‘/’ and continue until the next ‘/’. Block comments do not nest: /* this is /* one comment / text outside comment Line comments begin with ‘//’ and continue to the end of the current line. Line comments do not nest either, but it does not matter, because they would end in the same place anyway. // this is // one comment text outside comment It is safe to put line comments inside block comments, or vice versa. / block comment // contains line comment yet more comment / outside comment // line comment / contains block comment / But beware of commenting out one end of a block comment with a line comment. // l.c. / block comment begins oops! this isn’t a comment anymore / Comments are not recognized within string literals. "/ blah /" is the string constant ‘/ blah */’, not an empty string. Line comments are not in the 1989 edition of the C standard, but they are recognized by GCC as an extension. In C++ and in the 1999 edition of the C standard, they are an official part of the language.