PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : I2C und Word



XT600SM
01.02.2009, 20:16
Ich kämpfe nun seit drei Tagen mit dem Lesen und Schreiben auf einen 24c64.

Bin nun soweit das ich ein Byte geziehlt schreiben und lesen kann, allerdings würde ich viel lieber ein Word geziehlt schreiben und lesen.

Mit den Prog kann ich auf Tastendruck ein Wert (Word) an den 24C64 senden,
allerdings beim lesen geht es nur mit Werten bis 255 (also Byte)

Was muss ich noch ändern?



$regfile = "m8def.dat"
$crystal = 8000000


Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portb.5 , Rs = Portb.4
Config Lcd = 16 * 2
Cursor Off


Config Scl = Portc.5 'PIN für I2C Bus
Config Sda = Portc.4
Config Pinc.3 = Input
Config Pinc.1 = Input
Config Portc.2 = Output
Config Portc.0 = Output

Portc.3 = 1 'Pullup ein
Portc.1 = 1 'Pullup aus

Dim X As Word
Dim A As Byte
Dim B As Byte
Dim Lesen As Word
Cls

Main:

Do

X = X + 5
A = 1
B = 1
If Pinc.3 = 0 Then
Portc.2 = 1
Gosub Eschreiben
End If

If Pinc.3 = 1 Then
Portc.2 = 0
End If

If Pinc.1 = 0 Then
Portc.0 = 1
Gosub Elesen
End If

If Pinc.1 = 1 Then
Portc.0 = 0
End If

Loop

Eschreiben: '---- schreibe in EEprom ----

I2cstart 'Start I2C
I2cwbyte &HA0 'Sende Slave Adresse
I2cwbyte A 'Sende Speicheradresse High
I2cwbyte B 'Sende Speicheradresse LOw
I2cwbyte X 'Sende Wert
I2cstop 'Stop I2C
Waitms 10 'warte 10ms

Locate 1 , 1
Lcd "ins EE= " ; X ; " " ' Ausgabe der geschriebenen Werte am LCD
Waitms 500

Return

Elesen: '--- lesen vom EEprom ----

I2cstart 'Start I2C
I2cwbyte &HA0 'sende Slave Adresse
I2cwbyte A 'sende Speicheradresse High
I2cwbyte B 'sende Speicheradresse Low

I2cstart 'Start I2C
I2cwbyte &HA1 'sende Slave Adresse +1 für Lesen
I2crbyte Lesen , Nack 'lese Adresse vom EEprom
I2cstop 'Stop I2C 'Stop I2C

Locate 2 , 1
Lcd "Lese EE= " ; Lesen ; " " 'Ausgabe der EEprom Werte
Waitms 500

Return

End

linux_80
01.02.2009, 22:29
Hallo,

ein Word sind 2 Byte, Du musst diese beiden Bytes hintereinander senden bzw. lesen.
zB mit High(Word) und Low(word) bekommst Du die einzelnen Bytes aus dem Word,
mit makeint sollte man eins aus 2 Bytes bauen können (nach dem lesen).

Siehe Hilfe zu Bascom zu den hier vorgeschlagenen Befehlen.

XT600SM
02.02.2009, 10:52
Ja die Bascomhilfe und das Board habe ich schon rauf un runter studiert.

Aber irgend wie habe ich da eine Gedanken blockade.

Wenn ich den Wert 125 abspeichern will dann mach ich das so.

I2cstart 'Start I2C
I2cwbyte &HA0 'Sende Slave Adresse
I2cwbyte 1 'Sende Speicheradresse High
I2cwbyte 1 'Sende Speicheradresse LOw
I2cwbyte 125 'Sende Wert
I2cstop 'Stop I2C

Wenn ich nun den Wert 12534 abspeichern möchte, wie mache ich das ?

Oder teilt er das dann Automatisch in die High und Low Adresse auf?

linux_80
02.02.2009, 20:22
Nein, dafür gibts die Befehle High und Low, damit sendet man die zwei Bytes hintereinander ans EEprom.
Beim lesen liest man einfach 2 Bytes ein, und setzt die mit Makeint in der richtigen Reihenfolge wieder zusammen, und kommt auf den alten Wert. Sollte ein anderer Wert rauskommen, stimmt entweder die Reihenfolge bei Makeint nicht (einfach mal bei de Werte tauschen), oder es wurde von einer falschen Adrese gelesen.

Du musst die Bascom-Hilfe nicht rauf- und runterlesen, in diesem Fall hier erstmal nur diese drei Befehle von oben nach unten ;-)
Bei Makeint steht, wie man high und low übergibt, damit wieder der gewünschte Wert rauskommt.

zB so:

I2cstart 'Start I2C
I2cwbyte &HA0 'Sende Slave Adresse
I2cwbyte 1 'Sende Speicheradresse High
I2cwbyte 1 'Sende Speicheradresse LOw
I2cwbyte WertLow ' oder andersrum völlig egal
I2cwbyte WertHigh ' muss nur beim lesen in der gleichen Reihenfolge zusammengesetzt werden !
I2cstop 'Stop I2C

vom Prinzip her so wie beim senden der Speicheradresse.

kingmassivid
03.02.2009, 16:31
Ich erlaube mir jetzt mal, diesen Thread zu benutzen, geht aber genau um das gleiche Thema,
nämlich eine Word-Variable über I2C zu übertragen, nur in die andere Richtung.

Auf einem ATMEGA8 ist ein Slave implementiert, ein ATMEGA16 ist der Master,
der vom Slave einen (später mehrere) Werte auslesen soll.
Der Code ist aus dem Wiki-Artikel "TWI Praxis" übernommen und dann zugegebener maßen etwas zusammengepfuscht.

Hier der Code für den Slave:


' TWI-slave test
$regfile = "m8def.dat" ' the used chip
$crystal = 8000000 ' frequency used

Dim Twi_control As Byte ' Controlregister lokale kopie
Dim Twi_status As Byte
Dim Twi_data As Byte

Dim Count As Byte

Dim Wert As Word
Wert = &H1234

Dim Temp As Byte
Dim Count2 As Byte

Declare Sub Twi_init_slave

' Werte zurcksetzen
Count = 7
Count2 = 23
Twi_data = 0
Call Twi_init_slave ' TWI aktivieren


' Hauptschleife
Do



' schauen ob TWINT gesetzt ist
Twi_control = Twcr And &H80 ' Bit7 von Controlregister

If Twi_control = &H80 Then
Twi_status = Twsr And &HF8 ' Status

' will der Master ein Byte haben
If Twi_status = &HA8 Or Twi_status = &HB8 Then
'Temp = High(wert)
'Twdr = Temp
'Incr Count
Twdr = Count ' testwert +1
End If

' TWINT muss immer gelscht werden, damit es auf dem Bus weiter geht
Twcr = &B11000100
Twi_status = Twsr And &HF8
If Twi_status = &HA8 Or Twi_status = &HB8 Then
'Temp = Low(wert)
'Twdr = Temp
'Incr Count
Twdr = Count2
End If

' TWINT muss immer gelscht werden, damit es auf dem Bus weiter geht
Twcr = &B11000100 ' TWINT löschen, mit ACK
End If

Loop

End


' Unterprogramme


' TWI als slave aktivieren
Sub Twi_init_slave
Twsr = 0 ' status und Prescaler auf 0
Twdr = &HFF ' default
Twar = &H40 ' Slaveadresse setzen
Twcr = &B01000100 ' TWI aktivieren, ACK einschalten

End Sub

und der des masters:


' TWI Testprogramm
' mit Slave @ &H40


$regfile = "M16def.dat" ' the used chip
$crystal = 16000000 ' frequency used
$baud = 9600 ' baud rate

Declare Function Twi_read_byte(byval Slave As Byte) As Word

Dim Twi_control As Byte ' Controlregister lokale kopie
Dim Twi_status As Byte
Dim Twi_data As Byte
Dim Twi_read1 As Byte
Dim Twi_read2 As Byte

Dim B As Byte ' Zeichen von UART
Dim X As Byte ' Zeichen von TWI
Dim Error As Byte ' Fehlermerker

Dim Msg As Word

' TWI Init
Twcr = &B00000100 ' erstmal nur TWI aktivieren
Twsr = 0 ' Status und Prescaler Register
Twbr = 72 ' Bit Rate Register, 100kHz

' Startausgabe
Print "TWI Master Receiver"

' Hauptschleife
Do

' warten bis etwas ber UART kommt (egal welcher Wert, wird nur als Startbutton genutzt)
Input B

' ein Byte vom Slave holen
Msg = Twi_read_byte(&H40)

' Ausgabe, damit wir sehen was geschehen ist
Print "LSB: " ; Twi_read2
Print "MSB: " ; Twi_read1
Print Msg ;
Print " Error : " ;
Print Hex(error) ' error status Ausgeben

Loop

End

' Unterprogramme

' TWI read_byte
' holt ein Byte und schliesst die bertragung ab
Function Twi_read_byte(slave As Byte) As Word
Error = 0 ' Fehler zurücksetzen

Twi_read_byte = 0 ' Wert vorbelegen

' Startbedingung
Twcr = &B10100100 ' TWINT

' warten bis TWINT gesetzt ist
Gosub Twi_wait_int

' wenn Zugriff auf den Bus erlaubt, Slaveadresse ausgeben
If Twi_status = &H08 Or Twi_status = &H10 Then
Twdr = Slave Or &H01 ' slave adresse + Read
Twcr = &B10000100 ' TWINT lschen, Byte senden

' warten bis TWINT gesetzt ist
Gosub Twi_wait_int

' Slave hat sich gemeldet
If Twi_status = &H40 Then
Twcr = &B11000100 ' TWINT lschen, Byte senden
' ein ACK (TWEA = 1)
' warten bis TWINT gesetzt ist
Gosub Twi_wait_int

' ein Byte wurde empfangen
If Twi_status = &H58 Or Twi_status = &H50 Then
Twi_read1 = Twdr ' Daten lesen
Error = 0 ' kein Fehler
Else
Error = Twi_status ' Fehler
End If


'zweites lesen
Twcr = &B10000100 ' TWINT lschen, Byte senden
' kein ACK (TWEA = 0) senden, weil wir nur ein Byte lesen wollen

' warten bis TWINT gesetzt ist
Gosub Twi_wait_int

' ein Byte wurde empfangen
If Twi_status = &H58 Or Twi_status = &H50 Then
Twi_read2 = Twdr ' Daten lesen
Error = 0 ' kein Fehler
Else
Error = Twi_status ' Fehler
End If
Twi_read_byte = Makeint(twi_read2 , Twi_read1)

Else
' kein slave
Error = Twi_status ' Fehler
End If

' STOPbedingung kommt hier immer im Ablauf, egal welcher Status
Twcr = &B10010100 ' TWINT lschen, STOP senden
' nach einem STOP wird TWINT nicht mehr gesetzt,
' man darf/kann also nicht darauf warten !

Else
' Bus belegt, wird er wieder freigegeben
Twcr = &B10000100 ' TWINT lschen, Bus freigeben
Error = Twi_status ' Fehler
End If

End Function

' warten bis TWINT gesetzt ist, status auslesen
Twi_wait_int:
Do
Twi_control = Twcr And &H80
Loop Until Twi_control = &H80

Twi_status = Twsr And &HF8 ' status
' status nur zu Debugzwecken ausgeben, weil Bus sehr langsam wird !
' Print "Err " ; Hex(twi_status)
Return


Leider verhält sich das ganze jetzt garnicht so wie es soll,
in der Variante wie sie jetzt das steht, also das nicht auskommentierte,
sendet es zwei mal die 7 obwohl das zweite 23 seien sollte.
Wenn ich die Variante mit einer Variable verwende, die immer erhöht wird,
treten Sprünge auf wie:
LSB: 1
MSB:3
LSB:5
MSB:7

Wenn ich die Word Variable verwende, wie es ja eig. sein soll,
klappt das auch nicht wie gewollt.

Ich hab mir jetzt echt schon das Hirn zermartert, aber ich weiß nicht,
wie ich das hinkriegen soll, bitte helft mir.

Lukas

XT600SM
03.02.2009, 19:58
Also ich irgend wie kapier ich das nicht.


I2cstart 'Start I2C
I2cwbyte &HA0 'Sende Slave Adresse
I2cwbyte 1 'Sende Speicheradresse High
I2cwbyte 1 'Sende Speicheradresse LOw
I2cwbyte WertLow ' oder andersrum völlig egal
I2cwbyte WertHigh ' muss nur beim lesen in der gleichen Reihenfolge zusammengesetzt werden !
I2cstop 'Stop I2C

Dann versteh ich das so zb.


I2cstart 'Start I2C
I2cwbyte &HA0 'Sende Slave Adresse
I2cwbyte 1 'Sende Speicheradresse High
I2cwbyte 1 'Sende Speicheradresse LOw
I2cwbyte 123Low ' oder andersrum völlig egal
I2cwbyte 123High ' muss nur beim lesen in der gleichen Reihenfolge zusammengesetzt werden !
I2cstop 'Stop I2C

Wenn ich das aber so ein tippe, motzt Bascom schon beim übersetzen.

](*,)

TobiasBlome
23.11.2009, 17:15
Hi XT600SM,
hatte selbes Problem - das Word verschwand im eeprom und ich habs nicht wiedergefunden....
so geht´s:



$regfile = "m8def.dat" 'MEGA8-Deklarationen

$hwstack = 32
$swstack = 8
$framesize = 24


$crystal = 8000000 'intern 8MHz
$baud = 9600 'Baudrate definieren
'-------------------------------------------------------------------------------
'Ein / Ausgänge definieren:
'Ddrb = &B00111100 '0=Eingang
'Ddrc = &B1111111
Ddrd = &B01100011 '0=Eingang


'PullUps setzen:
'Portb = &B00000000 '1 = PullUp AKTIV
'Portc = &B0000000 '1 = PullUp AKTIV
'Portd = &B00000000 '1 = PullUp AKTIV

'-------------------------------------------------------------------------------
'Alias
Taster1 Alias Pind.2
Taster2 Alias Pind.3
Taster3 Alias Pind.4
Led1 Alias Portd.5
Led2 Alias Portd.6




'-------------------------------------------------------------------------------
'Variablen


'-------------------------------------------------------------------------------
'Timer
'Timer1 = 2x / sec bei 8MHz
'Config Timer1 = Timer , Prescale = 256 'Teiler
'Const Timervorgabe = 49910
'Enable Timer1
'Enable Interrupts

'-------------------------------------------------------------------------------
Dim Wert As Word 'eigendlicher Wert
Dim Wert1 As Byte 'Hilfswert1
Dim Wert2 As Byte 'Hilfswert2


Dim Lesen As Word 'Auslesen
Dim Lesenlow As Byte 'Hilfswert1
Dim Lesenhigh As Byte 'Hilfswert2

Dim Adresse As Word At $160 'Die Adresse als Word-Variable
Dim Low_adresse As Byte At $160 Overlay 'Zeiger auf das erste Byte
Dim High_adresse As Byte At $161 Overlay 'Zeiger auf das zweite Byte



'SDA und SCL definieren
Config Sda = Portc.4 ' I2C-Port festlegen
Config Scl = Portc.5 ' I2C-Port festlegen


Const Ext_eeprom = 162 'I2C Geräteadresse ggf. anpassen
Wert = 64998


'-------------------------------------------------------------------------------
'Für RS232:
'On Urxc Onrxd 'Interrupt-Routine setzen
'Enable Urxc 'Interrupt URXC einschalten
Enable Interrupts 'Interrupts global zulassen


'---------------------------------------------------------------------------------------------------------------
'---------------------------------------------------------------------------------------------------------------
Do

If Taster1 = 1 Then
'----schreiben----
For Adresse = 250 To 260 'Adresse geht über die Byte-Grenze
Incr Wert '1 bis Überlauf
Gosub Eeprom_schreiben
Print "schreiben ->Adres.=" ; Adresse ; "Wert=" ; Wert ; " " 'Anzeige vom schreiben
Waitms 500
Adresse = Adresse + 1 'weil ja immer 2 Bytes abgefragt werden
Next Adresse
End If


If Taster2 = 1 Then
'---lesen----
For Adresse = 250 To 260
Gosub Eeprom_lesen
Lesen = Makeint(lesenhigh , Lesenlow)
Print "lesen <-Adres.=" ; Adresse ; "Wert= " ; Lesen 'Anzeige vom lesen
Waitms 500
Adresse = Adresse + 1 'weil ja immer 2 Bytes abgefragt werden
Next Adresse
End If





Loop





'------------------------------------------------------
'- Byte (wert) auf EEprom Adresse (address) speichern -
'------------------------------------------------------
Eeprom_schreiben:
Wert1 = High(wert)
Print Wert1 ; " W1 "
Wert2 = Low(wert)
Print Wert2 ; " W2 "

I2cstart 'Start
I2cwbyte &HA0 'Sende Slavadresse
I2cwbyte High_adresse 'Sende Speicheradresse High
I2cwbyte Low_adresse 'Sende Speicheradresse LOW
I2cwbyte Wert2 'Sende Wert
I2cwbyte Wert1 'Sende Wert
I2cstop 'stop
Waitms 10
Return



'-----------------------------------------------------------------
'--- Byte (wert) von EEprom Adresse (address) lesen ---
'-----------------------------------------------------------------
Eeprom_lesen:

I2cstart 'Start
I2cwbyte &HA0 'Sende Slavadresse +1 für Schreiben
I2cwbyte High_adresse 'Sende Speicheradresse High
I2cwbyte Low_adresse 'Sende Speicheradresse Low

I2cstart 'Start
I2cwbyte &HA1 'Sende Slavadresse +1 für Lesen
I2crbyte Lesenhigh , Ack 'Lese Adresse vom EEprom
I2crbyte Lesenlow , Nack 'Lese Adresse vom EEprom
I2cstop 'Stop
Return


vielleicht hast du ja auch schon eine Lösung gefunden - der Beitrag ist ja schon etwas älter.... :-b