Hey, guys. I have an Arduino Micro that I'm trying to use to program a bunch of EEPROMs I'm going to use in a digital circuit build. I'm currently working on programming the first EEPROM, but it's not programming as expected.
The problem:
What is supposed to happen in the code below is the first 4 addresses in the EEPROM should be written to with the data in setup() (0x69 0x55 0xAA 0x0D)
. However, when I read the EEPROM, it shows 0xFF 0xFF 0xFF 0x0D
is programmed. I have verified this in my digital circuit build, so I know that my program is properly reading the EEPROM.
If I only program the first 3 bytes in the EEPROM (addresses 0, 1, & 2), it writes 0xFF 0xFF 0xAA
. This tells me that only the last byte is actually being written. I'm not sure why this is, so I'm hoping someone can help me.
The hardware:
Arduino Micro w/ micro-USB cable.
3 74HC595 chips (8-bit shift registers) for the address lines (17-bit address on this EEPROM). Link to data sheet.
1 Greenliant GLS29EE010 EEPROM. 17-bit addresses, 8-bit data per address. Link to data sheet.
The EEPROM does have Software Data Protection and a Page-Write capability. I don't know if those are inhibiting me or even how to use them. The way the data sheet reads makes me think I should be able to just write to the EEPROM 1 byte at a time like I am trying.
The way I have the circuit hooked up is:
The shift registers are wired to the address lines of the EEPROM.
The data lines of the EEPROM are connected directly to the Arduino Micro.
The code:
#define EEPROM_D0 2 // data LSB
#define EEPROM_D7 9 // data MSB
#define SHIFT_DATA 10 // data to shift into shift register
#define SHIFT_CLK 11 // pos-edge clock for shift register
#define DFF_CLK 12 // pos-edge clock for DFF to set after filling shift register
#define SHIFT_CLR 13 // active-low async clear for shift registers
#define EEPROM_READ_EN A0 // active-low EEPROM read enable
#define EEPROM_WRITE_EN A1 // active-low EEPROM write enable
void setup() {
// put your setup code here, to run once:
Serial.begin(300);
while (!Serial) { delay(10); }
// Write some data
setPinsToDefaultForWriting();
writeEEPROM(0, B01101001); // 0x69
writeEEPROM(1, B01010101); // 0x55
writeEEPROM(2, B10101010); // 0xAA
writeEEPROM(3, B00001101); // 0x0D
// Check what was written
setPinsToDefaultForReading();
byte data[] = { readEEPROM(0), readEEPROM(1), readEEPROM(2), readEEPROM(3) };
char buf[80];
sprintf(buf, "Read data: %02x %02x %02x %02x", data[0], data[1], data[2], data[3]);
Serial.println(buf);
}
void loop() {
// put your main code here, to run repeatedly:
// This code just keeps the Arduino Micro running so I can check voltages with a multimeter.
// Not sure if it's actually needed in order to maintain whatever voltages, but it's not doing any harm.
digitalWrite(LED_BUILTIN, HIGH);
Serial.println("ON");
delay(3000);
digitalWrite(LED_BUILTIN, LOW);
Serial.println("OFF");
delay(3000);
}
/*
* Sets all the pins for writing to the EEPROM. Still have to manually handle EEPROM_WRITE_EN for writing.
* No delay in this function.
*/
void setPinsToDefaultForWriting()
{
for (int pin = EEPROM_D0; pin <= EEPROM_D7; pin++) // for each data pin
{
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
}
pinMode(SHIFT_DATA, OUTPUT);
digitalWrite(SHIFT_DATA, LOW);
pinMode(SHIFT_CLK, OUTPUT);
digitalWrite(SHIFT_CLK, LOW);
pinMode(DFF_CLK, OUTPUT);
digitalWrite(DFF_CLK, LOW);
pinMode(SHIFT_CLR, OUTPUT);
digitalWrite(SHIFT_CLR, HIGH);
pinMode(EEPROM_READ_EN, OUTPUT);
digitalWrite(EEPROM_READ_EN, HIGH);
pinMode(EEPROM_WRITE_EN, OUTPUT);
digitalWrite(EEPROM_WRITE_EN, HIGH);
}
/*
* Sets all the pins for reading from the EEPROM. Still have to manually handle EEPROM_READ_EN for writing.
* No delay in this function.
*/
void setPinsToDefaultForReading()
{
for (int pin = EEPROM_D0; pin <= EEPROM_D7; pin++) // for each data pin
{
pinMode(pin, INPUT);
}
pinMode(SHIFT_DATA, OUTPUT);
digitalWrite(SHIFT_DATA, LOW);
pinMode(SHIFT_CLK, OUTPUT);
digitalWrite(SHIFT_CLK, LOW);
pinMode(DFF_CLK, OUTPUT);
digitalWrite(DFF_CLK, LOW);
pinMode(SHIFT_CLR, OUTPUT);
digitalWrite(SHIFT_CLR, HIGH);
pinMode(EEPROM_READ_EN, OUTPUT);
digitalWrite(EEPROM_READ_EN, HIGH);
pinMode(EEPROM_WRITE_EN, OUTPUT);
digitalWrite(EEPROM_WRITE_EN, HIGH);
}
/*
* Sets the shift registers values so they contain the address. They will be sending the EEPROM this address
* after this function is called. No delay in this function.
*
* Note: MAKE SURE YOU CALL setPinsToDefaultForReading() OR setPinsToDefaultForWriting() BEFORE CALLING THIS FUNCTION.
* This function does not make sure the pins are set properly.
*/
void setAddress(unsigned long address)
{
// address can have 17 bits of important info, but int is only 16 bits long, so have to use long.
// long is 32 bits.
shiftOut(SHIFT_DATA, SHIFT_CLK, LSBFIRST, (address)); // Outputs XXXX XXXX (bits 0-7)
shiftOut(SHIFT_DATA, SHIFT_CLK, LSBFIRST, (address >> 8)); // Outputs XXXX XXXX (bits 8-15)
shiftOut(SHIFT_DATA, SHIFT_CLK, LSBFIRST, (address >> 16)); // Outputs 0000 000X (bits 16-23)
digitalWrite(DFF_CLK, HIGH);
digitalWrite(DFF_CLK, LOW);
}
/*
* Writes to the EEPROM. Does delay after the write to ensure the contents are actually saved.
*
* Note: MAKE SURE YOU CALL setPinsToDefaultForWriting() BEFORE CALLING THIS FUNCTION.
* This function does not make sure the pins are set properly.
*/
void writeEEPROM(unsigned long address, byte data)
{
// Set up the address and data
setAddress(address);
for (int pin = EEPROM_D0; pin <= EEPROM_D7; pin++) // for each data pin
{
digitalWrite(pin, data & 1);
data = data >> 1;
}
// Perform the write
digitalWrite(EEPROM_WRITE_EN, LOW);
digitalWrite(EEPROM_WRITE_EN, HIGH);
delay(20); // datasheet says write takes max of 10 ms
}
/*
* Reads from the EEPROM. No delay in this function.
*
* Note: MAKE SURE YOU CALL setPinsToDefaultForReading() BEFORE CALLING THIS FUNCTION.
* This function does not make sure the pins are set properly.
*/
byte readEEPROM(unsigned long address)
{
// Set up the address
setAddress(address);
// Perform the read
digitalWrite(EEPROM_READ_EN, LOW);
byte data = 0;
for (int pin = EEPROM_D7; pin >= EEPROM_D0; pin--) // for each data pin in reverse
{
data = (data << 1) + digitalRead(pin);
}
digitalWrite(EEPROM_READ_EN, HIGH);
return data;
}