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:
Code:
' 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:
Code:
' 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
Lesezeichen