Forum: Mikrocontroller und Digitale Elektronik i2c Problem: Atmega644 & eeprom 24c04


von Till O. (tostermann)


Angehängte Dateien:

Lesenswert?

Hallo,

Ich versuche derzeit von einem Atmega644 über den i2c Bus mit einem 
st24c04 eeprom zu kommunizieren. Dazu verwende ich die i2c Lib von Peter 
Fleury.

Zum test soll, genau wie im Testprogramm, der Wert 0x75 an die Adresse 
0x05 geschrieben werden. Hier der entsprechende Programmteil:
1
// Send TWI Data, if key is pressed
2
if(PINB & (1<<PINB1) )
3
{
4
  unsigned char ret;
5
6
  i2c_init();                             // initialize I2C library
7
8
  // write 0x75 to EEPROM address 5 (Byte Write) 
9
  i2c_start_wait(Dev24C04+I2C_WRITE);     // set device address and write mode
10
  i2c_write(0x05);                        // write address = 5
11
  i2c_write(0x75);                        // write value 0x75 to EEPROM
12
  i2c_stop();                             // set stop conditon = release bus
13
  _delay_us(30);
14
  // read previously written value back from EEPROM address 5 
15
  i2c_start_wait(Dev24C04+I2C_WRITE);     // set device address and write mode
16
17
  i2c_write(0x05);                        // write address = 5
18
  i2c_rep_start(Dev24C04+I2C_READ);       // set device address and read mode
19
20
  ret =  i2c_readNak();                    // read one byte from EEPROM
21
  i2c_stop();
22
23
24
  sprintf((char*)usart_string, "Data: %02x",   // Create twistring
25
  ret);
26
  USART_Transmitstring((char*)usart_string);  // Send usart data
27
  while(PINB & (1<<PINB1)){wdt_reset();}    // Wait till Key is released
28
}

Jetzt das Problem: ret liefert nur die Adresse 0x05 und nicht den Wert 
0x75. Also das Oszi angemacht (Bilder sind im Anhang).

Am Anfang scheint alles ok. Die Startsequenz stimmt, die eeprom ID wird 
mit ACK bestätigt, genauso wie die Adresse 0x05 und der geschriebene 
Wert 0x75. Anschließend, wie programmiert, die Stopsequenz.
Danach ist eine 30µs Pause eingefügt(SCL frequenz 100kHz, wurde aber 
auch schon weniger versucht). Die Länge der Pause ist egal das Problem 
bleibt bestehen:
Wenn der µC den eeprom wieder anspricht, antwortet dieser nicht, das 9. 
Bit wird auf Vcc = 3,3 V gezogen (NACK). Genau so alle andern 
Nachrichten, die der µC raus schickt, alles NACK.

Leider habe ich bisher keine Antwort auf die Lösung des Problems 
gefunden.

Die eeprom Id ist Dev24C04 = 0xA0, die Pins zum einstellen der Id sind 
alle nach gnd verbunden. Es wurde aber auch schon Dev24C04 = 0xA2 
probiert. Keine Änderung des Ergebnisses.
Die Pullup Widerstände haben 3,3 kohm.

Ausprobiert wurde:
- SCL frequenz runter gedreht
- Pause vor dem 2. i2c_start_wait(Dev24C04+I2C_WRITE); erhöht
- verschiedene Id's ausprobiert
- eeprom ausgetauscht

Bin über jede Hilfe / jeden Hinweis dankbar. Hab bisher noch nicht mit 
dem i2c Bus gearbeitet.

Grüße,
Till

von Georg G. (df2au)


Lesenswert?

Nach dem Schreibbefehl sollte das EEProm Zeit haben, das Byte zu 
schreiben. Wo wartest du auf das Ende des Schreibzyklus?

von Till O. (tostermann)


Lesenswert?

>>Nach dem Schreibbefehl sollte das EEProm Zeit haben, das Byte zu
>>schreiben. Wo wartest du auf das Ende des Schreibzyklus?
1
unsigned char i2c_write( unsigned char data )
2
{  
3
    uint8_t   twst;
4
    
5
  // send data to the previously addressed device
6
  TWDR = data;
7
  TWCR = (1<<TWINT) | (1<<TWEN);
8
9
  // wait until transmission completed
10
  while(!(TWCR & (1<<TWINT)));
11
12
  // check value of TWI Status Register. Mask prescaler bits
13
  twst = TW_STATUS & 0xF8;
14
  if( twst != TW_MT_DATA_ACK) return 1;
15
  return 0;
16
17
}/* i2c_write */

Hier wird gewartet, bis der µC mit dem Senden fertig ist.
Das EEProm gönnt sich scheinbar 4ms zu schreiben. Zumindest gibts danach 
endlich das ACK.

Bei mir gibt es noch das Problem, dass der Befehl
1
i2c_rep_start(Dev24C04+I2C_READ);       // set device address and read mode
fehl schlägt, weil TW_STATUS (maskiert) weder TW_MT_SLA_ACK noch 
TW_MR_SLA_ACK ergibt.
Wenn man den Befehl mit einem
1
i2c_start_wait(Dev24C04+I2C_READ);    // set device address and read mode
ersetzt funktioniert der Code.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.