Hi,
EDIT: This may simply have been a defect with the breakout board.
EDIT: It was a bug with the board after all. Was able to get this to function using just dip chips on a breadboard with jumper wire. However note that the level shifter I had available (the 4050) is too slow to run the attached source as is. Changing the line
SPI.setClockDivider(SPI_CLOCK_DIV2);
to
SPI.setClockDivider(SPI_CLOCK_DIV32);
and it ran fine (t/y SurferTim).
original post
I'm having issues reading/writing to a 23K256 SRAM chip via SPI. It appears that bytes read are not the ones written.
Environment:
Arduino Uno R3
Arduino IDE 1.05
The 23K256 chip is on a small breakout board by Switch Science (Japan) that includes a level shifter on board to allow direct connection to the Arduino.
Sketch (includes pin connection chart in comments):
#include <SPI.h>
#include <SPISRAM.h>
/*
SRAM Arduino
1 CS 10(CS)
2 SO 12(MISO)
3 - -
4 Vss GND
5 SI 11(MOSI)
6 SCK 13(SCK)
7 HOLD <-- 100k ohm -- 3.3V
8 Vcc 3.3V
*/
SPISRAM myRAM(10); // CS pin
char buffer[128];
void setup()
{
pinMode(5, OUTPUT);
Serial.begin(9600);
SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV2);
SPI.setDataMode(SPI_MODE0);
Serial.println("Byte write...");
myRAM.write(0,'H');
myRAM.write(1,'e');
myRAM.write(2,'l');
myRAM.write(3,'l');
myRAM.write(4,'o');
myRAM.write(5,'-');
Serial.println("Byte read...");
Serial.println(myRAM.read(0));
Serial.println(myRAM.read(1));
Serial.println(myRAM.read(2));
Serial.println(myRAM.read(3));
Serial.println(myRAM.read(4));
Serial.println(myRAM.read(5));
Serial.println("\nByte write...");
myRAM.write(0x7FFC,'W');
myRAM.write(0x7FFD,'o');
myRAM.write(0x7FFE,'r');
myRAM.write(0x7FFF,'l');
myRAM.write(0x8000,'d');
myRAM.write(0x8001,'!');
myRAM.write(0x8002,'!');
Serial.println("Byte read...");
Serial.println(myRAM.read(0x7FFC));
Serial.println(myRAM.read(0x7FFD));
Serial.println(myRAM.read(0x7FFE));
Serial.println(myRAM.read(0x7FFF));
Serial.println(myRAM.read(0x8000));
Serial.println(myRAM.read(0x8001));
Serial.println(myRAM.read(0x8002));
Serial.println("\nseq write...");
int addr = 0x7F00;
myRAM.write(addr, (byte*)"Hello world!!", sizeof("Hello world!!"));
Serial.println("seq read...");
myRAM.read(addr, (byte*)buffer, sizeof(buffer));
Serial.println( buffer );
Serial.println("\nByte read at operator[]...");
myRAM[100] = 'H';
myRAM[101] = 'e';
myRAM[102] = 'l';
myRAM[103] = 'l';
myRAM[104] = 'o';
Serial.println( myRAM[100] );
Serial.println( myRAM[101] );
Serial.println( myRAM[102] );
Serial.println( myRAM[103] );
Serial.println( myRAM[104] );
Serial.println("\nRandom read/write...");
for(int i=0;i<100;i++){
int addr = random() & 0x7fff;
byte val = i;
Serial.print( addr, HEX );
Serial.print( " " );
Serial.print( val, HEX );
myRAM[addr] = val;
Serial.print( " " );
Serial.println( myRAM[addr], HEX );
}
}
void loop()
{
}
The SPISRAM library used is as follows.
/*
Copyright (c) 2010 by arms22 (email redacted)
Microchip 23x256 SPI SRAM library for Arduino
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef SPISRAM_H
#define SPISRAM_H
#include <SPI.h>
class SPISRAM
{
public:
struct MemCell {
SPISRAM &device;
unsigned int address;
MemCell &operator=(byte data){
device.write(address,data);
return *this;
}
operator byte() {
return device.read(address);
}
MemCell(SPISRAM &d,unsigned int a) : device(d), address(a) {};
~MemCell(){};
};
MemCell operator[](unsigned int address){
MemCell memcell(*this,address);
return memcell;
}
SPISRAM(byte ncsPin);
byte read(unsigned int address);
void read(unsigned int address, byte *buffer, unsigned int size);
void write(unsigned int address, byte data);
void write(unsigned int address, byte *buffer, unsigned int size);
private:
byte _ncsPin;
byte _buf[4];
void select(void);
void deselect(void);
byte transfer(byte length);
};
#endif
/*
Copyright (c) 2010 by arms22 (email redacted)
Microchip 23x256 SPI SRAM library for Arduino
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "SPISRAM.h"
// INSTRUCTION SET
#define READ 0x03 // Read data from memory
#define WRITE 0x02 // Write data to memory
#define RDSR 0x05 // Read Status register
#define WRSR 0x01 // Write Status register
// STATUS REGISTER
#define BYTE_MODE 0x00
#define PAGE_MODE 0x80
#define SEQ_MODE 0x40
SPISRAM::SPISRAM(byte ncsPin)
: _ncsPin(ncsPin)
{
}
byte SPISRAM::read(unsigned int address)
{
_buf[0] = READ;
_buf[1] = address >> 8;
_buf[2] = address & 0xff;
_buf[3] = 0x00;
return transfer(4);
}
void SPISRAM::read(unsigned int address, byte *buffer, unsigned int size)
{
_buf[0] = WRSR;
_buf[1] = SEQ_MODE;
transfer(2);
select();
SPI.transfer(READ);
SPI.transfer(address >> 8);
SPI.transfer(address & 0xff);
for(unsigned int i=0; i<size; i++){
*buffer++ = SPI.transfer(0);
}
deselect();
}
void SPISRAM::write(unsigned int address, byte data)
{
_buf[0] = WRITE;
_buf[1] = address >> 8;
_buf[2] = address & 0xff;
_buf[3] = data;
transfer(4);
}
void SPISRAM::write(unsigned int address, byte *buffer, unsigned int size)
{
_buf[0] = WRSR;
_buf[1] = SEQ_MODE;
transfer(2);
select();
SPI.transfer(WRITE);
SPI.transfer(address >> 8);
SPI.transfer(address & 0xff);
for(unsigned int i=0; i<size; i++){
SPI.transfer(*buffer++);
}
deselect();
}
void SPISRAM::select(void)
{
digitalWrite(_ncsPin, LOW);
}
void SPISRAM::deselect(void)
{
digitalWrite(_ncsPin, HIGH);
}
byte SPISRAM::transfer(byte length)
{
byte ret,i;
select();
for(i=0; i<length; i++){
ret = SPI.transfer(_buf[i]);
}
deselect();
return ret;
}
And the serial output looks like this. I would expect the serial output to start with the same characters that were written, particularly with the sequential read/write operation returning the character string "Hello world!!". However, I get seemingly random characters: (Ø×aD?
Byte write...
Byte read...
1
66
81
81
92
16
Byte write...
Byte read...
26
93
97
81
64
0
1
seq write...
seq read...
(Ø×aD?
Byte read at operator[]...
1
66
81
81
94
Random read/write...
41A7 0 0
3AF1 1 0
2CD9 2 0
C2A 3 2
3782 4 1
5AC8 5 1
ED8 6 4
9FE 7 6
2F43 8 0
44D 9 0
1898 A 1
3C55 B 5
128C C 8
5BE2 D 8
54B3 E C
3747 F F
3917 10 0
4111 11 1
4398 12 3
4954 13 7
2E2F 14 0
2B11 15 0
162D 16 B
B05 17 C
3258 18 10
66F5 19 10
16B 1A 10
1DD6 1B 17
7788 1C 18
1D07 1D 19
6499 1E 1C
3492 1F 1E
F48 20 0
5133 21 1
6E62 22 0
1441 23 6
4CF3 24 0
F0D 25 3
5023 26 8
6AE5 27 C
785F 28 0
3530 29 2
22D1 2A 0
76C8 2B B
75ED 2C 13
4561 2D 13
680C 2E 18
154B 2F 1E
2902 30 20
5435 31 20
39 32 22
5081 33 26
6484 34 20
25B8 35 22
6514 36 28
1BA2 37 2C
339C 38 31
66B4 39 30
6E5A 3A 32
1267 3B 34
2C2A 3C 38
34CA 3D 38
5AE5 3E 3D
1248 3F 3E
49E9 40 0
20C5 41 0
5F1 42 3
22B0 43 4
56C4 44 0
1C15 45 2
2B8A 46 9
11E5 47 E
6A9B 48 0
784D 49 3
4339 4A 2
75F6 4B F
7F7 4C 12
26E8 4D 11
4CA1 4E 18
1005 4F 1E
6AD3 50 0
78FE 51 3
73ED 52 0
4DA5 53 8
38D5 54 7
60F3 55 0
1AD9 56 17
4CE4 57 1C
3C5B 58 23
3BFA 59 23
546C 5A 20
DC3 5B 28
1151 5C 30
73E2 5D 32
1C20 5E 39
1FAE 5F 3F
100C 60 40
1EE1 61 41
7D06 62 43
2698 63 44
Please let me know if any of you have an idea what I'm doing wrong. Thanks!
Edit: By the way, following manufacturer spec (Switch Science) I have a 100K resistor between VCC and pin 7, so that isn't the cause from what I can see (apparently that is a common error).
A pic of the breakout board and pin diagram can be found here: http://docid81hrs3j1.cloudfront.net/contents/cms/10121702_5077ce9567a88.jpg