Problem mit I2C-EEprom

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Problem mit I2C-EEprom

      Hallo,
      ich benutze ein EEprom 24 LC 256. Es gelingt mir nicht, die eingeschriebenen Daten wieder auszulesen. Sie stimmen nicht überein. Ich denke, dass ich die Pagegrenzen von 128 einhalte. Ich starte bei Adresse 8, schreibe das Datenpaket von jeweils 8 Byte und erhöhe dann die Adresse um 8. Umgekehrt wird das Lesen bei Adresse 8 begonnen und nach dem Lesen die Adresse wieder um 8 erhöht. Wie gesagt, die ausgelesenen Daten stimmen mit den eingelesen nicht überein. Ich kann einen Fehler nicht finden. Was mache ich falsch? Für 10 ms Pause habe ich beim Schreiben und Lesen der Bytes gesorgt. Bleibt die Frage, ob ich immer nur ein Datenpaket von 128 Byte sammeln und dann erst am Stück einschreiben muss?
      Freundliche Grüße
      Bert
    • Hallo,
      ich habe ein Beispiel geschrieben. Ähnlich läuft das größere Programm. Zu sehen ist, dass die Daten nicht übereinstimmen. Hier der Code:


      '-------------------------------------------------------------------------------

      $regfile = "m328pdef.dat"
      $crystal = 16000000
      $hwstack = 50
      $swstack = 150
      $framesize = 150
      $baud = 9600

      '-------------------------------------------------------------------------------

      Enable Interrupts

      '-------------------------------------------------------------------------------


      config Scl = PortC.5 'SCL-Pin
      config Sda = PortC.4 'SDA-Pin
      config Twi = 100000
      I2cinit

      '-------------------------------------------------------------------------------

      Dim Sekunde As byte
      Dim Minute As byte
      Dim Stunde As byte
      Dim Jahr as word
      Dim Monat as byte
      Dim Tag as Byte
      Dim Weekday as byte

      CONFIG ADC = single, PRESCALER = AUTO, Reference = AREF

      Config rnd = 32
      const limit = 1000
      dim dw as Dword

      '-------------------------------------------------------------------------------------

      Config Clock = User 'Interne Time/Date Routinen für Bascom konfigurieren
      Config Date = Dmy , Separator = . 'Tag,Monat;Jahr Deutsch

      Dim Wert as Word
      Dim Wert_low as Byte at Wert Overlay
      Dim Wert_high as Byte at Wert Overlay+1

      Dim Eadr as Word 'fortlaufende EEprom-Adressen
      Dim Eadr_low as Byte at Eadr Overlay
      Dim Eadr_high as Byte at Eadr Overlay+1

      Const Ds3231w = &HD0 '208 Schreibaddresse des DS3231
      Const Ds3231r = &HD1 '209 Leseadresse des DS3231

      '-------------------------------------------------------------------------------

      Logger:

      Eadr=8
      Gosub Rnd
      Gosub Getdatetime
      Gosub Eschreiben
      Print "Eadr "; Eadr
      Print Stunde;":";Minute;":";Sekunde
      Print "Wert "; Wert

      Do
      Gosub Rnd
      Gosub Getdatetime
      gosub Eschreiben
      waitms 100
      'Gosub Elesen
      Eadr = Eadr + 8
      Print "Eadr "; Eadr
      Print Stunde;":";Minute;":";Sekunde
      Print "Wert "; Wert

      If Eadr=128 then
      Eadr=8
      Print
      Print
      Print
      while Eadr<128
      Print "Eadr "; Eadr
      Gosub Elesen
      Print Stunde;":";Minute;":";Sekunde
      Print "Wert : ";Wert
      Eadr = Eadr + 8
      wend
      end
      end if
      waitms 100
      Loop

      '-----------------------------------------------------------------------------------------------------------

      Rnd:
      dw = Rnd(Limit)
      Wert=dw
      return

      '-----------------------------------------------------------------------------------------------------------
      'Subroutinen
      '-----------------------------------------------------------------------------------------------------------
      'EAdressen
      Eschreiben:

      I2cstart 'Start I2C
      I2cwbyte &HA0 'Sende Slave SchreibAdresse
      I2cwbyte Eadr_high 'Sende Speicheradresse High
      I2cwbyte Eadr_low 'Sende Speicheradresse LOw
      I2cwbyte Sekunde
      waitms 20
      I2cwbyte Minute
      waitms 20
      I2cwbyte Stunde
      waitms 20
      I2cwbyte Tag
      waitms 20
      I2cwbyte Monat
      waitms 20
      I2cwbyte Jahr
      waitms 20
      I2cwbyte Wert_high
      waitms 20
      I2cwbyte Wert_low
      waitms 20
      I2cstop

      return

      '-----------------------------------------------------------------------------------------------------------

      Elesen:
      I2cstart 'Start I2C
      I2cwbyte &HA0 'sende Slave Adresse
      I2cwbyte Eadr_high 'sende Speicheradresse High
      I2cwbyte Eadr_low 'sende Speicheradresse Low
      I2Cstop
      I2cstart 'Start I2C
      I2cwbyte &HA1 'sende Slave LesenAdresse
      I2crbyte Sekunde, Ack
      waitms 20
      I2crbyte Minute, Ack
      waitms 20
      I2crbyte Stunde, Ack
      waitms 20
      I2crbyte Tag, Ack
      waitms 20
      I2crbyte Monat, ack
      waitms 20
      I2crbyte Jahr, ack
      waitms 20
      I2crbyte Wert_high, Ack
      waitms 20
      I2crbyte Wert_low, Nack
      waitms 20
      I2cstop

      return

      '------------------------------------------------------------------------------------
      ' Unterprogramme für die Bascom Date/Time-Funktionen
      '------------------------------------------------------------------------------------
      Getdatetime:
      I2cstart 'Start
      I2cwbyte Ds3231w
      I2cwbyte 0 'auf 0 stellen
      I2cstop
      I2cstart
      I2cwbyte Ds3231r
      I2crbyte Sekunde, Ack 'Sekunden
      I2crbyte Minute , Ack 'Minuten
      I2crbyte Stunde, Ack 'Stunden
      I2crbyte Weekday , Ack 'Wochentag
      I2crbyte Tag, Ack 'Tag
      I2crbyte Monat , Ack 'Monat
      I2crbyte Jahr , Nack 'Jahr
      I2cstop
      'Weekday=Makedec(Weekday)
      Tag = Makedec(Tag) : Monat = Makedec(Monat) :Jahr = Makedec(Jahr) 'in Dez.wandeln
      Sekunde= Makedec(Sekunde) : Minute = Makedec(Minute) : Stunde = Makedec(Stunde) 'in Dez. wandeln
      'Tag=_day:Monat=_month:Jahr=_year:Stunde=_hour:Minute=_min:Sekunde=_sec
      Weekday = Dayofweek() 'lt.Bascomhilfe erforderlich

      Return

      '------------------------------------------------------------------------------------

      Setdatetime: 'Datum setzen (Schreiben)
      'Weekday=Makebcd(Weekday):
      Tag = Makebcd(Tag) : Monat= Makebcd(Monat) : Jahr = Makebcd(Jahr)
      Sekunde = Makebcd(Sekunde) :Minute = Makebcd(Minute) : Stunde = Makebcd(Stunde)
      I2cstart
      I2cwbyte Ds3231w
      I2cwbyte 0
      I2cwbyte Sekunde
      I2cwbyte Minute
      I2cwbyte Stunde
      I2cwbyte Weekday
      I2cwbyte Tag
      I2cwbyte Monat
      I2cwbyte Jahr
      I2cstop
      Return

      '-----------------------------------------------------------------------



      Freundliche Grüße Bert
    • Zwei Dinge fallen mir auf:
      -Nach dem Senden eines Bytes brauchst du keine Wartezeit, der Chip sammelt und schreibt erst, wenn I2Cstop kommt (Microchip Datenblatt S.12)
      -Beim Lesen darfst du zwischendrin kein I2Cstop machen, das setzt nämlich die I2C Logik aller Teilnehmer auf Anfang.
      Ein I2crepstart wäre hier der korrekte Befehl (gilt für beide deiner Busteilnehmer)

      In deiner Do-Loop änderst du die Elesen Adresse, auch zwischen schreiben und lesen, dann hast du natürlich andere Daten.
      Eine Wartezeit beim Lesen ist nicht nötig.
    • Hallo Michael,
      ich denke, dass ich das Programm nach Deinen Tipps umgeschrieben habe. Es läuft weiterhin fehlerhaft, und zwar nur bei der Ausgabe von "Wert". Das Datum wird bei der jeweiligen Speicheradresse korrekt eingeschrieben und ausgelesen. Liegt es am Definieren von "Wert". Wert wird als High- und Low-Wert definiert. Das mache ich wie bei Adressen:
      Dim Wert as Word
      Dim Wert_low as Byte at Wert Overlay
      Dim Wert_high as Byte at Wert Overlay+1

      Dim Eadr as Word 'fortlaufende EEprom-Adressen
      Dim Eadr_low as Byte at Eadr Overlay
      Dim Eadr_high as Byte at Eadr Overlay+1

      Ist das korrekt?
    • Hallo Michael,
      ich denke, ich habe den Fehler gefunden. Wert ist als Word definiert. High und Low als Byte. Dabei übersteigt das Low-Byte bei größeren Zahlen den zulässige Maximalwert von 255. Ich müsste demnach Wert in drei oder vier Byte aufteilen. Muss mal schauen, wie das am einfachsten geht. Das gilt dann auch für die Adresse. Was meinst Du dazu?
      MfG Bert
    • Einfach Unsinn

      Hallo,
      eigentlich befürchtete ich, jetzt eine Menge Protest zu lesen, denn beim Zubereiten des Abendbrots merkte ich, dass ich zuvor ein Brett vor dem Kopf hatte oder die Mathematik auszuhebeln versuchte. Natürlich kann ein Word nur in zwei Bytes aufgeteilt werden. Und kein Byte kann größer als 255 anwachsen. Das mit den drei Bytes war Unsinn. Aber es funktioniert. Ich muss jetzt mal schauen, woran das liegt.
      MfG Bert