I2C EEPROM

Pavel Hudecek edizon na seznam.cz
Pondělí Říjen 8 13:50:57 CEST 2012


Tak asi půjdu koupit novou a pro jistotu ještě nějakou další, tentokrát 
třeba s SPI:-)

Chová se stále stejně, tzn. pokud je správná adresa na I2C, odpovídá 0 při 
ACK. Při čtení čte všude 255, akorát na adresách 3 a 5 je 161. Vypadá to, 
jako kdyby prostě "jen" nezapisovala. Na vývodu WP jsem zkoušel nezapojeno, 
0, i 1, ale vždy stejný výsledek.

Funkce i2cByteR a i2cByteW používá i převodník MCP3426 a funguje.

Při čtení:

    at24adr(0,1);
    dispInt(i2cAck);

    dispInt(at24rdB());    dispInt(at24rdB());
    dispInt(at24rdB());    dispInt(at24rdB());
    dispInt(at24rdB());    dispInt(at24rdB());
    dispInt(at24rdB());    dispInt(at24rdB());

vyleze:
0 255 255 255 161 255 161 255 255 ...
při jiné počáteční adrese se posunou pozice, na kterých je 161.

při zápisu:

    dispInt(at24wrB(0,100)); delay_ms(6);

    dispInt(at24wrB(1,101)); delay_ms(6);

    dispInt(at24wrB(2,102)); delay_ms(6);

    dispInt(at24wrB(3,103)); delay_ms(6);

vyleze:
0 0 0 0

Stejný výsledek je, i když vynechám čekání mezi zápisy.

#define MCP_adr  0b11010000
#define MCP_wait delay_us(2);
#define AT24_adr 0b10100000

SDA_dir je bit z DDR registru od portu s SDA
SDA_in je bit z PIN registru od portu s SDA
SCL_dir je bit z DDR registru od portu s SCL

unsigned char i2cImp(unsigned char b) { // poslat/precist bit
  unsigned char i;
  SDA_dir=!b;  MCP_wait
  SCL_dir=0;  MCP_wait
  i=SDA_in;
  SCL_dir=1;
  return i;
}

void i2cStart() {
  SDA_dir=1;    MCP_wait
  SCL_dir=1;    MCP_wait
}

void i2cStop() {
  MCP_wait
  SCL_dir=0;  MCP_wait
  SDA_dir=0;  MCP_wait
}

void i2cByteW(unsigned char b) {  // zapis bytu do I2C
  unsigned char n;
  for (n=7; n<8; n--) {
    i2cImp(b&(1<<n));
    MCP_wait
  }
  i2cAck=(i2cAck<<1)+i2cImp(1);
}

unsigned char i2cByteR(unsigned char a) {
 // cteni bytu z I2C, jako parametr ACK
  unsigned char n, b=0;
  for (n=7; n<8; n--) {
    b=b<<1;
    b|=i2cImp(1);
    MCP_wait
  }
  i2cImp(a);
  return b;
}

unsigned char at24adr(unsigned short a, unsigned char s) {
 // adresa, stop ano/ne, vraci 3x ack
  i2cStart();
  i2cAck=0;
  i2cByteW(AT24_adr+0);
  i2cByteW((unsigned char)(a>>8));
  i2cByteW((unsigned char)(a & 255));
  if (s==1) i2cStop();
  return i2cAck;
}

unsigned char at24wrB(unsigned short a, unsigned char b) {
  // zapsat 1 B do eeprom, vraci 4x ack
  at24adr(a,0);
  i2cByteW(b);
  i2cStop();
  return i2cAck;
}

unsigned char at24rdB() {  // cteni 1 B z eeprom
  unsigned char n, b=0;
  i2cStart();
  i2cByteW(AT24_adr+1);
  b=i2cByteR(0);
  i2cStop();
  return b;
}

Děkuji,
PH

From: "Pavel Hudecek" <edizon na seznam.cz>
mám subj, přesněji řečeno AT24C256C-SSHL-B.
S ní komunikuje ATmega8. Na lince je zároveň AD převodník, ten funguje.
EEPROM se také tváří funkčně. Po zápisu z ní vyleze ACK. Čtení taky skončí
úspěšně.

Jenže ať zapíšu cokoli, kamkoli, stejně přečtu všude 255, jen na adresách 3
a 5 se nachází 161. Zajímavé také je, že i když je zvenku zapnuté WP, po
zápisu přijde ACK, jakoby bylo vše ok.

V čem by mohl být problém? 



Další informace o konferenci Hw-list