mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Hilfe beim I2C EEPROM Ansteuern mit ATmega8


Autor: Dennis Brücke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi @all,

ich habe jetzt schon so einiges gelesen was I2C (TWI) betrifft, komme
allerdings nicht wirklich weiter. Ich möchte gerne einen EEPROM 24C512
per Software I2C an meinen ATMega8 hängen programmieren tue ich in ASM,
habe jetzt einfach mal folgende fragen:

1. teilweise habe ich gelesen, das es nur über externen PullUp
   geht, teilweise hab ich auch schon gelesen direkt an die Ports
   zu hängen... welches Stimmt jetzt oder Geht beides ?

2. Wie muss ich jetzt den EEPROM Ansprechen ? A0-A3 ist auf GND ?

4. Wie spreche ich dann Die Adressen im EEPROM zum lesen an ?

5. Wie spreche ich die Adressen über 255 Byte an ist ja dann schon 16
   bitig oder ??

6. Und zu guter letzt was muss ich machen um etwas zu schreiben.

Hauptsächlich geht es mir um den Abflauf, den Code bekomm ich dann
schon irgendwie gebacken.

Hoffe das ich Die fragen jetzt nicht allzudoof gestellt habe, und
bedanke mich ;)

Gruß Dennis

Autor: jochen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Dennis,

also ich hab das schon vor kurzem gemacht allerdings mit einem 24C16
und in C.

Was die PullUps angeht: lt. Spec. müssen die da ran ergo solltest Du
dies auch tun. Mag sein das es auch ohne geht, ist aber keine saubere
Lösung.

Für Deine Fragen 2-6 würde ich die raten Dir ein Datenblatt zu
besorgen, da steht das alles drin.
z.b. hier:
http://www.reichelt.de/inhalt.html?SID=14QCOf0dS4A...

Auf Seite 11 wird da z.B. Auch geschrieben wie man den adressiert.

Hoffe das Hilft, wenn nicht kannst Dich ja noch mal melden.

Grüßle, der Jochen

Autor: Dennis Brücke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Jochen,

danke erstmal für Deine Antwort, so habe mir jetzt meine Adapter
Platine fertig gemacht für mein EEPROM (Habe mir so ein kleines
Testboard Set gebastelt) Habe als Pull-Up jetzt von der Datenleitung zu
VCC einen 4k7 genommen ist das Ok, oder ist der zu Hoch ?

Wenn ich das mit dem 24C32 (oder 64 oder 256 etc...) richtig verstanden
habe, muss ich einmal I2C_Start dann 8 Bit senden die z.b. in Form von
0b10100001 (0xA1) ist zum lesen, dann in den Empfangsmodus gehen und 9
Bit empfangen (1. Bit ein ACK), richtig ?

Gruß Dennis

Autor: Hagen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn externe Pullups, dann einen von SDA nach Vcc und einen zweiten von
SCL nach Vcc. Allerdings gerade heute habe ich mit meinem ATmega8L bei
8064000Hz Takt, Vcc = 3.2V, I2C Takt ~400khz, mit einem ST24C64 der
eigentlich für 5.0V bestimmt ist und OHNE externe Pullups, also nur die
internen Pullups aktiv, absolut keine Probleme gehabt.

Die Frage ist erstmal ob du Software oder Hardware TWI benutzen willst.
Meine derzeitigen WinAVR C Source sehen so aus, sind aber noch nicht
fertig und werden größtenteils noch in Assembler umgestzt und müssen
noch Blöcke lesen und schreiben können. Das Prinzip ist aber klar. Die
Soucen nutzen TWI im Pollling mode, was für EEPROM's meistens besser
ist.


Gruß Hagen


#define EEPROM_ADDRESS      0xA0

void i2cInit(void) {

    TWBR = 3;  // < 400KHz bei 8.064MHz clock
}

uint8_t i2cStart(void) {

    TWCR = (1 << TWEN) | (1 << TWINT) | (1 << TWSTA);
    while (!(TWCR & (1 << TWINT)));
    return(TWSR & 0xF8);
}

uint8_t i2cWrite(const uint8_t Value) {

    TWDR = Value;
    TWCR = (1 << TWEN) | (1 << TWINT);
    while (!(TWCR & (1 << TWINT)));
    return(TWSR & 0xF8);
}

uint8_t i2cRead(const uint8_t Ack) {

    TWCR = (1 << TWEN) | (1 << TWINT) | (Ack << TWEA);
    while (!(TWCR & (1 << TWINT)));
    return(TWDR);
}

void i2cStop(void) {

    TWCR = (1 << TWEN) | (1 << TWINT) | (1 << TWSTO);
    asm("rjmp .+0");
    asm("rjmp .+0");
    asm("rjmp .+0");
    asm("rjmp .+0");
    TWCR = 0;
}


uint8_t EEPROMSetAddress(const uint16_t Address) {

    return((i2cStart() == TW_START) &&
           (i2cWrite(EEPROM_ADDRESS & 0xFE) == TW_MT_SLA_ACK) &&
           (i2cWrite(Address >> 8) == TW_MT_DATA_ACK) &&
           (i2cWrite(Address) == TW_MT_DATA_ACK));
}


uint8_t EEPROMPut(const uint16_t Address, const uint8_t Value) {

    uint8_t Ack = EEPROMSetAddress(Address) &&
                  (i2cWrite(Value) == TW_MT_DATA_ACK);
    i2cStop();
    while (i2cStart() != TW_START) ;
    i2cStop();
    return(Ack);
}


int16_t EEPROMGet(const uint16_t Address) {

    uint8_t Ack = EEPROMSetAddress(Address) &&
                  (i2cStart() == TW_REP_START) &&
                  (i2cWrite(EEPROM_ADDRESS | 1) == TW_MR_SLA_ACK);
    uint16_t Result = -1;
    if (Ack) {Result = i2cRead(0);}
    i2cStop();
    return(Result);
}



Gruß Hagen

Autor: Hagen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achso, im i2cInit() fehlt noch

{
#define I2C_SDA             PC4
#define I2C_SCL             PC5

    DDRC &= ~((1 << I2C_SDA) | (1 << I2C_SCL)); // SDA,SCL als input
    PORTC |= (1 << I2C_SDA) | (1 << I2C_SCL); // SDA,SCL Pullups.
}

Gruß Hagen

Autor: Dennis Brücke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Hagen,

ja die Pull-Up wieder stände habe ich so gesetzt.
Wie ich am Anfang schon geschrieben hatte muss ich leider SoftwareSPI
nutzen, da ich bereits kaum noch Port´s frei habe.

Was C betrifft, komme ich wesentlich weniger mit klar wie mit ASM :(
kommt aber bestimmt als nächstes, eine runde C lernen ;)

Gruß Dennis

Autor: jochen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo nochmal Dennis,

Also ich denke Du wirst im Netzt auch Sourcen für ein SW I2C in ASM
finde.

Was die Ansteuerung angeht gibt es mehrere Möglichkeiten zum lesen und
schreiben. Wenn Du dazu konkret fragen oder Problem hast kannse es ja
noch mal hier posten oder mich anmailen.

Grüßle, der Jochen

Autor: Dennis Brücke (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi @all nochmal,

so die nacht war super lang, und ich bin immer noch nicht
weitergekommen :(

Ich habe jetzt einfach mal den EEPROM 24c32 mit 0x09 gefüllt um dieses
dann einfach mal auszulesen und dann auf PortD auszugeben,
bekomme aber irgendwie immer nur 0xFF zurück :(

Ich habe mal im Anhang meine Test ASM Datei gepostet, vieleicht mache
ich ja auch was Grundlegendes Falsch.

Bitte um Hilfe.

P.S: Der EEPROM ist jetzt so angeschlossen, SDA (Pin5) an PC1 über
einen PullUp von 4k7, das gleiche für SCL (Pin6) an PC0

Gruß Dennis

Autor: jochen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So wie ich das jetzt auf die Schnelle sehe schreibst und ließt Du
gleichzeitig in einem I2C-Zyklus also zwischen i2c_start und i2c_stop.
Das geht nicht. Du mußt das jeweils einzeln machen. So wie ich das sehe
versuchst Du vom Chip mit der Adresse A0h + 1 für lesen ab der
Speicherstelle 0001h zu lesen, was hat da dann das 3 putchar zu
suchen.

Ist das ein SW TWI? Bin net so der Assembler Crack.

Wenn Du da nicht weiterkommst können wir vielleicht nacher mal per ICQ
oder so schwätzen muss jetzt mal einkaufen nacher hab ich aber Zeit.
Kannst Dich ja sonst mal per eMail melden.

Grüßle der Jochen

Autor: Dennis Brücke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Jochen,

danke Dir. Ich blicke in dem Datenblatt leider nicht wirklich durch,
so wie ich das verstanden habe muss ich die Speicheradresse in 2
schritten übergeben also MSB dann LSB sonst wird es ab 255byte
schlecht... oder habe ich da was falsch verstanden...

ICQ ist schlecht bei mir, gehe immer schnell per handy online.
Kann dich höchstens anrufen wenn du möchtest oder umgekehrt.

Gruß Dennis

Autor: jochen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Okay, versuche mal dir klar zu machen wie ich denke das es gehen müsste
(allerdings ohne Garantie da ich mich mit ASM net so auskenne)

Daten aus bestimmter Stelle des EEProm lesen wie folgt:

rcall i2c_start
ldi r16, 0b10100000
rcall pause
rcall pause
rcall putbyte
 -> Hier wird der Baustein mit der Adr. A0h im Schreibe-Modus
angesprochen da die Adresse des zu lesenden Bytes an den Baustein
übergeben werden muss also schreiben:

ldi r16, 0b00000000
rcall putbyte
ldi r16, 0b00000001
rcall putbyte
->hier werden die zwei Adressbytes geschrieben

rcall i2c_start
ldi r16, 0b10100001
rcall putbyte
-> hier kommt nun eine Repeated-Startbedinung hin siehe dazu Datenblatt
Seite 12 [Random Read]. Da muss dan jetzt auch die 1 rein fürs lesen.

rcall getbyte
rcall i2c_stop
-> So nun müsste das gelesene Byte im r16 stehen

Daten an bestimmter Stelle im EEProm schreiben wie folgt:

rcall i2c_start
ldi r16, 0b10100001
rcall putbyte
-> Adresse + Schreibmodus an EEPROM
ldi r16, 0b00000000
rcall putbyte
ldi r16, 0b00000000
rcall putbyte
-> Adresse an die geschrieben werden soll 00h
ldi r16, 0b0101010101
rcall putbyte
-> den Wert 55h schreiben
rcall i2c_stop
siehe dazu auch Datenblatt S. 11 Figure 2 Byte Write

So, damit sollte es eigentlich funtionieren. Was ich Dir nicht sagen
kann ist ob deine ASM Routinen für das I2C okay sind. Meiner Ansicht
nach sollte das ein SW-I2C sein, wenn ja Frag ich mich aber wo z.B. Die
Pins für den I2C deffinieert werden - oder sind das Pin 0 & 1 vom
PortC?.

Naja, vielleicht hilft das erst mal.

Grüßle der Jochen

Autor: jochen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh mist, da ist ein Fehler beim Schreiben in EEPROM muss natürlich wie
folgt aussehen:

rcall i2c_start
ldi r16, 0b10100000
                  ^da muss ne Null hin, wir wollwn ja was schreiben
rcall putbyte
ldi r16, 0b00000000
rcall putbyte
ldi r16, 0b00000000
rcall putbyte
ldi r16, 0b0101010101
rcall putbyte
rcall i2c_stop

Autor: Dennis Brücke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Jochen,

SUPER!!! ;) Ich danke Dir für Deine Hilfe habe erst einfach mal Byte´s
geschrieben, um zu schauen ob überhaupt erstmal das Timing hinhaut.
Dann mit PC ausgelesen supi, geht ;) jetzt habe ich folgenden Code:

        rcall i2c_start
        ldi r16, 0b10100000
        rcall putbyte

        ldi r16, 0b00000000
        rcall putbyte

        ldi r16, 0b00000001
        rcall putbyte

        rcall i2c_start
        ldi r16, 0b10100001
        rcall putbyte

        rcall getbyte

        rcall i2c_stop

und auch dieser geht ;) Bekomme jetzt meine EEPROM Daten, ist echt
super wie jeder jedem Hilft hier ;)

Dickes Lob an Dich für dein Engagement.

Gruß Dennis

Autor: jochen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mir wurde hier am Anfang auch sehr viel geholfen deshalb helfe ich nun
gerne auch Leuten die die selben Problem haben die ich hatte.

Schön das es nun tut.

Jochen

Autor: Dennis Brücke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zu früh gefreut :(

die routine scheint zu funktionieren, nur bekomme ich bei jedem 2. bis
3. mal Datenmüll, jetzt hab ich mal mein Oszi an die SDA leitung
gehängt und gesehen, das der EEPROM die Leitung nicht ganz auf 0 zieht.
habe jetzt als PullUP schon 1k5 und 4k7 ausprobiert, bei beiden das
gleiche.

Was könnte das sein ?

Gruß Dennis

Autor: jochen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Spontan würde ich da jetzt auf ein Timingproblem tippen. Ich weiß leider
nicht wie das da mit dem SW-I2C aussieht. Meines Wissens kann der I2C
max 400kHz. kann allso sein wenn Dein Prozessor "zu schnell" getaktet
ist Du ein paar Wartezyklen einbinden musst.

Ein anderes Problem könnte noch der EEPROM in der Form machen das der
ne gewisse Zweit braucht um Daten zu schreiben. In dieser Zeit ist
keine Kommunikation mit dem Chip möglich. Sollt aber bei Dir nicht der
Fall sein da Du so wie ich das sehe nur lesen tust.

Ich würde es erst mal mit ein paar Verzögerungen testen und wenn das
keinen Erfolg bringt darauf hoffen das Dir vielleicht jemand anderes
helfen kann.


Der Jochen

Autor: Dennis Brücke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Jochen,

hast Du den Windows Messenger ? Wenn ja, kannst Du mich bitte mal unter
Blackice3000@gmx.de mal anmailen.

Gruß Dennis

Autor: Dennis Brücke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey Jochen ;)

also im Moment bin ich Online. Habe es im übrigen gestern Abend noch
geschaft, so wie der Fehler aussah, hat der EEPROM die Stop Condition
nicht richtig empfangen, habe mir noch mal eine andere Routine
Angeschaut, und habe gesehen das der Fehler im I2C_STOP liegt.

Jetzt haut es hin ;)

Endlich bekomm ich auf mein Grafik display ein wenig mehr wie nur
"."

Also weiter im Basteln, jetzt muss ich mal schauen, ob ich Irgendwo
Font´s finde. Ansonsten heist es selber schreiben... uff..

Gruß Dennis

Autor: Dieter B (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Dennis

Wegen der Fonts schau doch mal bei

http://www.apetech.de

Da sollte doch was zu finden sein.

MFG
Dieter

Autor: Dennis Brücke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Dieter,

schau ich gleich mal, sollte mir bestimmt Arbeit ersparen ;)
Danke Dir

Gruß Dennis

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.