jeudi 5 janvier 2012

SDE2516

Utilisation de l'EEPROM SDE2516 récupéré dans un vieil autoradio.



Ce composant fonctionne avec un bus I2C qui est constitué de 2 fils : Horloge et Données. Plus d'info sur la Wiki. Le SDE2516 est une mémoire non volatile de 128 octets.

Je n'ai pas pu le faire fonctionner avec la bibliothèque Wire du Arduino qui est destinée à la communication grâce au bus I2C. Un exemple d'utilisation de cette librairie est dispo sur le Playground avec le composant AT24C256.

Ainsi j'ai préféré me passer de la librairie et refaire à la main les changements d'état des entrées Horloge et Données, tels qu'ils sont décrits dans le datasheet du SDE2516.


Les branchements sont très simples :
Arduino <=> SDE2516
PIN5 <=> SDA
PIN6 <=> SCL
5V <=> VDD
GND <=> VSS
GND <=> CS0
GND <=> CS1
GND <=> CS2



Le programme est constitué d'une fonction par type de bloc de données : Start, Stop, écriture d'un octet, lecture d'un octet, écriture de l'accusé de réception (acknowledge), lecture de l'accuser de réception.
Ensuite des fonctions plus globales appellent ces sous-fonctions de protocole : write_byte, read_byte, write_string, read_string.


Programme

const int SDA_PIN = 5;
const int SCL_PIN = 6;

const int DELAI = 2;
const int DELAI_ECRITURE = 15;

byte CSE = B10100000; //Adresse du composant pour l'écriture
byte CSA = B10100001; //Adresse du composant pour la lecture

// Ecriture START
void write_ST() {
  digitalWrite(SCL_PIN, HIGH);
  digitalWrite(SDA_PIN, HIGH);
  delay(DELAI);
  digitalWrite(SDA_PIN, LOW);
  delay(DELAI);
  digitalWrite(SCL_PIN, LOW);
  delay(DELAI);
}

// Ecriture d'un octet
void write_BYTE(byte mot) {
  for(int i=0;i<8;i++) {
    int val = (mot & 128) >> 7;
    digitalWrite(SDA_PIN, val);
    delay(DELAI);
    digitalWrite(SCL_PIN, HIGH);
    delay(DELAI);
    delay(DELAI);
    digitalWrite(SCL_PIN, LOW);
    delay(DELAI);
    mot = mot << 1;
  }
}

// Ecriture du bit de l'accusé de réception
void write_AS(boolean etat) {
  digitalWrite(SDA_PIN, etat);
  delay(DELAI);
  digitalWrite(SCL_PIN, HIGH);
  delay(DELAI);
  delay(DELAI);
  digitalWrite(SCL_PIN, LOW);
  delay(DELAI);
  digitalWrite(SDA_PIN, LOW);
}

// Lecture de l'accusé de réception
boolean read_AS() {
  pinMode(SDA_PIN, INPUT);
  delay(DELAI);
  digitalWrite(SCL_PIN, HIGH);
  delay(DELAI);
  int val = digitalRead(SDA_PIN);
  delay(DELAI);
  digitalWrite(SCL_PIN, LOW);
  delay(DELAI);
  pinMode(SDA_PIN, OUTPUT);
  if(val == 0) return false;
  Serial.println("ERREUR AS");
  return true;
}

// Ecriture STOP
void write_SP() {
  digitalWrite(SCL_PIN, LOW);
  digitalWrite(SDA_PIN, LOW);
  delay(DELAI);
  digitalWrite(SCL_PIN, HIGH);
  delay(DELAI);
  digitalWrite(SDA_PIN, HIGH);
  delay(DELAI);
}

// Lecture d'un octet
byte read_DA() {
  byte res = 0;
  pinMode(SDA_PIN, INPUT);
  for(int i=0;i<8;i++) {
    delay(DELAI);
    digitalWrite(SCL_PIN, HIGH);
    delay(DELAI);
    int val = digitalRead(SDA_PIN);
    if(i != 0) res = res << 1;
    if(val == 1) res += 1;
    else if(val != 0) Serial.println("ERREUR DA");
    delay(DELAI);
    digitalWrite(SCL_PIN, LOW);
    delay(DELAI);
  }
  pinMode(SDA_PIN, OUTPUT);
  return res;
}

// Fonction de lancement de la séquence I2C d'écriture d'un octet
void write_byte(byte adresse, byte mot) {
  write_ST();
  write_BYTE(CSE);
  read_AS();
  write_BYTE(adresse);
  read_AS();
  write_BYTE(mot);
  read_AS();
  write_SP();
  delay(DELAI_ECRITURE);
}

// Fonction de lancement de la séquence I2C de lecture d'un octet
byte read_byte(byte adresse) {
  write_ST();
  write_BYTE(CSE);
  read_AS();
  write_BYTE(adresse);
  read_AS();
  write_ST();
  write_BYTE(CSA);
  read_AS();
  byte a = read_DA();
  write_AS(HIGH);
  write_SP();
  return a;
}

// Ecriture d'une chaine de caractère sur l'EEPROM
void write_string(char* string) {
  int i=0;
  while(string[i] != '\0' && i < 128) {
    write_byte(i,string[i]);
    i++;
  }
  write_byte(i,'\0');
}

// Lecture d'une chaine de caractère sur l'EEPROM
char* read_string() {
  char* res = (char*)malloc(128);
  int i=0;
  char car = read_byte(i);
  while(car != '\0' && i < 128) {
    res[i] = car;
    i++;
    car = read_byte(i);
  }
  res[i] = car;
  return res;
}

void setup()
{
  Serial.begin(9600);
  pinMode(SCL_PIN, OUTPUT);
  pinMode(SDA_PIN, OUTPUT);

  // écriture d'une valeur à une adresse
  write_byte(3,42);
  byte val = read_byte(3);
  Serial.println(val,DEC);

  // écriture d'une chaine de caractère
  write_string("SDE2516 dit Bonjour.");
  char* string = read_string();
  Serial.println(string);
}


void loop()
{
  delay(2000);
}

Aucun commentaire:

Enregistrer un commentaire