- 12V Akku mit 280 Ah bauen         
Ergebnis 1 bis 8 von 8

Thema: I2C Wert nach EEPROM 24C512 schreiben

  1. #1

    I2C Wert nach EEPROM 24C512 schreiben

    Anzeige

    Powerstation Test
    Hallo alle Zusammen,

    ich mache gerade meine ersten Schritte mit I2C. Und habe gleich schon meine ersten Probleme.

    Ich habe einen 24C512 an einen ATMega8 über Hardware TWI, also PIN 27 und 28 angeschlossen, 4k7 Pullups vorhanden, die Adressen des 24C512 wie im Code gezeigt setzt, Spannung und Masse verbunden. Also alles in Minimalkonfiguration.

    Als Lib verwende ich die von Peter Fleury ohne irgendwelche Änderungen.

    Ich möchten den Wert der Speicherstelle 0x05 auslesen, um Eins erhöhen und an die gleiche Speicherstelle zurück schreiben. Die Werte sollen auf einem LCD dargestellt.

    Mein Programm sieht wie folgt aus:

    Code:
    /*-------+---------+---------+---------+---------+---------+---------+---------+
    *   #include-Dateien
    *--------+---------+---------+---------+---------+---------+---------+---------+*/
    #include <avr/io.h>
    #include <stdlib.h>
    #include <util/delay.h>    
    
    #include "lcd.h"
    #include "i2cmaster.h"
    
    
    /*-------+---------+---------+---------+---------+---------+---------+---------+
        Prototypen():
    ---------+---------+---------+---------+---------+---------+---------+---------+*/
    void Fehler(uint8_t Schritt);
    
    /*-------+---------+---------+---------+---------+---------+---------+---------+
        Funktionen():
    ---------+---------+---------+---------+---------+---------+---------+---------+*/
    //-------+---------+---------+---------+---------+---------+---------+---------+
    //    void Fehler(uint8_t Schritt):
    /**    @brief    gibt eine Fehlermeldung aus */
    /**    @param    (Programm-)Schritt in der der Fehler aufgetreten ist */ 
    /**    @return    keinen Rückgabewert */
    //-------+---------+---------+---------+---------+---------+---------+---------+
    void Fehler(uint8_t Schritt)
    {
        switch(Schritt)
        {
            case 1:
                lcd_gotoxy(0,2); lcd_puts("ERR: 1. Start");
                break;
    
            case 2:
                lcd_gotoxy(0,2); lcd_puts("ERR: 1. Adresse");
                break;
    
            case 3:
                lcd_gotoxy(0,2); lcd_puts("ERR: READ-Modus");
                break;
    
            case 4:
                lcd_gotoxy(0,2); lcd_puts("ERR: 2. Start");
                break;
    
            case 5:
                lcd_gotoxy(0,2); lcd_puts("ERR: 2. Adresse");
                break;
    
            case 6:
                lcd_gotoxy(0,2); lcd_puts("ERR: Schreiben");
                break;
    
            default:
                lcd_gotoxy(0,2); lcd_puts("unbekannter Fehler.");
        }
        
        i2c_stop();
        while(1);
    }
    
    
    //-------+---------+---------+---------+---------+---------+---------+---------+
    //    main(void)
    /**    @brief    LCD initialisieren. \n
                I2C Kommunikation initialisieren. \n
                Wert aus Speicherstelle 0x05 auslesen, \n
                um Eins erhöhen, \n
                und an die gleich Stelle zurückschreiben. 
                Beide Werte dann auf dem LCD darstellen. \n*/
    /**    @param    keine Übergabeparameter */ 
    /**    @return    0 */
    //-------+---------+---------+---------+---------+---------+---------+---------+
    int main(void)
    {
        /**    @brief    Returnwert aus den Funktionen zur Fehlerkontrolle */
        uint8_t        ret;
    
        /**    @brief    aus dem Speicher ausgelesen bzw. zurück geschriebene
                    Werte. */
        uint8_t        WertAlt;
        uint8_t        WertNeu;
    
        /**    @brief    Zwischenspeicher für Ausgabe */
        char        Ausgabe[13];
    
        //    LCD initialisieren
        lcd_init(LCD_DISP_ON); lcd_command(LCD_BACKLIGHT_ON);
    
        //    initialize I2C library
        i2c_init();
    
        //    read value from 24C512 EEPROM address 5
        //    24C512 adress set to A2 = 0, A1 = 1, A0 =1
        i2c_start_wait(0b10100110+I2C_WRITE);        // set device address and write mode
        /*    oder auch
        ret= i2c_start(0b10100110+I2C_WRITE);        // set device address and write mode
        if ( ret ) Fehler(2);
        */
    
        ret = i2c_write(0x05);                        // write address = 5
        if ( ret ) Fehler(2);
    
        ret = i2c_rep_start(0b10100110+I2C_READ);        // set device address and read mode
        if ( ret ) Fehler(3);
    
        WertAlt = i2c_readNak();                // read one byte from EEPROM
    
        i2c_stop();
    
        WertNeu = WertAlt + 1;
    
        // write value to 24C512 EEPROM address 5 (Byte Write) 
        i2c_start_wait(0b10100110+I2C_WRITE);        // set device address and write mode
        /*    oder auch
        ret= i2c_start(0b10100110+I2C_WRITE);        // set device address and write mode
        if ( ret ) Fehler(4);
        */
    
        ret = i2c_write(0x05);                            // write address = 5
        if ( ret ) Fehler(5);
    
        ret = i2c_write(WertNeu);                        // write value 0x75 to EEPROM
        if ( ret ) Fehler(6);
    
        i2c_stop();                                    // set stop conditon = release bus
    
        lcd_gotoxy(0,1); utoa(WertAlt, Ausgabe, 10); lcd_puts("Alt: "); lcd_puts(Ausgabe);
    
        lcd_gotoxy(0,2); utoa(WertNeu, Ausgabe, 10); lcd_puts("Neu: "); lcd_puts(Ausgabe);
    
        while(1);
        
    return 0;
    }
    Als Werte erhalte ich aber immer nur als gelesen Wert 255 und als geschriebene Wert 0. Was für den ersten Durchlauf des Programmes noch in Ordnung wäre. Wenn ich dann aber einen Reset am Controller auslöse und das Programm von vorn beginnt, sollte als gelesen 0 und geschrieben 1 erscheint. Tut es aber wie gesagt leider nicht, immer nur 255 und 0.

    Ich sehe das doch richtig, dass alle Speicherstellen in einem fabrikneuen 24C512 mit 255 beschrieben sind. Somit müsste zumindest das Auslesen funktionieren, oder?

    Die I2C-Funktionen erzeugen keinen Fehlercode. Kann ich dann davon ausgehen, dass der Code korrekt abgearbeitet wird? Und vor allem kann ich damit einen Hardwarefehler ausschließen?

    Oder habe ich gerade ein Brett vor dem Kopf und sehe den Wald vor lauter Bäumen nicht mehr?

    Bin für jeden Hinweis dankbar.

    Vielen Dank

    Bot-Builder
    Legasteniker on Board!
    gefundene Rechtschreibfehler dienen der Belustigung des Lesers und dürfen von diesem behalten werden.

  2. #2
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.652
    ... meine ersten Schritte mit I2C ... möchten ... Speicherstelle 0x05 auslesen .... zurück schreiben ...
    Ich weiß ja nicht, wie schnell Deine I²C-Kommunikation eingestellt ist, die i2cmaster.h steht ja nicht dabei. Aber vielleicht gehts zu schnell zum Schreiben und vielleicht auch zu schnell zum Lesen? Ich hatte mal mit dem 24C16 rumgespielt - da konnte ich auch keinen wirklich schnellen Datenverkehr realsieren. Aber keine Ahnung wie schnell-langsam das war. Deinen Code habe ich nicht durchgesehen.

    Vorschlag: setz mal die I²C-Kommunikation um eine Null runter oder testweise sogar um zwei.
    Ciao sagt der JoeamBerg

  3. #3
    Zitat Zitat von oberallgeier Beitrag anzeigen
    Ich weiß ja nicht, wie schnell Deine I²C-Kommunikation eingestellt ist, ...
    Also die Busfrequenz ist mit #define SCL_CLOCK 100000L auf 100kHz gesetzt. Aber auch ein Runtersetzen bis auf 1kHz hat leider am Ergebniss nichts geändert. Aber trotzdem Danke für den Tip.

    Allerdings ist bei mir die Busfrequenz in der twimaster.c definiert. Die habe ich im makefile bei den C-Sources mit angegeben. Und i2cmaster.h mit #include eingebunden. Also eigentlich so, wie ich das immer gemacht habe. Oder liegt schon hier ein Fehler?
    Legasteniker on Board!
    gefundene Rechtschreibfehler dienen der Belustigung des Lesers und dürfen von diesem behalten werden.

  4. #4
    Erfahrener Benutzer Roboter Experte Avatar von ePyx
    Registriert seit
    14.05.2008
    Ort
    Falkensee
    Beiträge
    700
    Hmm muss die Adresse nicht aus einem Wort also 16 Bit bestehen? Hab letztens das Datenblatt eine 24L024 gelesen und bin mir sicher das es 16 Bit waren.
    Grüße,
    Daniel

  5. #5
    Zitat Zitat von ePyx Beitrag anzeigen
    Hmm muss die Adresse nicht aus einem Wort also 16 Bit bestehen?
    Hallo Daniel,

    vielen herzlichen Dank! Das war der entscheidene Hinweis.

    Ist bei genauem Nachdenken natürlich auch klar. Wie sollen 512k mit nur 8bit adressiert werden können. Da hätte ich auch selber darauf kommen müssen. Aber manchmal sehe ich den Wald vor lauter Bäumen eben nicht mehr.

    Ich habe gerade quick and dirty ein zusätzliches Adressbyte eingebaut und das einfache Programm leistet jetzt genau das, was ich erwartet habe. Ich hoffe, das bleibt auch so wenn es umfangreicher wird.

    Ich habe das Datenblatt auch noch mal intensiv gelesen. Wenn ich die Sache richtig verstanden habe, ist das Adressword ein 16bit Wert. Also mit 0b0000 0000 0000 0001 greift man auf die erste Speicherstelle zu? Oder gibt es auch die Speicherstelle 0b0000 0000 0000 0000?

    Jedenfalls nach 0b0000 0000 1111 1111 folgt 0b0000 0001 0000 0000, richtig? Oder werden erst die unteren 8bit übergeben und dann die oberen?

    Was mich dann zu der Frage der Speicherorganisation führt. Wenn ich z.B. nur 12 Bytes als Konfigurationsdaten speichern will, diese aber wegen der Lebensdauer des Bausteins nicht immer wieder in die gleichen Speicherstellen schreiben will muss man eine Art Pointer aufbauen. Den muss man aber auch wieder irgendwo speichern. Wie löst man dieses Problem?

    Das Thema muss aber mindestens bis Morgen warten.

    Nochmals vielen Dank.

    Und für heute eine guten Nacht.

    Uwe
    Legasteniker on Board!
    gefundene Rechtschreibfehler dienen der Belustigung des Lesers und dürfen von diesem behalten werden.

  6. #6
    Erfahrener Benutzer Roboter Experte Avatar von ePyx
    Registriert seit
    14.05.2008
    Ort
    Falkensee
    Beiträge
    700
    Also laut den Datasheets von Microchip wird zunächst das Controllbyte ( Adresse + I2C_Write/I2C_Read) , dann das High-Byte der Adresse (Bit 15- gefolgt von Low-Byte der Adresse (Bit 7-0) gesendet. Würde schon davon ausgehen, dass der Speicher des EEPROMs bei 0x0000 beginnt und nicht bei 0x0001. Aufpassen musst du eigentlich nur bei einem Random-Read oder wenn du eine ganze Page adressieren willst.

    Das Ganze ist aber momentan ohne Gewähr, da ich erst morgen Zeit habe um das mal selbst zu testen.
    Grüße,
    Daniel

  7. #7
    Ich habe den Code umgeschrieben, ist jetzt funktionsfähig. Ich post ihn mal hier, vielleicht kann er ja für andere hilfreich sein.

    Code:
    /*-------+---------+---------+---------+---------+---------+---------+---------+
    *   #include-Dateien
    *--------+---------+---------+---------+---------+---------+---------+---------+*/
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <stdlib.h>
    #include <util/delay.h>    
    
    #include "lcd.h"
    #include "i2cmaster.h"
    
    /*-------+---------+---------+---------+---------+---------+---------+---------+
        Prototypen():
    ---------+---------+---------+---------+---------+---------+---------+---------+*/
    void Fehler(uint8_t Schritt);
    
    /*-------+---------+---------+---------+---------+---------+---------+---------+
        Funktionen():
    ---------+---------+---------+---------+---------+---------+---------+---------+*/
    //-------+---------+---------+---------+---------+---------+---------+---------+
    //    void Fehler(uint8_t Schritt):
    /**    @brief    gibt eine Fehlermeldung aus */
    /**    @param    (Programm-)Schritt in der der Fehler aufgetreten ist */ 
    /**    @return    keinen Rückgabewert */
    //-------+---------+---------+---------+---------+---------+---------+---------+
    void Fehler(uint8_t Schritt)
    {
        switch(Schritt)
        {
            case 1:
                lcd_gotoxy(0,2); lcd_puts("ERR: 1. Start"); lcd_command(LCD_CLEAR_RESTLINE);
                break;
    
            case 2:
                lcd_gotoxy(0,2); lcd_puts("ERR: 1. Ad. HByte"); lcd_command(LCD_CLEAR_RESTLINE);
                break;
    
            case 3:
                lcd_gotoxy(0,2); lcd_puts("ERR: 1. Ad. LByte"); lcd_command(LCD_CLEAR_RESTLINE);
                break;
    
            case 4:
                lcd_gotoxy(0,2); lcd_puts("ERR: READ-Modus"); lcd_command(LCD_CLEAR_RESTLINE);
                break;
    
            case 5:
                lcd_gotoxy(0,2); lcd_puts("ERR: 2. Start"); lcd_command(LCD_CLEAR_RESTLINE);
                break;
    
            case 6:
                lcd_gotoxy(0,2); lcd_puts("ERR: 2. Ad. HByte"); lcd_command(LCD_CLEAR_RESTLINE);
                break;
    
            case 7:
                lcd_gotoxy(0,2); lcd_puts("ERR: 2. Ad. LByte"); lcd_command(LCD_CLEAR_RESTLINE);
                break;
    
            case 8:
                lcd_gotoxy(0,2); lcd_puts("ERR: Schreiben"); lcd_command(LCD_CLEAR_RESTLINE);
                break;
    
            default:
                lcd_gotoxy(0,2); lcd_puts("unbekannter Fehler."); lcd_command(LCD_CLEAR_RESTLINE);
        }
        
        i2c_stop();
        while(1);
    }
    
    
    //-------+---------+---------+---------+---------+---------+---------+---------+
    //    main(void)
    /**    @brief    LCD initialisieren. \n
                I2C Kommunikation initialisieren. \n
                Wert aus Speicherstelle 0x05 auslesen, \n
                um Eins erhöhen, \n
                und an die gleich Stelle zurückschreiben. 
                Beide Werte dann auf dem LCD darstellen. \n*/
    /**    @param    keine Übergabeparameter */ 
    /**    @return    0 */
    //-------+---------+---------+---------+---------+---------+---------+---------+
    int main(void)
    {
        /**    @brief    Adresse der zu lesenden bzw. beschreibenden Speicherstelle */
        uint16_t    Adresse;
        uint8_t        HByte;
        uint8_t        LByte;
    
        //    Adresse willkürlich gewählt; nur zum Testen
        Adresse = 0x4321;
        LByte = Adresse;
        HByte = (Adresse >> 8);
        
        /**    @brief    Returnwert aus den Funktionen zur Fehlerkontrolle */
        uint8_t        ret;
    
        /**    @brief    aus dem Speicher ausgelesen bzw. zurück geschriebene
                    Werte. */
        uint8_t        WertAlt;
        uint8_t        WertNeu;
    
        /**    @brief    Zwischenspeicher für Ausgabe */
        char        Ausgabe[13];
    
        //    LCD initialisieren
        lcd_init(LCD_DISP_ON); lcd_command(LCD_BACKLIGHT_ON);
    
        // initialize I2C library
        i2c_init();
    
        // read value from EEPROM
        i2c_start_wait(Dev24C512+I2C_WRITE);        // set device address and write mode
        /*    oder auch
        ret= i2c_start(Dev24C512+I2C_WRITE);        // set device address and write mode
        if ( ret ) Fehler(2);
        */
    
        ret = i2c_write(HByte);                        // write address hbyte
        if ( ret ) Fehler(2);
    
        ret = i2c_write(LByte);                        // write address lbyte
        if ( ret ) Fehler(3);
    
        ret = i2c_rep_start(Dev24C512+I2C_READ);    // set device address and read mode
        if ( ret ) Fehler(4);
    
        WertAlt = i2c_readNak();                    // read one byte from EEPROM
    
        i2c_stop();
    
        WertNeu = WertAlt + 1;
    
        // write value to EEPROM (Byte Write) 
        i2c_start_wait(Dev24C512+I2C_WRITE);        // set device address and write mode
        /*    oder auch
        ret= i2c_start(Dev24C512+I2C_WRITE);        // set device address and write mode
        if ( ret ) Fehler(5);
        */
    
        ret = i2c_write(HByte);                        // write address hbyte
        if ( ret ) Fehler(6);
    
        ret = i2c_write(LByte);                        // write address lbyte
        if ( ret ) Fehler(7);
    
        ret = i2c_write(WertNeu);                    // write value
        if ( ret ) Fehler(8);
    
        i2c_stop();                                    // set stop conditon = release bus
    
        //    Ausgabe der Werte auf dem LCD
        lcd_gotoxy(0,1); lcd_puts("Adresse: ");
        utoa(HByte, Ausgabe, 16); lcd_puts("0x"); lcd_puts(Ausgabe);
        utoa(LByte, Ausgabe, 16); lcd_puts(" "); lcd_puts(Ausgabe); lcd_command(LCD_CLEAR_RESTLINE);
        lcd_gotoxy(0,2); lcd_puts("Alt: "); utoa(WertAlt, Ausgabe, 10); lcd_puts(Ausgabe); lcd_command(LCD_CLEAR_RESTLINE);
        lcd_gotoxy(0,3); lcd_puts("Neu: "); utoa(WertNeu, Ausgabe, 10); lcd_puts(Ausgabe);lcd_command(LCD_CLEAR_RESTLINE);
    
        while(1);
        
    return 0;
    }
    Die erste Speicherstelle hat die Adresse 0x0000, Adressierung hat die Form Hbyte, LByte.

    Dann kann ich den Thread jetzt als "Erledigt" kennzeichnen.

    Nochmals Vielen Dank.

    Uwe
    Legasteniker on Board!
    gefundene Rechtschreibfehler dienen der Belustigung des Lesers und dürfen von diesem behalten werden.

  8. #8
    Erfahrener Benutzer Roboter Experte Avatar von ePyx
    Registriert seit
    14.05.2008
    Ort
    Falkensee
    Beiträge
    700
    Schön das es klappt. Dann viel Spaß beim weiterfrickeln.
    Grüße,
    Daniel

Ähnliche Themen

  1. Problem beim Schreiben in einen I2C EEPROM
    Von DarkFire im Forum C - Programmierung (GCC u.a.)
    Antworten: 0
    Letzter Beitrag: 05.01.2008, 09:13
  2. Long Variable in I2C-EEprom schreiben und wieder lesen ?
    Von Roberto im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 10
    Letzter Beitrag: 01.11.2006, 08:52
  3. Float Wert in EEPROM schreiben
    Von AlexAtRobo im Forum C - Programmierung (GCC u.a.)
    Antworten: 5
    Letzter Beitrag: 26.06.2006, 22:10
  4. Suche EEprom 24C512
    Von Razer im Forum Elektronik
    Antworten: 1
    Letzter Beitrag: 22.05.2006, 18:53
  5. i2c-eeprom 24c256 lesen/schreiben
    Von pebisoft im Forum C - Programmierung (GCC u.a.)
    Antworten: 1
    Letzter Beitrag: 28.02.2005, 13:47

Stichworte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiFePO4 Speicher Test