- 3D-Druck Einstieg und Tipps         
Ergebnis 1 bis 5 von 5

Thema: Probleme I2C und ATMEL 24C256

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    29.11.2005
    Ort
    57334 Bad Laasphe
    Alter
    53
    Beiträge
    8

    Probleme I2C und ATMEL 24C256

    Anzeige

    Powerstation Test
    Hallo zusammen und auch noch ein frohes neues Jahr.

    Ich habe mal wieder ein Problem !

    Seit einigen Tagen beschäftige ich mich zum erstenmal mit dem I2C Bus.

    Nun habe ich schon einige Hürden überwunden aber dieses Problem ist mir unerklärlich.

    Für meine ersten Versuche habe ich mir ein ATMEL 24C256 EEProm besorgt und mir unter VB ein Programm geschrieben welches dieses am Parallelport ansteuert. (Bustiming mit Oszi geprüft)

    Wenn ich nun in eine Speicherzelle einen Wert hinein schreibe so ist dieser Wert in allen Zellen des gesamten unteren Adressbereich.
    Beispiel:
    Also ich schreibe in
    HiAdresse: 00
    LoAdresse: 00
    den Wert: 128

    Beim auslesen finde ich diesen Wert aber im Bereich
    HiAdresse: 00
    LoAdresse: 00 -FF
    Wert: 128

    Also der gesamt LoAdress Bereich erhält den geschrieben Wert. Verändere ich die Speicherzelle so verhält es sich wieder so.
    Wenn ich den HiAdresse ändere so verhält es sich genauso.

    Was mache ich falsch ?

    Vielen Dank schonmal für eure Unterstützung.

    fg
    Frank

  2. #2
    Erfahrener Benutzer Begeisterter Techniker Avatar von Andre_S
    Registriert seit
    26.06.2005
    Beiträge
    357
    Hallo Frank,

    bist Du denn sicher, dass Deine Leseroutine auch ordnungsgemäß arbeitet, Du also die "tatsächlichen" Inhalte der jeweiligen Speicherstelle angezeigt bekommst?
    Und welche Methode (Page/Byte) zum schreiben bzw lesen nutzt Du denn? Oder zeig doch einfach mal...


    Gruß André

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    29.11.2005
    Ort
    57334 Bad Laasphe
    Alter
    53
    Beiträge
    8
    Hallo Andrè,

    wenn ich das HiAdressByte ändere wird sofort ein anderer Wert angezeigt.
    Das spricht dafür das die Routine funktioniert. Da ich am Anfang stehe verwende ich nur Byte Write und Random Read.

    Ich gebe dir aber recht das ich vieleicht nur immer die selbe Zelle auslese !?. Auch wenn ich nach dem Schreiben des LoAdressByte ein ACK=OK bekomme.

    Das ganze besteht natürlich aus drei Routinen.

    1.)Der Ablauf

    Code:
    Private Sub CmdMemoryRead_Click()
    'Initalisiere die Ports
    List1.AddItem (I2C_init)
    'Bus Start
    List1.AddItem ("Memory Read:" & I2C_Start(Channel_1))
    
    'Prüfen ob Directionbit HIGH (Readmodus) ist
    If DeviceAdrByte And 1 Then
    'Ist Directionbit HIGH (Readmodus) dann ändere auf LOW (Writemodus)
      DeviceAdrByte = DeviceAdrByte Xor 1
    End If
    
    'Schreibe Bauteil AdressByte aber im Writemodus
    'um die Memory Adresse zu schreiben
    If Not I2C_WriteByte(Channel_1, DeviceAdrByte) Then
        List1.AddItem ("Memory Read: Bauteil Adresse " & DeviceAdrByte & " ACK=NO")
            List1.AddItem ("Memory Read:" & I2C_Stop(Channel_1))
                Exit Sub
    Else
            List1.AddItem ("Memory Read: Bauteil Adresse " & DeviceAdrByte & " ACK=OK")
    End If
    
    'Memory oberer Adresse
    If Not I2C_WriteByte(Channel_1, AdrHiByte) Then
        List1.AddItem ("Memory Read: High Adresse Byte " & AdrHiByte & " ACK=NO")
            List1.AddItem ("Memory Read:" & I2C_Stop(Channel_1))
                Exit Sub
    Else
        List1.AddItem ("Memory Read: High Adresse Byte " & AdrHiByte & " ACK=OK")
    End If
    
    'Memory untere Adresse
    If Not I2C_WriteByte(Channel_1, AdrHiByte) Then
        List1.AddItem ("Memory Read: Low Adresse Byte " & AdrLoByte & " ACK=NO")
            List1.AddItem ("Memory Read:" & I2C_Stop(Channel_1))
                Exit Sub
    Else
        List1.AddItem ("Memory Read: Low Adresse Byte " & AdrLoByte & " ACK=OK")
    End If
    
    'Prüfen ob Directionbit nicht HIGH (Readmodus) ist
    If Not DeviceAdrByte And 1 Then
    'Ist Directionbit LOW (Writemodus) dann ändere auf HIGH (Readmodus)
      DeviceAdrByte = DeviceAdrByte Xor 1
    End If
    
    'Bus Start / Nach Dtenblatt muss nach der Memoryadresse nochmals START
    List1.AddItem ("Memory Write:" & I2C_Start(Channel_1))
    
    'Schreibe Bauteil AdressByte aber im Readmodus um die zuvor gesetzte
    'Memory Adresse lesen zu können
    If Not I2C_WriteByte(Channel_1, DeviceAdrByte) Then
        List1.AddItem ("Memory Read: Bauteil Adresse " & DeviceAdrByte & " ACK=NO")
            List1.AddItem ("Memory Read:" & I2C_Stop(Channel_1))
                Exit Sub
    Else
            List1.AddItem ("Memory Read: Bauteil Adresse " & DeviceAdrByte & " ACK=OK")
    End If
    'Lese Byte Laut Datenblatt kein ACK
    DatenByte = I2C_ReadByte(Channel_1, True)
    Label3.Caption = CStr(DatenByte)
    'Bus Stop
    List1.AddItem ("Memory Read: " & I2C_Stop(Channel_1))
    
    End Sub
    2.) Write Routine
    Code:
    'Ein Byte schreiben
    Function I2C_WriteByte(AkChannel As SDA_Channel, ByVal I2C_Data As Byte) As Boolean
    Dim RetVal As Boolean
    Dim BinData As String
    Dim AkControllPort As Byte
    Dim wait As Integer
    Dim X As Long
    Dim I As Integer
    
    BinData = DezToBin(I2C_Data) 'dezimale Daten in binäre umwandeln
    
    AkControllPort = Inp(LPT_Controll)
     'Ist Bit 5 im Controllregister gesetzt (Inputmodus)
    If AkControllPort And LPT_mode Then
    'Ist Inputmodus dann umschalten auf Outputmodus(Bit 5 Löschen)
    Out Controllport, AkControllPort Xor LPT_Input_mode
    Else
    'Outputmodus eingestellt
    End If
    
    'For I = 1 To 10000 'Nur zum testen des Bus Timing
    For X = 1 To 8
      If Mid(BinData, X, 1) = "1" Then
        'SDA High
        Out I2C_Port.SDA, AkChannel * High
        'veränderten ControllPort wieder einlesen
        AkControllPort = Inp(LPT_Controll)
        'SCL High
        Out I2C_Port.SCL, AkControllPort Xor SCL_Channel.Channel_SCL 'Xor MaskeAkControllPort = Inp(LPT_Controll)
        'veränderten ControllPort wieder einlesen
        AkControllPort = Inp(LPT_Controll)
        'SCL Low
        Out I2C_Port.SCL, AkControllPort Xor SCL_Channel.Channel_SCL 'Xor Maske
        '(Als Pause)veränderten ControllPort wieder einlesen
        AkControllPort = Inp(LPT_Controll)
        'SDA Low
        Out I2C_Port.SDA, AkChannel * Low
      Else
        'SDA Low
        Out I2C_Port.SDA, AkChannel * Low
        'veränderten ControllPort wieder einlesen
        AkControllPort = Inp(LPT_Controll)
        'SCL High
        Out I2C_Port.SCL, AkControllPort Xor SCL_Channel.Channel_SCL 'Xor Maske
        'veränderten ControllPort wieder einlesen
        AkControllPort = Inp(LPT_Controll)
        'SCL Low
        Out I2C_Port.SCL, AkControllPort Xor SCL_Channel.Channel_SCL 'Xor Maske
        '(Als Pause)veränderten ControllPort wieder einlesen
        AkControllPort = Inp(LPT_Controll)
        'SDA Low
        Out I2C_Port.SDA, AkChannel * Low
      End If
    Next
    'Next I 'Nur zum Testen des Bus Timing
    'ACK ausgeben und testen, ob es bestätigt wird
    'LPT auf lese modus schalten
    AkControllPort = Inp(LPT_Controll)
    'Ist Bit 5 im Controllregister nicht gesetzt (Outputmodus)
    If Not AkControllPort And LPT_mode Then
    'Ist Outputmodus dann umschalten auf Inputmodus(Bit 5 setzen)
    Out LPT_Controll, AkControllPort Xor LPT_mode
    'Hierdurch wird der gesamt I2C SDA Port High und kann als Input
    'auf Low gezogen werden.
    End If
    
    'veränderten ControllPort wieder einlesen
    AkControllPort = Inp(LPT_Controll)
    'SCL High
    Out I2C_Port.SCL, AkControllPort Xor SCL_Channel.Channel_SCL
    wait = 0
    Do 'Nun den SDA Port abfragen ob er auf Low gezogen wird = ACK OK
    DoEvents
    
    If Not Inp(I2C_Port.SDA) And AkChannel Then 'Ist Kanal Low ?
        Debug.Print "Empfang bestätigt (ACK=OK)"
            RetVal = True
                Exit Do
    ElseIf wait = 10 Then
        Debug.Print "Zeitüberschreitung Empfangsbestätigung"
            RetVal = False
                Exit Do
    End If
    
    Debug.Print "Warte auf Empfangsbestätigung (ACK=NO):" & wait
    wait = wait + 1
    
    Loop
    'veränderten ControllPort wieder einlesen
    AkControllPort = Inp(LPT_Controll)
    'SCL Low
    Out I2C_Port.SCL, AkControllPort Xor SCL_Channel.Channel_SCL 'Wichtig: SCL muss wieder low werden - hätte fast die Nerven verloren!
    
    'veränderten ControllPort wieder einlesen
    AkControllPort = Inp(LPT_Controll)
    'LPT wieder auf Outputmodus umschalten
    Out LPT_Controll, AkControllPort Xor LPT_mode
    
    'veränderten ControllPort wieder einlesen
    Debug.Print Inp(LPT_Controll)
    
    I2C_WriteByte = RetVal
    
    End Function
    3.) Read Routine
    Code:
    Function I2C_ReadByte(AkChannel As SDA_Channel, Optional ByVal NACK As Boolean = False) As Long
    Dim Temp As Byte
    Dim Bit As Integer
    Dim AkControllPort As Byte
    Temp = 0
    AkControllPort = Inp(LPT_Controll)
    Debug.Print AkControllPort
     'Ist Bit 5 im Controllregister nicht gesetzt=Outputmodus
    If Not AkControllPort And LPT_mode Then
    'Ist Oututmodus dann umschalten auf Inputmodus(Bit 5 Setzen)
    Out LPT_Controll, AkControllPort Xor LPT_mode
    'Hierdurch werden alle SDA Port HIgh und können gegen Masse auf null gezogen werden
    Debug.Print Inp(LPT_Controll)
    Else
    'Inputmodus ist eingestellt
    End If
    
    'ControllPort einlesen
    AkControllPort = Inp(I2C_Port.SCL)
    'Prüfen ob Bit0 (SCL) High ist
    If Not AkControllPort And SCL_Channel.Channel_SCL Then
      'War SCL High dann ändere auf Low
      Out I2C_Port.SCL, AkControllPort Xor SCL_Channel.Channel_SCL
    End If
    
    'Schleife starten
    For Bit = 7 To 0 Step -1 'Höherwertiges Bit (MSB) zu erst (rückwerts)
        'ControllPort einlesen
        AkControllPort = Inp(I2C_Port.SCL)
      'SCL High
      Out I2C_Port.SCL, AkControllPort Xor SCL_Channel.Channel_SCL
      'SDA abfrage
      Debug.Print Inp(I2C_Port.SDA)
      If Inp(I2C_Port.SDA) And AkChannel Then
        Temp = Temp + 2 ^ Bit
      End If
      'ControllPort einlesen
      AkControllPort = Inp(I2C_Port.SCL)
      'SCL Low
      Out I2C_Port.SCL, AkControllPort Xor SCL_Channel.Channel_SCL
    Next
    
    If NACK = True Then
    'SDA Port auf Hi voreinstellen noch nicht ausführen (ACK=No)
      Out I2C_Port.SDA, Inp(I2C_Port.SDA) Or AkChannel * High
    Else
    'SDA Port auf Lo voreinstellen noch nicht ausführen (ACK=OK)
      Out I2C_Port.SDA, Inp(I2C_Port.SDA) And AkChannel * Low
    End If
    
    'LPT wieder auf Outputmodus und damit voreinstellung ausführen
    Out LPT_Controll, AkControllPort Xor LPT_mode
    'Nun noch den Clock erzeugen
      'ControllPort einlesen
      AkControllPort = Inp(I2C_Port.SCL)
      'SCL High
      Out I2C_Port.SCL, AkControllPort Xor SCL_Channel.Channel_SCL
      'ControllPort einlesen
      AkControllPort = Inp(I2C_Port.SCL)
      'SCL Low
      Out I2C_Port.SCL, AkControllPort Xor SCL_Channel.Channel_SCL
      
    I2C_ReadByte = Temp
    
    End Function
    Angehängte Dateien Angehängte Dateien

  4. #4
    Erfahrener Benutzer Begeisterter Techniker Avatar von Andre_S
    Registriert seit
    26.06.2005
    Beiträge
    357
    Hallo Frank,

    da muss ich passen. Ich hatte gehofft, dass Du eine fertige Library verwendest. Hier fehlt mir einfach die Umgebung um was sinnvolles beitragen zu können.
    Aber eventuell kann jemand anderes weiterhelfen.

    Hast Du denn schon mal versucht 2-3 verschiedene Bytes in nacheinander folgende Speicherstellen zu schreiben. Wäre interessant was Du dann liest...


    Gruß André

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    29.11.2005
    Ort
    57334 Bad Laasphe
    Alter
    53
    Beiträge
    8
    Hallo André,
    ja ich habe schon verschiedene Werte hintereinander in verschiedene Speicherzellen geschrieben.

    Und den letzten Wert kann ich dann aus allen Speicherzellen eines HiAdress Bereiches auslesen.

    Ich werde es wohl erstmal mit einem anderen I2C IC probieren ich dachte an den PCF 8574.

    Wenn es damit klappt, dann sollte es hiermit auch klappen.

    Die Idee des ganzen war eigendlich einen I2C Multimaster mit 8 Kanälen zu Programieren. Zum Schluß möchte ich mehrere TMC222 ansteuern. Das zu meinen Ilusionen.

    Aber nochmals vielen Dank

    Gruß Frank

Berechtigungen

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

Solar Speicher und Akkus Tests