Archiv verlassen und diese Seite im Standarddesign anzeigen : Probleme I2C und ATMEL 24C256
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 ?:-k
Vielen Dank schonmal für eure Unterstützung.
fg
Frank
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é
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
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
'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
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
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é
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
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.