0
Offline
Newbie
Karma: 0
Posts: 2
Arduino rocks
|
 |
« on: October 03, 2009, 03:50:44 am » |
I'm new in the Arduino programming, I'm just an hobbyst. So please be gentle, also with my english. Anyway, I want post an argument which could be useful for many developers involved in storing physical data from sensors, in particular the amount of data and the speed of reading/writing. For this purpose I read about the new Microchip SRAM's 23K256 and suppose it's a very good solution to improve the limit of the Arduino Duemilanove board (which has only 2K of ram). So I invite an interested reader to take a look at Datasheet of this powerful ram chip. I post this article because I encountered problems in interfacing it with Arduino Duemilanove, ...nothing is going as in theory it should go. I enclose next my code. What is wrong?
#define CS 10 // Arduino pin 10 - 23K256 CS pin
#define MOSI 11 // Arduino pin 11 - 23K256 MOSI pin
#define MISO 12 // Arduino pin 12 - 23K256 MISO pin
#define SCK 13 // Arduino pin 13 - 23K256 SCK pin
byte value;
byte clr;
char spi_transfer(volatile char data)
{
SPDR = data; // Start the transmission
while (!(SPSR & (1<<SPIF))) // Wait the end of the transmission
{};
return SPDR; // return the received byte
}
void setup()
{
Serial.begin(9600);
pinMode(MOSI, OUTPUT);
pinMode(SCK, OUTPUT);
pinMode(CS, OUTPUT);
pinMode(MISO, INPUT);
digitalWrite(CS, HIGH); //disable device
//Configure SPI control register (SPCR)
SPCR = B1010000;
// | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
// | SPIE | SPE | DORD | MSTR | CPOL | CPHA | SPR1 | SPR0 |
// SPIE - Enables the SPI interrupt when 1
// SPE - Enables the SPI when 1
// DORD - Sends data least Significant Bit First when 1, most Significant Bit first when 0
// MSTR - Sets the Arduino in master mode when 1, slave mode when 0
// CPOL - Sets the data clock to be idle when high if set to 1, idle when low if set to 0
// CPHA - Samples data on the falling edge of the data clock when 1, rising edge when 0'
// SPR1 and SPR0 - Sets the SPI speed, 00 is fastest (4MHz) 11 is slowest (250KHz)
//--------------------------------
clr=SPSR;
clr=SPDR;
digitalWrite(CS,LOW);delay(10);
spi_transfer(0x01);
spi_transfer(0x41);
digitalWrite(CS,HIGH);
delay(10);
}
void loop()
{
digitalWrite(CS,HIGH);
delay(100);
Serial.print("Read Status Register Config -> ");
digitalWrite(CS,LOW);
spi_transfer(0x05);
value=spi_transfer(0xFF);
digitalWrite(CS,HIGH);
Serial.println(value,DEC);
delay(100);
Serial.println("Write data to RAM ");
digitalWrite(CS,LOW);
spi_transfer(0x02); //write command
spi_transfer(0x00); //MSB address byte
spi_transfer(0x00); //LSB address byte
for (int i=1; i<=10; i++)
{
spi_transfer(0x33); //example data to write
}
digitalWrite(CS,HIGH);
delay(100);
Serial.println("Read data from RAM ");
digitalWrite(CS,LOW);
spi_transfer(0x03); //read command
spi_transfer(0x00); //MSB address byte
spi_transfer(0x00); //LSB address byte
for (int i=1; i<=10; i++)
{
value=spi_transfer(0xFF); //send a dummy byte and receive byte stored
Serial.print(value,DEC); Serial.print(" ");
}
digitalWrite(CS,HIGH);
Serial.println();Serial.println();
delay(2000);
}
I obtain non-sense values from the Read Status Register routine, to verify the right configuration (Serial storage mode) and also from Read command. I suppose the answer must require a better knowledge than mine, and a very deepened study of the matter. Thank you in advance.
|
|
|
|
|
Logged
|
|
|
|
|
Greenwood, Indiana
Offline
God Member
Karma: 0
Posts: 508
Arduino rocks
|
 |
« Reply #1 on: October 03, 2009, 04:37:06 pm » |
http://www.arduino.cc/en/Tutorial/SPIEEPROMIt should be possible to use it similar to this but I've not gotten very far with Arudino yet.
|
|
|
|
|
Logged
|
If it was designed by man it can be repaired by man.
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 21
Arduino rocks
|
 |
« Reply #2 on: October 06, 2009, 07:18:44 am » |
I have tried with this code on arduino, and also with similar code on a Atmega128. I am currently using 10k inline resistors for the level convert and a 1k inline+10 to 3v3 for CS. 4k7 pullup to 3v3 on MISO. I dont have a scope to check what is actually on the wire, so its blind luck if its code or hardware that is the problem. Have you checked the spi mode is correct? #define DATAOUT 11//MOSI #define DATAIN 12//MISO #define SPICLOCK 13//sck #define SLAVESELECT 10//ss
//opcodes #define WRITE 2 #define READ 3
char spi_transfer(volatile char data) { SPDR = data; // Start the transmission while (!(SPSR & (1<<SPIF))) // Wait for the end of the transmission { Serial.print('.',BYTE); }; return SPDR; // return the received byte }
void setup() { Serial.begin(9600); Serial.print('h',BYTE); Serial.print('i',BYTE); Serial.print('\n',BYTE);//debug pinMode(DATAOUT, OUTPUT); pinMode(DATAIN, INPUT); pinMode(SPICLOCK,OUTPUT); pinMode(SLAVESELECT,OUTPUT); digitalWrite(SLAVESELECT,HIGH); //disable device delay(100); }
void loop() {
digitalWrite(SLAVESELECT,LOW); spi_transfer(0x41); digitalWrite(SLAVESELECT,HIGH);
delay(1000); SPCR = (1<<SPE)|(1<<MSTR); byte clr=SPSR; clr=SPDR; delay(10);
digitalWrite(SLAVESELECT,LOW); spi_transfer(WRITE); spi_transfer(0); spi_transfer(0); spi_transfer(1); spi_transfer(2); spi_transfer(3); spi_transfer(4); spi_transfer(5); digitalWrite(SLAVESELECT,HIGH);
delay(3000); digitalWrite(SLAVESELECT,LOW); spi_transfer(READ); spi_transfer(0);//address spi_transfer(0);//address char data1 = spi_transfer(0xFF); //get data byte char data2 = spi_transfer(0xFF); //get data byte char data3 = spi_transfer(0xFF); //get data byte char data4 = spi_transfer(0xFF); //get data byte char data5 = spi_transfer(0xFF); //get data byte digitalWrite(SLAVESELECT,HIGH);
Serial.print(data1,DEC); Serial.print('\n',BYTE); Serial.print(data2,DEC); Serial.print('\n',BYTE); Serial.print(data3,DEC); Serial.print('\n',BYTE); Serial.print(data4,DEC); Serial.print('\n',BYTE); Serial.print(data5,DEC); Serial.print('\n',BYTE); }
If I comment out the init code for seq access and hold disabled, it returns -1, otherwise its stuck in the wait loop. But I think the -1 is really from the spi function, not the sram itself.
|
|
|
|
« Last Edit: October 06, 2009, 07:25:54 am by MORA »
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 2
Arduino rocks
|
 |
« Reply #3 on: October 08, 2009, 12:37:23 pm » |
After some frustrating tests in interfacing the Microchip SRAM 23K256 with Arduino duemilanove, the results are without success. I'm quite confused about this simple hardware and software interfacing, as reported in the Datasheet and in Application notes. From the Hardware point of view, I used the next wiring: - an in-line resistor of 1K on pin CS (SLAVESELECT) plus a 10K pull-up resistor to 3,3 volt; - an in-line resistor of 10K on pin MOSI (DATAIN); - an in-line resistor of 10K on pin SCLK (SERIALCLOCK); - direct connection to pin MISO (DATAOUT); - a power of 3,3 volts coming directly from the proper pin on Arduino, connected to pin Vdd of 23K256 chip; - SPI mode 1 (CPOL=0 and CPHA=1). I also tried to simplify the code, just limiting it to only two simple steps: 1) configuring the Write Status Register of the SRAM; 2) reading the above configuration. In the next code I post, I first send the command Write Status Register (0x01), then send the configuration Sequential mode and Hold pin disabled (0x41). In second place, I send the Read Status Register Command (0x05) and finally send a dummy byte (0xFF) to obtain a byte from the MISO pin. Unfortunately I do not obtain the value 0x41 (65 in decimal format), as I should expect ! I just obtain -1 or 0. The solution of the above two steps is crucial for the next phase of storing true data coming from an high resolution ADC. Is there anybody interested with this challenge? #define DATAOUT 11//MOSI #define DATAIN 12//MISO #define SPICLOCK 13//sck #define SLAVESELECT 10//ss
byte clr; char value;
char spi_transfer(volatile char data) { SPDR = data; // Start the transmission while (!(SPSR & (1<<SPIF))) // Wait for the end of the transmission { //Serial.print('.'); }; return SPDR; // return the received byte }
void setup() { Serial.begin(9600); pinMode(DATAOUT, OUTPUT); pinMode(DATAIN, INPUT); pinMode(SPICLOCK,OUTPUT); pinMode(SLAVESELECT,OUTPUT); digitalWrite(SLAVESELECT,HIGH); //disable device delay(10); SPCR= (1<<SPE)|(1<<MSTR)|(0<<CPOL)|(1<<CPHA); //SPI mode 1 clr=SPSR; clr=SPDR; delay(10); }
void loop() { digitalWrite(SLAVESELECT,LOW); spi_transfer(0x01); Serial.println("send 0x01 Write Status Register Command "); delay(100); spi_transfer(0x41); Serial.println("send 0x41 Select Sequential mode, Hold disabled"); digitalWrite(SLAVESELECT,HIGH); delay(100);
digitalWrite(SLAVESELECT,LOW); spi_transfer(0x05); Serial.println("send 0x05 Read Status Register Command "); delay(100); value=spi_transfer(0xFF); digitalWrite(SLAVESELECT,HIGH); Serial.print("Data from Status Register -> "); //should obtain 0x41 or 65 in dec mode Serial.println(value,DEC); Serial.println(); delay(3000); }
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 2
Arduino rocks
|
 |
« Reply #4 on: November 08, 2009, 03:21:20 pm » |
I've written a library that interfaces with this chip which I've uploaded to the playground. I'd include a link but the board won't let me as this is my first post ...
-- Phil
|
|
|
|
« Last Edit: November 08, 2009, 03:22:43 pm by LichP »
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 2
Arduino rocks
|
 |
« Reply #5 on: November 08, 2009, 03:21:48 pm » |
|
|
|
|
« Last Edit: November 08, 2009, 03:22:06 pm by LichP »
|
Logged
|
|
|
|
|
carolinas
Offline
Newbie
Karma: 0
Posts: 9
Arduino rocks
|
 |
« Reply #6 on: January 25, 2010, 11:24:55 pm » |
hi, does this library work with arduino 017? I can't get this one working. The IDE does not recognize it as a library,even though it was placed in the libraries folder.
thanks.
|
|
|
|
|
Logged
|
|
|
|
|
Manchester (England England)
Offline
Brattain Member
Karma: 277
Posts: 25501
Solder is electric glue
|
 |
« Reply #7 on: January 26, 2010, 10:05:03 am » |
Yes it works, put them in a folder called SpiRAM and then at the start of the sketch put the lines:- #include "Spi.h" #include "SpiRAM.h"
As the note says you need the Spi library in first.
|
|
|
|
« Last Edit: January 26, 2010, 10:05:39 am by Grumpy_Mike »
|
Logged
|
|
|
|
|
carolinas
Offline
Newbie
Karma: 0
Posts: 9
Arduino rocks
|
 |
« Reply #8 on: January 26, 2010, 03:57:20 pm » |
Thanks for your response. I had all of that in already, I must have something else wrong.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Jr. Member
Karma: 0
Posts: 50
Arduino rocks
|
 |
« Reply #9 on: September 11, 2010, 07:08:07 pm » |
Anyone know if using an SPI SRAM chip would be any faster than using an I2C EEPROM chip?
Right now I'm experimenting with an I2C EEPROM chip of the same size. It works great, but it takes 5ms to write a single byte. I know I could write it about 30 bytes at a time, but one is easier.
I imagine this SPI SRAM chip is capable writing a single byte in less than 5ms.
thanks, Phil
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 10
Arduino rocks
|
 |
« Reply #10 on: September 19, 2010, 01:42:33 pm » |
Writing to SRAM should be much faster than writing to EEPROM. Looking at the data sheet for the 23K256, the only limitation I see is that the clock frequency at 3.0V has to be below 20MHz for the industrial version and below 16MHz for the automotive version. In other words, it can accept data as fast as the Arduino can push it out. Just keep in mind that while your EEPROM will retain data for decades, the SRAM will lose its data as soon as Vcc drops below 1.2V.
|
|
|
|
|
Logged
|
|
|
|
|
Kauai
Offline
Newbie
Karma: 0
Posts: 36
Amani 64 CPLD Shield
|
 |
« Reply #11 on: September 22, 2010, 06:36:45 pm » |
I measured the 23K256 transfer process to be around 260us. Not great but far better than 5ms! Below is a link to some work I've done with the 23K256, a CPLD, and the Arduino. I have a method of injecting addressing in the 23K256 data stream and expanding memory. I have tested up to 256KB, the theoretical limit is 2MB. The practical limit is far less due to cost and real estate. http://majolsurf.net/wordpress/?p=930
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 3
Arduino rocks
|
 |
« Reply #12 on: October 08, 2010, 04:15:55 pm » |
Hi all, I'm trying to make this work with Arduino 021, but so far no success. I want to use the included SPI library instead of "Spi.h" that the library in the playground uses. So far this is my code: # SPIRAM.h #include <WProgram.h> #include <SPI.h>
// SRAM opcodes #define READ 0b00000011 #define WRITE 0b00000010 #define RDSR 0b00000101 #define WRSR 0b00000001
#define HOLD 1 #define BYTE_MODE (0x00 | HOLD) #define PAGE_MODE (0x80 | HOLD) #define STRM_MODE (0x40 | HOLD)
class SPIRAM { public: SPIRAM(); void writeByte(uint8_t address, uint8_t data); uint8_t readByte(uint8_t address); private: void setMode(uint8_t mode); uint8_t mode_; };
# SPIRAM.cpp #include "pins_arduino.h" #include "SPIRAM.h"
SPIRAM::SPIRAM() { digitalWrite(SS, LOW); SPI.begin(); SPI.setBitOrder(MSBFIRST); SPI.setDataMode(SPI_MODE1); mode_ = BYTE_MODE; }
void SPIRAM::writeByte(uint8_t address, byte data) { setMode(BYTE_MODE); digitalWrite(SS, LOW); SPI.transfer(WRITE); SPI.transfer((byte)(address >> 8)); SPI.transfer(address); SPI.transfer(data); digitalWrite(SS, HIGH); }
byte SPIRAM::readByte(uint8_t address) { byte data; setMode(BYTE_MODE); digitalWrite(SS, LOW); SPI.transfer(READ); SPI.transfer((byte)(address >> 8)); SPI.transfer(address); data = SPI.transfer(0x00); digitalWrite(SS, HIGH); return data; }
// write the status register (bites 7 and 6) void SPIRAM::setMode(uint8_t mode) { if (mode != mode_) { digitalWrite(SS, LOW); SPI.transfer(WRSR); SPI.transfer(mode); digitalWrite(SS, HIGH); mode_ = mode; } }
#SRAMTest.pde #include <SPI.h> #include "SPIRAM.h"
SPIRAM spiRAM;
void setup() { Serial.begin(9600); }
void loop() { char data_to_chip[17] = "Testing 90123456"; char data_from_chip[17] = ""; int i; for (i=0; i < 17; i++) { spiRAM.writeByte(i, data_to_chip[i]); } // read back data for (i=0 ; i < 17; i++) { data_from_chip[17] = spiRAM.readByte(i); } data_from_chip[i] = '\0'; Serial.print("data: "); Serial.println(data_from_chip); delay(3000); }
On the hardware side, I'm using this (taken from this post):  I just want to test the sram with a simple write/read byte and the go to page/stream. Any idea where could be my problem? thanks!
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 3
Arduino rocks
|
 |
« Reply #13 on: October 08, 2010, 04:26:16 pm » |
This is what I'm getting back from the sram: will write data 'T' to address 0 will write data 'e' to address 1 will write data 's' to address 2 will write data 't' to address 3 will write data 'i' to address 4 will write data 'n' to address 5 will write data 'g' to address 6 will write data ' ' to address 7 will write data '9' to address 8 will write data '0' to address 9 will write data '1' to address A will write data '2' to address B will write data '3' to address C will write data '4' to address D will write data '5' to address E will write data '6' to address F will write data '' to address 10 read data '0' from address 0 read data '0' from address 1 read data 'FC' from address 2 read data 'F8' from address 3 read data 'FF' from address 4 read data 'FD' from address 5 read data 'FF' from address 6 read data 'FC' from address 7 read data '70' from address 8 read data 'FF' from address 9 read data 'FF' from address A read data 'FF' from address B read data 'E7' from address C read data 'FF' from address D read data 'FF' from address E read data 'FF' from address F read data 'FF' from address 10
|
|
|
|
|
Logged
|
|
|
|
|
Greenwood, Indiana
Offline
God Member
Karma: 0
Posts: 508
Arduino rocks
|
 |
« Reply #14 on: October 10, 2010, 03:46:57 am » |
|
|
|
|
|
Logged
|
If it was designed by man it can be repaired by man.
|
|
|
|
|