[aide] EEPROM AT93C46 protocole SPI

Bonjour à tous,
j'ai fais l'acquisition d'EEPROM AT93C46 de marque Atmel tout d'abord voici le Datasheet http://ee-classes.usc.edu/ee459/library/datasheets/AT93C46.pdf

Le protocole utiliser pour communiquer est le SPI (il me pause relativement problème),
Mais avant tout voici quelques informations sur ce qui a déjà été fait,

j'utilise un Arduino Nano et l'ide Arduino 0023,
niveau du brochage voici ce qu'il en est

Arduino | AT93C46
|
pin 10 | CS
pin 13 | SK
pin 11 | DI
pin 12 | DO
GND | GND
5V5 | VCC
GND | ORG (mode 8bit)
aucun | DC

Le problème que je rencontre est que via la libraire SPI.h fournie par Arduino, je ne sais pas comment mi prendre pour recevoir des informations, ni même si c'est possible ?

Voici mon code actuel, je ne suis pas sure de l'initiation des paramètres de base du protocole SPI donc si vous voyer des erreurs signalez-les !

#include <SPI.h>
#define TD 5 // temps d'attente

const int cs = 10;

void Read()//l'ecture
{

}

void Write()//écriture
{

}

void setup()
{
pinMode(cs,OUTPUT);
delay(TD);//temps datente
SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE2);//?
SPI.setClockDivider(SPI_CLOCK_DIV2);// sk 2mhz
delay(TD);
Serial.begin(9600);
}

void loop()
{

}

Salut,

Je vois quelques erreurs dans la configuration du bus SPI :

  • Mode SPI :
    Il faut choisir le mode 0. Au repos l'horloge est à 0 (CPOL = 0). De plus, les données sont prises en compte sur un front montant de l'horloge (CPHA = 0).

  • Fréquence d'horloge :
    La datasheet indique une fréquence de 2 MHz. Le SPI de l'Arduino Nano tourne à 16 MHz. Il faut donc diviser cette fréquence par 8.

Sinon pour la partie lecture tu trouveras surement ton bonheur ici : Tutorial: Arduino and the SPI bus part II | tronixstuff.com

Merci de m'avoir signaler les erreurs d'initiation,

Sinon le lien poster par B@tto est très intéressent,

Mais lorsque je tente d'enregistrée une valeur et ensuite de la lire sa ne fonctionne pas la variable qui est censé réceptionner les données reste a 0,

Voici le code actuel.

#include <SPI.h>
#define TD 5 // temps d'attente

const int cs = 10;
int data=0;

void Read()//l'ecture
{
delay(TD);
digitalWrite(cs,LOW);
SPI.transfer(2); // opcode binaire 10
SPI.transfer(1); // adresse
data = SPI.transfer(0); // reception
digitalWrite(cs,HIGH);
}

void Write()//écriture
{
delay(TD);
digitalWrite(cs,LOW);
SPI.transfer(1); // opcode binaire 01
SPI.transfer(1); // adresse 0x01
SPI.transfer(9); // envois 0x09
digitalWrite(cs,HIGH);
}

void setup()
{
pinMode(cs,OUTPUT);
delay(TD);//temps datente
SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);// mode 0. Au repos l'horloge est à 0 (CPOL = 0). les données sont prises en compte sur un front montant de l'horloge (CPHA = 0).
SPI.setClockDivider(SPI_CLOCK_DIV8);// sk 2mhz, 16 MHz diviser par 8.
delay(TD);
Serial.begin(9600);
}

void loop()
{
Write();
Read();

Serial.println(data);
delay(1000);
}

Bonjour,

lacolombenoir:
Le problème que je rencontre est que via la libraire SPI.h fournie par Arduino, je ne sais pas comment mi prendre pour recevoir des informations, ni même si c'est possible ?

Heureusement que c'est possible sinon on seraient bien embêter :wink:

Pour lire quelque chose en SPI il suffit d'écrire quelque chose, des 0x00 par exemple.
Ces octets "poubelles" servent juste à avoir les fronts d'horloge pour que l'esclave SPI puisse répondre.

Exemple :

byte val = SPI.write(0x00);

Par contre pour lire des données depuis une EEPROM SPI il faut aussi respecter le protocole de communication de celle ci (voir datasheet).
Exemple: http://www.arduino.cc/en/Tutorial/SPIEEPROM

Dans le dernier lien il n'utilise pas la libraire spi.h, donc au final es que c'est possible d'utiliser cette librairie sur le AT93C46 ?

Et je ne vois nul part de protocole pour l'utilisation de l'eeprom sur le datasheet,

Pour rien vous cachez je suis assez perdu.

J'ai trouver ce document venant d'Atmel sur la page du AT93C46, http://www.atmel.com/Images/doc8546.pdf

il donne l'ordre dans le quelle envoyer les valeur via SPI pour read et write,

Write Operation:
Enable device via chip select low
Send write enable op code
Disable device via chip select high
Enable device via chip select low
Send write op code with address
Send data byte(s) for byte write or page write
Disable device via chip select high to start write cycle

Read Operation:
Enable device via chip select low
Send read op code with address
Receive data byte(s)
Disable device via chip select high

Pour read voici le code que j'imagine

digitalWrite(cs,LOW);
  SPI.transfer(B10000110); // opcode binaire 10 suivi d'une adresse
  int data = SPI.transfer(0);   
  digitalWrite(cs,HIGH);

Avec ce code j'obtiens toujours 0 même si ma variable est initialiser a 1 ( ses un bon debut :blush: )

Par contre l'écriture rien a faire j'ai tester tout ce que j'ai cru comprendre mais rien ne fonctionne, je compte sur vous pour m'aider a écrire dans l'eeprom car je suis a bout de souffle.

Salut,

La mémoire AT93C46 n'est pas en SPI, mais en 3-Wire (3WI dans ta doc). La principale différence est que le Chip Select est inversé. Je précise que tu peux toutefois utiliser la bibliothèque SPI d'Arduino...

Dans ton cas, la lecture se fait de cette manière :

Read Operation:
Enable device via chip select high
Send read op code with address
Receive data byte(s)
Disable device via chip select low

Dans ton code, il te suffit donc d'inverser les niveaux de cs.

++

Merci pour l'information mais le résultat est le même.

Qu'est-ce qui te fait dire que la lecture ne fonctionne pas ? Sais-tu ce que tu es censé lire alors que tu n'as rien écrit dans la mémoire ?

Et bien je n'en sais rien, si seulement tout les essais que j'ai fais pour l'écriture avais fonctionner peu être que j'aurais pu vérifier si la lecture fonctionnais

Write Operation:
Enable device via chip select high
Send write enable op code
Disable device via chip select low
Enable device via chip select high
Send write op code with address
Send data byte/word
Write cycle begins
Disable device via chip select low

Voila mon dernier code pour la lecture

digitalWrite(cs,HIGH);
  SPI.transfer(B01); // opcode binaire 01
  digitalWrite(cs,LOW);
  digitalWrite(cs,HIGH);
  SPI.transfer(B01000110); // opcode binaire 01
  SPI.transfer(B00000111);
  digitalWrite(cs,LOW);

lacolombenoir:
Et bien je n'en sais rien, si seulement tout les essais que j'ai fais pour l'écriture avais fonctionner peu être que j'aurais pu vérifier si la lecture fonctionnais

...

bonjour
ça ne resoud pas ton probleme, mais lire çà :

il semblerait que la 93C46 pose des problemes/questions sous pas mal d'environnements

When I read the Erase command from AT93C46 as shown below:

ERASE (ERASE): The Erase (ERASE) instruction programs all bits in the specified
memory location to the logical “1” state. The self-timed erase cycle starts once the
ERASE instruction and address are decoded. The DO pin outputs the READY/BUSY
status of the part if CS is brought high after being kept low for a minimum of 250 ns (tCS). A logic “1” at pin DO indicates that the selected memory location has been erased, and the part is ready for another instruction.

Am I right that when erase process completes, all of bits in DOUT indicates "1" states?

The reason that I asked about this is that everytime I erase the data and read the same address and 0xFF which is completely opposite to what I expected because I expected to receive 0x00 instead of 0xFF. Unless there is problem in my erase_command function prototype!

lacolombenoir:
Voila mon dernier code pour la lecture

digitalWrite(cs,HIGH);

SPI.transfer(B01); // opcode binaire 01
  digitalWrite(cs,LOW);
  digitalWrite(cs,HIGH);
  SPI.transfer(B01000110); // opcode binaire 01
  SPI.transfer(B00000111);
  digitalWrite(cs,LOW);

Il ne manquerait pas quelques bits au premier envoi ? Car là c'est comme si tu envoyais B00000001 et non pas B01000000.

++

J'ai remplacer B01 par ta proposition et toujours aucun changement,
Je commence a croire que je suis tomber sur tomber sur le pire modèle d'eeprom que je pouvais rencontré,
Je pensais que du faite que sa soit de marque Atmel je risquais rien, c'était bien ma vaine dans commander 100 :stuck_out_tongue_closed_eyes: heureusement que sa ma couter que 14 euro :*

Non mais la y'a des gros soucis dans le code, pourquoi envoyer 01 avant ? Deja quelle organisation as-tu choisi : 8 ou 16 bit ?

Ensuite ton code devrait plus ressembler à ça (en mode 8 bits):

#include <SPI.h>

const int cs = 10;
int data=0;

void Read(int adresse)//lecture
{
long Command=0b110<<7;
Command&=adresse;
digitalWrite(cs,LOW);
delaymicroseconds(10);
 SPI.transfer(Command);
data=SPI.tranfer(0);
digitalWrite(cs,HIGH);
}

void Write(int adresse,int donnees)//écriture
{
long Command=0b101<<7;
Command&=adresse;
Command<<8;
Command&=donnees;
  digitalWrite(cs,LOW);
delaymicroseconds(10);
  SPI.transfer(Command);
  digitalWrite(cs,HIGH);
}

}

void setup()
{
  pinMode(cs,OUTPUT);
 digitalWrite(cs,HIGH);
   
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0);// mode 0. Au repos l'horloge est à 0 (CPOL = 0). les données sont prises en compte sur un front montant de l'horloge (CPHA = 0).
  SPI.setClockDivider(SPI_CLOCK_DIV8);// sk 2mhz, 16 MHz diviser par 8.
  SPI.begin();
  Serial.begin(9600);
}

void loop()
{
  Write(50,100);
  Read(50);
  
  Serial.println(data);
  delay(1000);
}

J'ai indiquer dans le premier poste que je travaillais en 8 bit,

Sinon dans ton code ne donne pas plus de résultat, et tu a inverser l'état des broche cs vu que ses du wire 3,
J'ai découvert qu'il y avais une autre appelle a faire lors de wire

Write Operation:
Enable device via chip select high
Send write enable op code ******************************
Disable device via chip select low
Enable device via chip select high
Send write op code with address
Send data byte/word
Write cycle begins
Disable device via chip select low

La ligne que j'ai indiquer fait référence a

EWEN |1|00|11XXXXX|11XXXX| Write enable must precede all |
programming modes

dans le datasheet

Sinon grand merci a B@tto car tu ma fais découvrir l'utilisation de Bitwise Operators,
Je vais continuer de m'acharner pour faire fonctionner cette eeprom.

j'ai travailler sur la base de ton code, voici se que j'ai obtenu

void Read(int adresse)//lecture
{
long Command=0b110<<7;
Command|=adresse;
Serial.print("  ");
Serial.println(Command,BIN);
digitalWrite(cs,HIGH);
delay(10);
SPI.transfer(Command);
data=SPI.transfer(0);
digitalWrite(cs,LOW);
}

void Write(int adresse,int donnees)//écriture
{
long Command=0b010<<8;
 Command|=adresse;
 Serial.print(Command,BIN);
 Serial.print("  ");
 digitalWrite(cs,HIGH);
 delay(10);
  SPI.transfer(Command);
  SPI.transfer(donnees);
  digitalWrite(cs,LOW);
}

j'ai donc ceci qui s'affiche

1000110010 1100110010
247
247
247
...

théoriquement il devrais m'envoyer 100 comme valeur, donc si quelqu'un a une explication ?

A mon avis ça vient de la le problème

SPI.transfer(Command);
  SPI.transfer(donnees);

imagine du envoi la donnée 2 : ça va faire 10 au lieu de 00000010
Il faut faire comme je l'avais fait, décaler command et ajouter données et envoyer le tout

J'ai refait le code mais cette fois si en rajoutent Ewen qui est a mettre selon la documentation et toujours aucun changement.

void Write(int adresse,int donnees)//écriture
{
long Ewen = 0b0011000000;

long Command=0b010<<8;
 Command|=adresse;
 Command<<=8;
 Command|=donnees;
 Serial.print(Command,BIN);
 Serial.print("  ");
 digitalWrite(cs,HIGH);
 delay(10);
  SPI.transfer(Ewen);
  SPI.transfer(0x01);
  digitalWrite(cs,LOW);
 digitalWrite(cs,HIGH);
 delay(10);
  SPI.transfer(Command);
  digitalWrite(cs,LOW);
}

Voici ce que j'ai dans la console.

100011000101100100 1100110001
247
247
247
...

Une lecture attentive de la doc de l'EEPROM et de la doc de la librairie SPI montre que les deux ne peuvent pas coucher ensemble.
L'EEPROM attend des paramètres sur 10bits en entrée alors que la méthode transfer() de la librairie SPI manipule des octets
Il va falloir que tu écrives ta propre librairie pour supporter ta mémoire. C'est pas super compliqué mais par contre tu ne pourras pas utiliser le SPI matériel. Du coup cela te permets de connecter la mémoire sur n'importe quelle IO.
En fait, il faut bien voir, que le SPI n'est pas du tout standardisé comme l'I²C ou le RS232 par exemple. Et du coup chaque fabricant l'implémente comme il l'entend. Utiliser le SPI c'est un peu partir à l'aventure. Alors laisse s'exprimer l'explorateur qui dort en toi.....