23LC1024 manual programming

/*
 * Demo program for accessing Microchip 23lc1023 SPI SRAM chip
 * using low-level bit-banged IO and Arduino environment.
 *
 * Written Sep, 2022 by Bill Westfield
 * Released to the public domain.
 */

#define P_CS 10
#define P_SCK 13
#define P_IN 11
#define P_OUT 12

/*
 *  how big is the memory?  The part numbers usually specify
 *  size in kbits (23lc1024 is 1024 kbits, but we mostly
 *  want bytes for our use.
 */
#define MEMSIZE_BITS (1024UL*1024)      // 1024 kbits
#define MEMSIZE_BYTES (MEMSIZE_BITS/8)  // 8 bits/byte

/*
 * Pick a range of memory addresses for the test step.
 */
#define STARTADDR 0 // (MEMSIZE_BYTES - 123)
#define ENDADDR 123 // (MEMSIZE_BYTES - 50)


/*
 * Top level functions
 */
void writeByte(uint32_t addr, uint8_t data) {
  chipEnable();
  writeInstr(2);
  writeAddr(addr);
  writeData(data);
  chipOff();
}

uint8_t readByte(uint32_t addr) {
  uint8_t inByte = 0;
  chipEnable();
  writeInstr(3);
  writeAddr(addr);
  for (byte i = 0; i < 8; i++) { // read 8 bits
    inByte <<= 1;          // Shift
    inByte |= readBit();   // or in the next bit
  }
  chipOff();
  return inByte;
}

void showMode() {
  chipEnable();
  writeBit(0);  // send command "0x05", one bit at a time for
  writeBit(0);  //   explicit clarity...
  writeBit(0);
  writeBit(0);
  //
  writeBit(0);
  writeBit(1);
  writeBit(0);
  writeBit(1);
  // "Read Mode" command has been sent - now show the results
  Serial.print("\nMode is 0b");
  Serial.print(readBit());  // Likewise, read one bit at a time.
  Serial.print(readBit());
  Serial.print(readBit());
  Serial.print(readBit());
  //
  Serial.print(readBit());
  Serial.print(readBit());
  Serial.print(readBit());
  Serial.print(readBit());
  Serial.println();
  chipOff();
}

void clearBytes(uint32_t start, uint32_t l) {
  uint32_t i;
  for (i = 0; i < l; i++) {
    if ((i & 0xFF) == 0) {
      Serial.print(".");
      if ((i & 0x3FFF) == 0) {
        Serial.println();
      }
    }
    writeByte(start + i, 0);
  }
  Serial.println();
}


/*
 * Low level functions
 */
void writeInstr(uint8_t inst) {
  // Start with bit 7 and write all 8 bits.
  for (uint8_t mask = 1 << 7; mask != 0; mask >>= 1) {
    if (inst & mask) {
      writeBit(1);
    } else {
      writeBit(0);
    }
  }
}
void writeData(uint8_t data) {
  writeInstr(data);  // writing data is the same as writing an instruction!
}

void writeAddr(uint32_t addr) {
  // start with bit 23 and send all 24 bits.
  for (uint32_t mask = 1UL << 23; mask != 0; mask >>= 1) { // 24 bits to write
    if (addr & mask) {
      writeBit(1);
    } else {
      writeBit(0);
    }
  }
}
void chipEnable() {
  digitalWrite(P_CS, LOW);
}
void chipOff() {
  digitalWrite(P_CS, HIGH);
}
void clockHigh() {
  digitalWrite(P_SCK, HIGH);
}
void clockLow() {
  digitalWrite(P_SCK, LOW);
}
void toggleClock() {
  clockHigh();
  clockLow();
}

/*
 * Individual bits are clocked into or out of the RAM
 * on the rising edge of the clock.  The "default" state of
 * clock is low, so writing a bit means setting the data pin,
 * raising the clock, and lowering the clock again for the next bit.
 * Reading a bit means raising the clock, reading the bit, and then
 * lowering the clock again.
 */
void writeBit(bool bitVal) {
  // write the data bit and clock it.
  digitalWrite(P_OUT, bitVal);
  toggleClock();
}

bool readBit() {
  // read bits while clock is high.
  clockHigh();
  bool temp = digitalRead(P_IN);
  clockLow();
  return temp;
}

/*
 * Sketch
 */

void setup() {
  pinMode(P_OUT, OUTPUT);    // Pin initialization
  pinMode(P_IN, INPUT);
  pinMode(P_SCK, OUTPUT); clockLow();
  pinMode(P_CS, OUTPUT);  chipOff();
  Serial.begin(115200);
  Serial.print("\n23LC1024 bit-banged SPI test\n");
  Serial.println("Clearing Memory");
  uint32_t startTime = millis();
  clearBytes(0, MEMSIZE_BYTES);   // zero all of the memory
  Serial.print("(Cleared: ");
  Serial.print((millis() - startTime) / 1000UL);
  Serial.println(" seconds!)");
}

void loop() {
  delay(1000);
  showMode();

  Serial.println("Writing data");
  for (uint32_t addr = STARTADDR; addr < ENDADDR; addr += 5) {
    // write value == address for easy visual check
    writeByte(addr, (uint8_t) addr & 0xff);
    Serial.print(addr);
    Serial.print(": ");
    Serial.println(addr & 0xFF);
  }
  Serial.println("Reading Data");
  for (uint32_t addr = STARTADDR; addr < ENDADDR; addr += 1) {
    uint8_t v = readByte(addr);
    if (v != 0) { // Only show the non-zero values.
      Serial.print(addr);
      Serial.print(": ");
      Serial.println((uint32_t)v);
    }
  }

  Serial.println("Hit any key to run again");
  while (Serial.read() < 0) {
    // wait for key to continue
  }
}
1 Like