-1

I am trying to read a 93lc46b EEPROM chip using Arduino. I am reusing the code from http://owlsan.blogspot.de/2012/10/accessing-93c4693c46n-serial-eeprom.html, except I have modified it for 93lc46b chip, plus I am using Arduino Uno and not Arduino Mega. The problem I am facing is, I get different set of bytes every time I try to read 93lc46b EEPROM chip. I doubt this might be some garbage data. Can you please explain me what and where exactly I am doing something wrong. The modified code snippet is as follows:

#include <avr/io.h>
#include <util/delay.h>

#define CLEAN 0b00000000

#define DDR93LC46B  _SFR_IO8(0x04)
#define PORT93LC46B _SFR_IO8(0x05)
#define PIN93LC46B  _SFR_IO8(0x03)

#define SK 13 
#define DO 12 
#define DI 11 
#define CS 10 

#define READ 0x02 

#define SET_CS PORT93LC46B |= (1 << CS)
#define CLR_CS PORT93LC46B &= ~(1 << CS)

#define SET_SK {PORT93LC46B |= (1 << SK); _delay_us(0.01);}
#define CLR_SK PORT93LC46B &= ~(1 << SK)

#define SET_DI PORT93LC46B |= (1 << DI)
#define CLR_DI PORT93LC46B &= ~(1 << DI)

class SPI_93LC46B {
  private:
    uint8_t Transfer(uint8_t data) {
      SPDR = data;
      while(!(SPSR & (1 << SPIF))); // Wait for SPI interrupt flag
      return SPDR;                  // Return byte gathered from SPI data register
    }
    void Opcode(uint8_t opcode, uint8_t address) {
      SET_CS;
      SPCR &= ~(1 << SPE);               // SPI disable
     _delay_us(1);
      CLR_SK;
      SET_DI;                            // Send start bit
      SET_SK;
      CLR_SK;
      SPCR |= (1 << SPE);         // SPI enable
      Transfer((opcode << 6) | address); // Transmit byte
    }
  public:
    SPI_93LC46B() {
      SPCR =    CLEAN        // Set SPI control register
         & ~(1 << SPIE)  // SPI interrupt disable
         |  (1 << SPE)   // SPI enable
         & ~(1 << DORD)  // MSB first
         |  (1 << MSTR)  // SPI master device
         & ~(1 << CPOL)  // SPI
         & ~(1 << CPHA)  //  mode 0
         |  (1 << SPR1)  // XX/64 MHz
         & ~(1 << SPR0); //  speed
      SPSR =    CLEAN         // Init SPI status register
         & ~(1 << SPI2X); // SPI double speed
      DDR93LC46B =    CLEAN      // Set up inputs/outputs
             |  (1 << SK)  // Serial clock output
             |  (1 << DI)  // Data input (MOSI) output
             |  (1 << CS)  // Chip select output
             & ~(1 << DO); // Data output (MISO) input
      PORT93LC46B |= (1 << DO); // Data output (MISO) high
      CLR_DI;
      CLR_CS;    
      CLR_SK;
     _delay_us(1);
    }
    ~SPI_93LC46B() {
      //
    }
    uint16_t Read(uint8_t address) {
      uint16_t data = 0;
      Opcode(READ, address);              
      CLR_DI;
      SET_SK;                             
      CLR_SK;
      SPCR |=  (1 << CPHA);       
      data = Transfer(0);
      data = (data << 8) | (Transfer(0));
     _delay_us(1);
      CLR_CS;
      CLR_DI;
      SPCR &= ~(1 << CPHA);   
      return data;
   }
};

void setup(void) {
  Serial.begin(115200);
  _delay_ms(100);
  Serial.println("EEPROM writing/reading");
}

void loop(void) {
  Serial.println("new round");
  SPI_93LC46B _93LC46B;
  int i;
  uint16_t data;
  for(i = 0; i < 64; i++) {
    data = _93LC46B.Read(i);
    _delay_ms(50);
    Serial.print(data, HEX);
    Serial.print(" ");
    if((i + 1) % 8 == 0)
      Serial.println();
  }
  _delay_ms(10000);  
}

1 Answer 1

0

This code is over complicated and has a lot of errors. Let us start with the obvious. Look closely at this section. Do you see the error(s)?

#define SK 13 
#define DO 12 
#define DI 11 
#define CS 10 

#define READ 0x02 

#define SET_CS PORT93LC46B |= (1 << CS)
#define CLR_CS PORT93LC46B &= ~(1 << CS)

#define SET_SK {PORT93LC46B |= (1 << SK); _delay_us(0.01);}
#define CLR_SK PORT93LC46B &= ~(1 << SK)

#define SET_DI PORT93LC46B |= (1 << DI)
#define CLR_DI PORT93LC46B &= ~(1 << DI)

The symbols SK, D0, DI, CS seem to be pin numbers but look how they are used in the SET_XX and CLR_XX macros. That is very wrong. They should be the bit numbers in the PORT register instead.

There is more. How about this?

_delay_us(0.01);

What is the intention? _delay_ns(10)??? In any case yet another error.

Cheers!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.