Reading and Writing eeprom 95320

Hi guys,

Trying to use the SPIEEPROM tutorial to read and write an eeprom 95320
Key Features
Memory array
Organized as 4096 x 8 bits
32 Kb (4 Kbytes) of EEPROM
Page size: 32 bytes
Write
Byte Write within 5 ms
Page Write within 5 ms
High-speed clock: 20 MHz
Enhanced ESD protection

Serial Clock (C) :This input signal provides the timing of the serial interface. Instructions, addresses, or data
present at Serial Data Input (D) are latched on the rising edge of Serial Clock (C). Data on
Serial Data Output (Q) change from the falling edge of Serial Clock (C).

Datasheet 95320

The tutorial is based on a chip using 16-bits addressing. When reading data from the chip, it passes the read address using 2 separate bytes:

#define DATAOUT 11//MOSI
#define DATAIN  12//MISO 
#define SPICLOCK  13//sck
#define SLAVESELECT 10//ss

//opcodes
#define WREN  6
#define WRDI  4
#define RDSR  5
#define WRSR  1
#define READ  3
#define WRITE 2

byte eeprom_output_data;
byte eeprom_input_data=0;
byte clr;
int address=0;
//data buffer
char buffer [32];


void setup()
{
  Serial.begin(9600);

  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK,OUTPUT);
  pinMode(SLAVESELECT,OUTPUT);
  digitalWrite(SLAVESELECT,HIGH); //disable device
 
 // C'est le registre de controle
  //SPCR = 01110011;
  //interrupt disabled,spi enabled,msb 1st,master,clk low when idle,
  //sample on leading edge of clk,system clock/4 rate (fastest)
  //7 SPIE (Enable Interrupt SPI bit) =0 : Inactivation de l'interruption SPI
  //6 SPE (Enable SPI) =1 : Active le module SPI
  //5 DORD = 0 : Envoie les données en commençant par le bit de poids fort
  //4 MSTR =1 : Configure l'Arduino en mode MAÎTRE
  //3 CPOL= 0 : Configure l'impulsion d'horloge inactive au niveau BAS
  //2 CPHA = 0 : Valide les données sur le front sur le front montant
  //1 SPR1 =0 et SPR0 = 0: Configure la vitesse de communication à 00 = le plus rapide (Fosc/4= 4MHz) 
  //SPCR = (1<<SPE)|(1<<MSTR);
  SPCR = (1<<SPE)|(1<<MSTR)|(0<<CPHA)|(1<<SPR1)|(1<<SPR0)(0<<DORD);
  //nous lisons le registre d'état SPI et le registre de donnée SPI dans la variable poubelle clr
  //pour effacer toutes données liées aux exécutions précédentes.
  clr=SPSR;
  clr=SPDR;
  delay(10); 
 /*******************************************************************************************************************************/
 //Ici, nous remplissons notre tableau de données avec des nombres et envoyons une instruction d'écriture à l'EEPROM. 
 //L'EEPROM DOIT ETRE ACTIVEE EN ECRITURE avant toute instruction d'écriture. 
 
 //Pour envoyer l'instruction, nous mettons la ligne SLAVESELECT au niveau bas, pour activer la mémoire EEPROM externe, puis nous envoyons l'intruction 
 //en utilisant la fonction spi-transfer (voir ci-dessous). Noter que nous utilisons l'opcode WREN que nous avons défini au début du programme. 
 //Puis nous remettons le ligne SLAVESELECT à nouveau au niveau HAUT : 
 
 //fill buffer with data
  fill_buffer();
  //fill eeprom w/ buffer
  digitalWrite(SLAVESELECT,LOW);
  spi_transfer(WREN); //write enable
  digitalWrite(SLAVESELECT,HIGH);
  
/*******************************************************************************************************************************/ 
 // A présent, nous mettons la ligne SLAVESELECT au niveau BAS pour sélectionner la mémoire EEPROM externe après une brève pause. 
 // Nous envoyons une instruction WRITE pour indiquer à l'EEPROM que nous allons envoyer une donnée à mettre en mémoire. 
 // Nous envoyons l'adresse 16 bits sur 2 octets pour commencer l'écriture, le bit de poids fort en premier. Puis nous envoyons nos 128 octets de 
 // données depuis notre tableau buffer, un octet après l'autre, sans pause. Finalement, nous remettons la ligne SLAVESELECT à l'état HAUT pour désactiver 
 // la mémoire puis faisons une pause pour permettre à l'EEPROM d'écrire les données :
 
  delay(10);
  digitalWrite(SLAVESELECT,LOW);
  spi_transfer(WRITE); //write instruction
  address=0;
  spi_transfer((char)(address>>8));   //send MSByte address first
  spi_transfer((char)(address));      //send LSByte address
  //write 128 bytes
  for (int I=0;I<32;I++)
  {
    spi_transfer(buffer[I]); //write data byte
  }
  digitalWrite(SLAVESELECT,HIGH); //release chip
  //wait for eeprom to finish writing
  delay(3000); 
  
  // Nous terminons la fonction setup en envoyons le mot "OK" suivi d'un saut de ligne via la connexion série vers l'ordinateur. 
  // De cette façon, si nos données envoyées pour affichage ont une drôle d'allure, nous saurons que ce n'est pas un caprice du port série : 
  Serial.print('O');
  Serial.print('K');
  Serial.print('\n');//debug
  delay(1000);
}

//Dans notre boucle principale loop, nous lisons juste un octet à la fois depuis l'EEPROM et 
//nous l'affichons sur le port série vers l'ordinateur. Nous ajoutons un saut de ligne et une pause pour plus de lisibilité. 
//A chaque passage, la boucle incrément l'adresse de l'EEPROM à lire. 
//Quand l'adresse arrive à 128, 
//nous la réinitialisons à 0 car nous avons rempli uniquement 128 adresses de l'EEPROM avec des données.


void loop()
{
  eeprom_output_data = read_eeprom(address);
  Serial.print(eeprom_output_data,DEC);
  Serial.print('\n');
  address++;
  delay(500); //pause for readability
} 

//La fonction fill_buffer rempli simplement notre tableau de données avec les nombres 0 à 127 à chaque index du tableau. 
//Cette fonction peut être aisément modifiée pour remplir le tableau avec des données significatives pour votre application.
void fill_buffer()
{
  for (int I=0;I<32;I++)
  {
    buffer[I]=I;
  }
}

//La fonction spi-transfer charge les données dans le registre de transmission du module SPI, et démarre ainsi la transmission SPI. 
//Elle regarde ensuite l'état d'un bit du registre d'état, SPIF, pour détecter lorsque la transmission est complète en utilisant un bit de masque.
//Une explication des bits masques peut être trouvée ici. Puis la fonction renvoie toute données reçue de l'EEPROM qui est présente dans le registre de données.
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
}

//La fonction read_eeprom nous permet de lire les données depuis l'EEPROM. 
//Tout d'abord, nous mettons la ligne SLAVESELECT au niveau bas pour activer la mémoire EEPROM. 
//Puis nous transmettons une instruction READ, suivie des 16 bits de l'adresse que nous souhaitons lire, 
//le bit de poids fort en premier. 
//Ensuite nous envoyons un octet factice à l'EEPROM pour la fonction d'envoi des données. 
//Finalement nous remettons la ligne SLAVESELECT au niveau HAUT pour désactiver la mémoire externe après avoir lu un octet, 
//et on renvoie la valeur. 
//Si nous voulons lire plusieurs octets à la fois nous devrons laisser la broche SLAVESELECT au niveau BAS tant que nous répèterons la ligne data=spi-transfer(0xFF);
//jusqu'à 128 fois pour la lecture d'une page complète.


byte read_eeprom(int EEPROM_address)
{
  //READ EEPROM
  int data;
  digitalWrite(SLAVESELECT,LOW);
  spi_transfer(READ); //transmit read opcode
  spi_transfer((char)(EEPROM_address>>8));   //send MSByte address first
  spi_transfer((char)(EEPROM_address));      //send LSByte address
  data = spi_transfer(0xFF); //get data byte
  digitalWrite(SLAVESELECT,HIGH); //release chip, signal end transfer
  return data;
}