Forum: Mikrocontroller und Digitale Elektronik Serielles EEPROM über I2C auslesen


von C. B. (catwiesl1000)


Lesenswert?

Hallo.

Ich möchte ein serielles 256 Byte EEPROM über I2C per random read 
(beliebige Speicherzelle) mit dem ATMEGA8 auslesen. Das Schreiben 
funktioniert soweit.

Der Lesevorgang klappt allerdings nur ein einziges mal. Starte ich einen 
zweiten Lesevorgang, um ein weiteres Byte zu lesen, "hängt" der uC.

Soweit ich das beurteilen kann, müsste das Problem in der while-Schleife 
beim Senden der Start-Bedingung i2c_start() liegen. Stimmt das? Wie 
lässt sich das Problem lösen?


Im folgenden der Code:
1
void i2c_start(void)
2
{
3
4
  TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);
5
  while((TWCR & _BV(TWINT)) == 0);
6
}
7
8
void i2c_stop(void)
9
{
10
  TWCR = _BV(TWINT) | _BV(TWSTO) | _BV(TWEN);
11
}
12
13
14
void i2c_send(uint8_t Data)
15
{
16
  TWDR = Data;
17
  TWCR = _BV(TWINT) | _BV(TWEN);
18
  while ((TWCR & _BV(TWINT)) == 0);
19
}
20
21
uint8_t i2c_receive(uint8_t ack)
22
{
23
  if(ack ==1)
24
    TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN);
25
  else
26
    TWCR = _BV(TWINT) | _BV(TWEN);
27
  while((TWCR & _BV(TWINT)) == 0);
28
  return TWDR;
29
}
30
31
//###################################################
32
33
uint8_t ReadRandomByte(uint16_t addr)
34
{
35
    PORTD |= (1 << DDD3);  //Status LED auf High
36
  uint8_t wert;
37
  i2c_start();
38
  i2c_send(BASEADR | TW_WRITE);
39
  i2c_send(addr);
40
  i2c_start();
41
  i2c_send(BASEADR | TW_READ);
42
  wert = i2c_receive(1);
43
  i2c_stop();
44
  PORTD &= ~(1 << DDD3);       //Status LED auf Low
45
  return wert;
46
}

von Klaus W. (mfgkw)


Lesenswert?

Das ist aber nicht das ganze Programm, oder?

>· Bit 5 ­ TWSTA: TWI START Condition Bit
> The application writes the TWSTA bit to one when it desires to
> become a Master on the Two-wire Serial Bus. The TWI hardware
> checks if the bus is available, and generates a START condition
> on the bus if it is free. However, if the bus is not free, the
> TWI waits until a STOP condition is detected, and then generates
> a new START condition to claim the bus Master status.
> TWSTA must be cleared by software when the START condition
> has been transmitted.

Löschst du TWSTA irgendwo auch wieder?

von Klaus W. (mfgkw)


Lesenswert?

Abgesehen davon bin ich mir auch nicht sicher, ob du überhaupt richtig 
liest.

Lt. Datenblatt zum AT24C01A etc. sieht random read so aus:
1
RANDOM READ: A random read requires a "dummy" byte write sequence to load in the data
2
word address. Once the device address word and data word address are clocked in and
3
acknowledged by the EEPROM, the microcontroller must generate another start condition.
4
The microcontroller now initiates a current address read by sending a device address with the
5
read/write select bit high. The EEPROM acknowledges the device address and serially clocks
6
out the data word. The microcontroller does not respond with a zero but does generate a fol-
7
lowing stop condition (see Figure 11 on page 12).

Das kann ich in deiner Leserei nicht wiederfinden.

von Detlev T. (detlevt)


Lesenswert?

Das letzte Byte muss mit einem "NAK" gelesen werden, also
1
wert = i2c_receive(0);

von ingo (Gast)


Lesenswert?

> Das letzte Byte muss mit einem "NAK" gelesen werden

Richtig, steht in den meisten Datenblättern so drin, hab ich aber nie 
gemacht und hat mit den meisten (24c02, 24x04 und 24c16) auch so 
funktioniert, nach der Stopbedingung setzt sich die EEPROM-interne Logik 
wohl auch so zurück.
mfG ingo

von C. B. (catwiesl1000)


Lesenswert?

So funktioniert es:

Detlev T. schrieb:
> Das letzte Byte muss mit einem "NAK" gelesen werden, also
> wert = i2c_receive(0);


Danke für die Antworten!

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.