Need More Memory? Arduino and 23LC1024

Buzz Lightyear

See this post for background information on interfacing the 23K256 SPI SRAM to the Arduino. Since the 23LC1024 is tolerant of 5V logic levels, it was much easier. However, note in the code below, the larger memory (1024K vs. 256K) requires passing 3-bytes (24-bits) of memory address.

Simple Test Program:

/*
   Used the following components and wire routing:
   (1) Arduino Uno
   (2) Microchip 23LC1024
   (3) 10K Resistor
 */
#include <SPI.h>

//SRAM opcodes
#define RDSR        5
#define WRSR        1
#define READ        3
#define WRITE       2
 
//Byte transfer functions
uint8_t Spi23LC1024Read8(uint32_t address) {
  uint8_t read_byte;

  PORTB &= ~(1<<PORTB2);        //set SPI_SS low
  SPI.transfer(READ);
  SPI.transfer((uint8_t)(address >> 16) & 0xff);
  SPI.transfer((uint8_t)(address >> 8) & 0xff);
  SPI.transfer((uint8_t)address);
  read_byte = SPI.transfer(0x00);
  PORTB |= (1<<PORTB2);         //set SPI_SS high
  return read_byte;
}
 
void Spi23LC1024Write8(uint32_t address, uint8_t data_byte) {
  PORTB &= ~(1<<PORTB2);        //set SPI_SS low
  SPI.transfer(WRITE);
  SPI.transfer((uint8_t)(address >> 16) & 0xff);
  SPI.transfer((uint8_t)(address >> 8) & 0xff);
  SPI.transfer((uint8_t)address);
  SPI.transfer(data_byte);
  PORTB |= (1<<PORTB2);         //set SPI_SS high
}
 
void setup(void) {
  uint32_t i;
  uint8_t value;

  Serial.begin(9600);
  SPI.begin();

  for (i=0; i<32; i++) {
    Spi23LC1024Write8(i, (uint8_t)i);
    value = Spi23LC1024Read8(i);
    Serial.println((uint16_t)value);
  }
}

void loop() {
}

Arduino and Microchip 23LC1024 SPI SRAM

Wire Routing:

   Arduino -- 23LC1024
   D13 <------> SCK
   D12 <------> MISO
   D11 <------> MOSI
   D10 <------> CS
   5V  <------> VCC
   5V  <------> HOLD
   5V  <-10KR-> CS
   GND <------> VSS

About Jim Eli

µC experimenter
This entry was posted in Uncategorized and tagged , , , , . Bookmark the permalink.

19 Responses to Need More Memory? Arduino and 23LC1024

  1. Bogdan says:

    I have exactly the same chip and I am trying to make it work with Arduino Leonardo. I am a bit puzzled about the following:
    – is the pull-up resistor for CS really necessary?
    – why PORTB &= ~(1<<PORTB2) for SS low, and not digitalWrite(10, LOW); ?
    – you didn't use RDSR and WRSR; they should be needed for setting up the SRAM module; isn't any setup necessary?
    – in the wire routing you omitted Vcc to 5V 🙂

    Any further input would be necessary as I am still struggling to make this work.

    Thank you

    • Jim Eli says:

      – is the pull-up resistor for CS really necessary?

      From the datasheet:
      “A low level on this pin selects the device. A high level deselects the device and forces it into Standby mode. When the device is deselected, SO goes to the high-impedance state, allowing multiple parts to share the same SPI bus. After power-up, a low level on CS is required, prior to any sequence being initiated.”

      It is definitely needed if you are connecting more than 1 SPI device on the same lines, and floating pins are generally a bad idea. If the chip goes into Standby mode it will be unresponsive. I didn’t test it without the pullup.

      – why PORTB &= ~(1<<PORTB2) for SS low, and not digitalWrite(10, LOW); ?

      Simply for speed. To get a glimpse of the overhead required by digitalWrite see this post.

      – you didn't use RDSR and WRSR; they should be needed for setting up the SRAM module; isn't any setup necessary?

      Byte operation is the default operating mode. If you desire another mode (i.e., page or sequential), then it would be necessary to fiddle with the mode register. It wasn’t required for this simple test.

      – in the wire routing you omitted Vcc to 5V

      Thanks. I’ll correct that.

  2. Kirill says:

    Thanks for the post! 🙂 It’s great!
    PS: Has left to order…

  3. Paolo says:

    Congratulations for your articles.

    Thanks to this your article I have created a project with arduino one and 23LC1024.

    I would like to ask your advice, I now would like to accomplish the same project with Arduino mini (V 05) and 23LC1024.

    I used the same code used for arduino one, but I could not make it work.

    The data that I am going to read from memory are incorrect.
    Can you give me some advice how to solve?
    It could be a clock problem or SPI library that fails to work with arduino mini?

    thanks

    • Jim Eli says:

      I have never used an Arduino Mini, so I’m not much help here. However, here are a few things you might check:

      (1) Check the pin mapping

      (2) Set the SPI Slave select pin as an output:
      const int SS = 10;
      pinMode (SS, OUTPUT);

      (3) Also, I found this note on the Arduino Mini Webpage: “If anything besides the Mini USB (or other) adapter is connected to pins 0 and 1, it will interfere with the USB communication, preventing new code from being uploaded or other communication with the computer.”

  4. heimi says:

    No problems to set and get data to the chip until I tried to drive the CS via a pull-up and an Si-diode to realize an OR. Reading the datasheet shows that the Low-level input voltage must not be greater than 0.10*Vcc. Doing the OR with an HCT32 solved the problem. Perhaps this will help someone.

  5. Thanks a lot, I just got a few of these chips and your documentation worked flawlessly!

    When trying to move our code to sequential reading and writing instead of byte-based reading and writing, we didn’t have to change the mode of the chip to get unlimited streams of read/write bytes from/to the chip. I couldn’t find documentation on what the default behavior of the chip is, it seems like the sequential mode is default, but that might not always be true.

    What functions should I call with which parameter to change the mode between byte/page/sequential? Is this SPI.setDataMode(mode)? The datasheet mentions “Sequential Operation is selected when bits 7 and 6 in the MODE register are set to 01” but I’m not sure whether these are least/most significant bits etc.

    Again, thanks a lot for this post, it helps me make my epic xmas tree light display ideas possible!

    • Jim Eli says:

      As I see it, for the 23LC1024, you would call SPI.setDataMode(mode), with mode = b0100000 (0x40 in hex or 64 in decimal). Per the datasheet, bits 6 and 7 set the mode, while bits 0 through 5 are reserved. And you are correct, these bits should be set to “01” for sequential operation. Bit 0 should always be the least significant bit, and bits are transmitted in least to most significant order (hence your possible confusion). A close study of the datasheet should make this clear(er?).

      However, I have not confirmed this with a test. I’m happy to have helped.

  6. Grumpy_Mike says:

    You said of the pull up resistor:-
    It is definitely needed if you are connecting more than 1 SPI device on the same lines, and floating pins are generally a bad idea. If the chip goes into Standby mode it will be unresponsive.
    Two things wrong with that,
    1) When the ~CS pin is un-asserted, that is it goes high, it is the arduino pin that is doing this. It is driven high by the pin and so a pull up is not needed. You would only need a pull up if you un-assert the pin by making it an input, and you are not doing that.
    2) If you are using more than one device on the SIP lines, each one needs it’s own pin.

    You also said:-
    As I see it, for the 23LC1024, you would call SPI.setDataMode(mode),
    No you would write to mode into the mode register of the 23LC1024. The instruction 0x01 writes to the mode register, you would write 0x80 to get it into page mode, 0x40 for sequence mode (default) and 0x00 for byte mode.

  7. alex says:

    Hi, i’m working on an instructable article on the basics of interfacing with SRAM, would it be acceptable to use your code, with attribution, in my writeup? your code is way better than mine, and probably makes more sense.

  8. Daemon says:

    First of all: Thanks for the code. It’s forming the basics for a somewhat bigger project (on a Parallax Propeller) and it really shows the basic principles. 🙂

    I also have some feedback: controlling 1 chip is trivial in this way. However: I added a second chip to the SPI bus, with its own SS line to pin 9 of the Arduino. The chip to pin 10 of the arduino kept working, but the one to pin 9 (PORTB1) was not. Doing snooping around with an old scope (that thankfully had a trigger option) I noticed that the SS for chip 2 was never going to ‘0’. At first I couldn’t figure out how, but then it hit me: Your code never sets the pinmodes for the pins.
    Adding
    pinMode(9, OUTPUT);
    pinMode(10, OUTPUT);
    to the setup function solved the problem… I’m not entirely sure why it worked at all without it. But apparently for some reason pin 10 is output by default, but pin 9 isn’t.

    • Grumpy_Mike says:

      It is the SPI library that sets up pin 10 to be an output, so you only need to set the pin mode on pin 9.

  9. Sahra says:

    Hi, thank you so much for your little tutorial, it helped me out a lot!
    I just have one small, maybe silly question, but i cant seem to figure it out: but why do you write uint8_t address>>16 and then uint8_t address>>8 why not 24 all together, as in uint8_t address>>24? Why does it have to be that way in other words?

    Again, thank you a lot.

    • Jim Eli says:

      The 23LC1024 datasheet requires a 3-byte (24-bits) memory address. The address is sent to the chip in 3 separate bytes, high, middle then low. If one wants bits 16 through 23 transferred into a byte, you shift the value by 16. If you want bits 8 through 15, you shift it by 8 and the low 8 bits don’t require any shift at all. If you shifted the address by 24, it would shift all 24-bits completely out of the address variable.

  10. Hello Jim,

    I have been working on a project similar to the one above, however, i would like to explore connecting ‘n’ SRAMS to the Arduino Uno via. a demultiplexer/decoder, specifically SN74HC138. It has 3 inputs which you can set high or low very easily on the Arduino, and 8 outputs, which go high or low accordingly. This seems like a good intermediate chip to use to control many SRAMS, and perform read/write operations while still being connected to the Arduino.
    However, after having connected the SRAMS up and the decoder, I notice constant garbage values and zeros, where instead I’d like to see what I’d written.

    Do you know why this would happen?

    Thank you for your help.

    Sahra

    • Jim Eli says:

      Sahara,

      My bet is you are experiencing a hardware/wiring issue. However, I must ask, why complicate matters with multiplexer chip? Why not share the bus lines between SRAM chips and address individually with separate CS lines? Good luck.

      Jim

    • Grumpy_Mike says:

      “Since the 23LC1024 is tolerant of 5V logic levels”
      That phrase normally means they can withstand 5V even if the supply to that chip is lower. This is not the case with this chip. The signals must be no more than 0.3V above the voltage you use to power the chip.

      In order to help out with the problem Sahra has we would need to see a schematic and photograph of the hardware along with some simple code that shows this problem.

Leave a comment