Pages: [1] 2   Go Down
Author Topic: Trouble with SPI interfaced SRAM chip  (Read 3342 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm trying to get my Uno communicating with an SRAM chip (Microchip 23LC512) via SPI.
As a simple verification, I write several bytes of data then go back and read them, and print it on the serial monitor. But, when I run my code I get this:

Memory status:   
20   1010101
21   1010101
22   1010101
23   1010100
400   10101010
401   1010101
402   1010101
403   1010101


Memory addresses are 16 bit, shown in hex; values are in binary. In this case I wrote B10101010 to each memory address.
I can't find any consistent pattern--sometimes several bytes in a row are correct, others none. Here it looks like it's wrapping values from the back to the front?
Any help is very much appreciated!

The code:
Code:
// Read and write to SRAM via SPI

#include <SPI.h>

//Pin definitions:
#define CS 8

//SRAM SPI commands
#define READ 0x03    //READ and WRITE to be followed by 16 bit address
#define WRITE 0x02
#define RDMR 0x05    //read mode register
#define WRMR 0x01    //write mode register
#define RSTIO 0xFF   //reset input mode
//Mode commands
#define BYTE 0x00
#define PAGE 0x80
#define SEQUENTIAL 0x40

void configureRAM(void);    //declare function

//Incoming and outgoing start addresses (16 bit)
unsigned int cw_addr=0x0020;
unsigned int ccw_addr=0x0400;

byte incoming=0xFF;      //incoming SPI data
byte cw_status[4];
byte ccw_status[4];

int i=0;

void setup()
{
  Serial.begin(9600);
  SPI.begin();
  configureRAM();
 
 
  //read CW memory status byte
  digitalWrite(CS,LOW);
  SPI.transfer(READ);
  SPI.transfer(highByte(cw_addr));
  SPI.transfer(lowByte(cw_addr));
  for(i=0;i<4;i++)
  {
    cw_status[i]=SPI.transfer(0x00);
  }
  digitalWrite(CS,HIGH);
 
  //read CCW memory status byte
  digitalWrite(CS,LOW);
  SPI.transfer(READ);
  SPI.transfer(highByte(ccw_addr));
  SPI.transfer(lowByte(ccw_addr));
  for(i=0;i<4;i++)
  {
    ccw_status[i]=SPI.transfer(0x00);
  }
  digitalWrite(CS,HIGH);
 
  //print results
  Serial.println("Memory status:\t");
 
  for(i=0;i<4;i++){
    Serial.print(cw_addr+i,HEX);
    Serial.write('\t');
    Serial.println(cw_status[i],BIN);
  }
  for(i=0;i<4;i++){
    Serial.print(ccw_addr+i,HEX);
    Serial.write('\t');
    Serial.println(ccw_status[i],BIN);
  }
}

void loop()
{
 
}


//Configure RAM settings and clear memory status bytes.
//Initialize SPI before calling configureRAM()
void configureRAM(void)
{
  SPI.setClockDivider(SPI_CLOCK_DIV2);    //SPI clock at 8MHz
  SPI.setDataMode(SPI_MODE0);            //CPOL=0, CPHA=0
  SPI.setBitOrder(MSBFIRST);              //MSB first
 
  pinMode(CS,OUTPUT);
 
  digitalWrite(CS,LOW);    //set to single SPI mode
  SPI.transfer(WRMR);
  SPI.transfer(RSTIO);
  digitalWrite(CS,HIGH);
 
  digitalWrite(CS,LOW);
  SPI.transfer(WRMR);        //Set data mode to sequential
  SPI.transfer(SEQUENTIAL);
  digitalWrite(CS,HIGH);
 
  digitalWrite(CS,LOW);
  SPI.transfer(WRITE);        //clear outgoing memory status byte
  SPI.transfer(highByte(cw_addr));  //16 bit address transferred one byte at a time
  SPI.transfer(lowByte(cw_addr));
  for(i=0;i<4;i++){
  SPI.transfer(0xAA);
  }
  digitalWrite(CS,HIGH);      //pulse CS
 
  digitalWrite(CS,LOW);
  SPI.transfer(WRITE);        //clear incoming memory status byte
  SPI.transfer(highByte(ccw_addr));
  SPI.transfer(lowByte(ccw_addr));
  for(i=0;i<4;i++){
  SPI.transfer(0xAA);
  }
  digitalWrite(CS,HIGH);
 
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

180 views.. who has the answers?
I have checked all the SPI modes, and the chip is rated for 20MHz.
The 23LC512 is functionally equivalent to the more popular 23LC256.. can anyone replicate the problem?
Thanks all
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 538
Posts: 27089
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Sorry, don't have either of those chips. Haven't had time to browse the datasheet yet.
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Offline Offline
Edison Member
*
Karma: 48
Posts: 1631
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This doesn't look right:
Code:
  digitalWrite(CS,LOW);    //set to single SPI mode
  SPI.transfer(WRMR);
  SPI.transfer(RSTIO);
  digitalWrite(CS,HIGH);

RSTIO is an instruction like WRITE or WRMR. This writes 0xFF to the mode register and that isn't valid.

Pete
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

RSTIO is an instruction like WRITE or WRMR. This writes 0xFF to the mode register and that isn't valid.

Good catch; the problem persists, however.
Logged

Offline Offline
Edison Member
*
Karma: 48
Posts: 1631
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have the feeling that this is a timing problem. Have you tried a lower clock speed or perhaps try Mode 1 (or even 2 or 3)?

Pete
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

That's what I thought; I tried a higher clock divider,  but the result was the exact same.
As for SPI modes, I have tried them all--modes 0 and 3 give similar results, and 1 or 2 don't work at all.
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 64
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This is what I get using your code after changing SPI_MODE0 to SPI_MODE3:

Memory status:   
20   10101010
21   10101010
22   10101010
23   10101010
400   10101010
401   10101010
402   10101010
403   10101010

Now that it works, how do you plan to keep track of variables as you store them? Storing bytes is not very usable unless you convert them to ints or longs... ...unless for text or images

I don't get it - I worked on something else and then went back to it (had to rewire it) and now it doesn't work....

I rewire again with shorter wires (noise issue), use the default SPI speed (/ by 4) and changed the 0x00 to 0xFF on reads

results:
Memory status:   
0   0x0   0b10101010
1   0x1   0b10101010
2   0x2   0b10101010
3   0x3   0b10101010
4   0x4   0b10101010
5   0x5   0b10101010
6   0x6   0b10101010
7   0x7   0b10101010
8   0x8   0b10101010
9   0x9   0b10101010
10   0xA   0b10101010
11   0xB   0b10101010
12   0xC   0b10101010
13   0xD   0b10101010
14   0xE   0b10101010
15   0xF   0b10101010
16   0x10   0b10101010
17   0x11   0b10101010
18   0x12   0b10101010
19   0x13   0b10101010
20   0x14   0b10101010
21   0x15   0b10101010
22   0x16   0b10101010
23   0x17   0b10101010
24   0x18   0b10101010
25   0x19   0b10101010
26   0x1A   0b10101010
27   0x1B   0b10101010
28   0x1C   0b10101010
29   0x1D   0b10101010
30   0x1E   0b10101010
31   0x1F   0b10101010
freeRam(): 1767

...but it still has problems - it works very well 9 out of 10 times when reading/writing 1024 bytes - I'll have to read the specs again and again... let me know what you find out - thanks

« Last Edit: May 03, 2013, 09:43:18 pm by sparkfuntoday » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

How do you have the unused pin configured? Mine is tied to ground, though I get different results with it tied to Vcc. The datasheet doesn't specify which is best, though it advises not to leave it floating.

I'll try rewiring mine with shorter jumpers.. maybe it's noise or there's too much capacitance on the line? I'm going to try observing the SCK signal on my o-scope later, some devices are sensitive to long rise-times. On a preliminary search, I couldn't find any free samples for Schmitt triggers..

As for tracking data, I'm vaguely thinking of using it as a type of data buffer between MCUs, so that one isn't stuck waiting for the other to free up. Effectively it'd be structured as a stack, with a header byte saying how many bytes and of what type it should be expecting.
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 64
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

How do you have the unused pin configured? Mine is tied to ground, though I get different results with it tied to Vcc. The datasheet doesn't specify which is best, though it advises not to leave it floating.
Code:
23LC512 pin 1 CS to UNO pin 10 (CS)
23LC512 pin 2 SO to UNO pin 12 (MISO) or(pin 1 of ICSP bus)
23LC512 pin 3 to GND
23LC512 pin 4 to GND
23LC512 pin 5 SI to UNO pin 11 (M0S1) or (pin 4 of ICSP bus)
23LC512 pin 6 SCK to UNO pin 13 (SCK) or (pin 3 of ICSP bus)
23LC512 pin 7 to Vcc
23LC512 pin 8 to Vcc
I'll try rewiring mine with shorter jumpers.. maybe it's noise or there's too much capacitance on the line? I'm going to try observing the SCK signal on my o-scope later, some devices are sensitive to long rise-times. On a preliminary search, I couldn't find any free samples for Schmitt triggers..
Code:
I also got better results when I slowed down my serial port - I went from 115200 down to 38600 and didn't seem to find a fail
As for tracking data, I'm vaguely thinking of using it as a type of data buffer between MCUs, so that one isn't stuck waiting for the other to free up. Effectively it'd be structured as a stack, with a header byte saying how many bytes and of what type it should be expecting.

Actually, I think it might be better to write 64K of 0xAA and then go back an read all 64K to find a fail - can't trust the serial output
« Last Edit: May 04, 2013, 06:33:46 pm by sparkfuntoday » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 18
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You're using the hardware CS on the Uno? Won't that go high in the middle of a command, since we call spiTransfer multiple times in what the SRAM considers one command?
Logged

Global Moderator
Boston area, metrowest
Offline Offline
Brattain Member
*****
Karma: 538
Posts: 27089
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

CS is under software control. You can set i it low, send as many bytes as you want, then bring it high again.
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Offline Offline
Jr. Member
**
Karma: 0
Posts: 64
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You're using the hardware CS on the Uno? Won't that go high in the middle of a command, since we call spiTransfer multiple times in what the SRAM considers one command?

Honestly, I'm a newbie, I got my first UNO this Feb (2013) and all I did was to copy and paste your code and figured since you were having a problem I'd see what the internet had to say. Well, this is what I came up with. Something is still wrong because I don't understand this comment (what did you do to correct it?):
Code:
Quote from: el_supremo on April 30, 2013, 09:47:35 PM
RSTIO is an instruction like WRITE or WRMR. This writes 0xFF to the mode register and that isn't valid.

Good catch; the problem persists, however.
):
Code:
using pin 8:
Configuing RAM
RAM configured
Memory status:
0 0x0 0b11010101
1 0x1 0b1010101
2 0x2 0b1010101
3 0x3 0b1010101
freeRam(): 1743 bytes, using: 305 bytes

using pin 10:
Configuing RAM
RAM configured
Memory status:
0 0x0 0b10101010
1 0x1 0b10101010
2 0x2 0b10101010
3 0x3 0b10101010
freeRam(): 1743 bytes, using: 305 bytes

However, I still don't understand it, both ways consume more memory as you increase byteCnt. Why would that be if it was truly read/writing to the SRAM?
« Last Edit: May 05, 2013, 12:30:13 am by sparkfuntoday » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Have you tried tying the HOLD pin to VCC?  A similar issue was raised in a thread for the Microchip 23k256 sram chips.  I also noticed some errors due to my IC socket not being 100% seated on my breadboard (it can get loose).  I used the wiring diagram from the referenced thread on a Due with a clock divider of 0 and received the right output.

23k256 thread for reference: http://arduino.cc/forum/index.php?topic=150346.0
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 64
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

with:
CS pin 8
SPI_CLOCK_DIV2
SPI_MODE0
and no delayMicroseconds()
and no pinMode(10, OUTPUT);

every thing works fine with even shorter wires (don't use jumper wires with SRAM, with EEPROM OK, at least for me)
64K bytes written in 1.2 sec (in BYTE mode)
64K writes and 64K reads 100 times with different data each time and no fails
64K reads and writes in SEQUENTIAL mode:
write time= 128 mSec
read time= 128 mSec
no fails - I claim done
« Last Edit: May 06, 2013, 02:04:54 pm by sparkfuntoday » Logged

Pages: [1] 2   Go Up
Jump to: