Hallo,

da die Beispiele im Wiki wohl nicht immer so ganz optimal für Einsteiger zu überschauen sind, bzw. für den weiteren Ausbau etwas zu einfach gehalten sind, hab ich ein Beispiel zusammengebaut, in dem das RN-Mega8 I2C-Slave ist, und das RN-Control Mega32 der Master.
Der Master ist per UART mit dem PC verbunden, über den man Daten eingeben kann, die dann zum I2C-Slave gesendet werden.
Am RN-Mega8 habe ich 2 Servos hängen, die entsprechend den Werten die man am PC eingibt positioniert werden.

I2C-Slave:
Code:
$regfile = "M8def.dat"                                 ' the used chip
$crystal = 16000000                                    ' frequency used
'$baud = 9600    ' brauchen wir nicht

Waitms 100

' TWI init
Gosub Twi_init_slave

Config Servos = 2 , Servo1 = Portb.1 , Servo2 = Portb.2 , Reload = 8

' Ports für Servo auf Ausgang
Config Portb.1 = Output
Config Portb.2 = Output
Config Portd = Output

' Musik, wegen Stimmung usw. :-)
Sound Portb.0 , 300 , 450                              ' BEEP

Servo(1) = 100
Servo(2) = 100

Const Maxanzahlbyte = 10                               ' Wenn mehr Zeichen kommen werden diese verworfen !
Dim Messagebuf(maxanzahlbyte) As Byte
Dim Anzahlbuf As Byte                                 ' Anzahl Zeichen die gesendet wurden

Dim Neuemsg As Byte                                    ' zeigt an wenn eine neue Message gültig ist

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

Const Eigene_slave_adr = &H40                          ' Adresse evtl. Anpassen

' wegen der Servos, TWI braucht das hier nicht
Enable Interrupts

Twi_data = 0
Neuemsg = 0                                            ' Paket ungültig
Anzahlbuf = 0                                          ' Anzahl empfangener Bytes

Portd = &HFF                                           ' alle LEDs aus

'Print "M8 servo test"
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

        Portd = Not Twi_status                         ' test auf die LEDs

        Select Case Twi_status

            ' Slave Adress received, wir sind gemeint !
            Case &H60 :
                Twcr = &B11000100                      ' TWINT löschen, erzeugt ACK
                Anzahlbuf = 0
                Neuemsg = 0                            ' Flag für Message ungültig

            ' Byte mit ACK
            Case &H80 :
                If Anzahlbuf < Maxanzahlbyte Then
                    Incr Anzahlbuf                     ' zähler +1
                    Messagebuf(anzahlbuf) = Twdr
                End If
                Twcr = &B11000100                      ' TWINT löschen, erzeugt ACK

            ' Stop oder restart empfangen
            Case &HA0 :
                Twcr = &B11000100                      ' TWINT löschen, erzeugt ACK
                ' es müssen 3 Byte sein, damit das Paket OK ist
                If Anzahlbuf = 3 Then
                    Neuemsg = 1                        ' Flag für Message gültig
                Else
                    Neuemsg = 0                        ' Flag für Message ungültig
                End If

            ' letztes Byte mit NACK, brauchen wir nicht
            Case &H88 :
            Case &HF8 :
            ' Fehler, dann reset TWI
            Case &H00 :
                Twcr = &B11010100                      ' TWINT löschen, reset TWI

            ' was anderes empfangen, sollte nicht vorkommen
            Case Else :
                Twcr = &B11000100                      ' TWINT löschen, erzeugt ACK

        End Select

    End If

    ' ein gültiges Paket angekommen
    If Neuemsg = 1 Then
        Neuemsg = 0                                    ' Flag wieder löschen
        ' nur wenn das erste Zeichen ein "S" ist tun wir was damit !
        If Messagebuf(1) = "S" Then
            Servo(messagebuf(2)) = Messagebuf(3)
            Sound Portb.0 , 300 , 450                  ' Roger-BEEP
        End If
    End If

    Waitms 10

Loop

End

' TWI als slave aktivieren
Twi_init_slave:
    Twsr = 0                                                ' status und Prescaler auf 0
    Twdr = &HFF                                             ' default
    Twar = Eigene_slave_adr                                 ' Slaveadresse setzen
    Twcr = &B01000100                                       ' TWI aktivieren, ACK einschalten
Return
Angepasst werden kann die Slaveadresse mit Eigene_slave_adr,
und die max. Grösse des Paketes bei Maxanzahlbyte.

I2C-Master:
Code:
$regfile = "M32def.dat"                                ' the used chip
$crystal = 16000000                                    ' frequency used
$baud = 9600

$lib "i2c_twi.lbx"                                     ' Für Hardware TWI

Waitms 100

Config Twi = 400000                                   ' setzt die TWI-Register
' Twsr = 0                                               ' Status reset
' Twbr = 12                                              ' Bus Geschwindigkeit 400kHz @ 16MHz
TWCR = &B00000100                                      ' TWI Modul aktivieren, nur TWEN

Dim Nr As Byte                                         ' Servo-Nr
Dim Position As Byte                                   ' Position

Const Servom8w = &H40                                  ' Slaveadresse
Const Servom8r = &H41

Sound Portd.7 , 300 , 450                              ' BEEP

' Startausgabe
Print
Print "TWI Master Servo einstellen"

Print "Nr. und Wert fuer Servo eingeben :"

Do

    Print "Nr : " ;
    Input Nr
    Print "Position : " ;
    Input Position

    ' Es gibt nur 2 Servos mit Nr 1 und 2
    If Nr > 0 And Nr < 3 Then

        I2cstart
        I2cwbyte Servom8w
        I2cwbyte &H53                                  ' "S" Kennzeichen für Servo ansteuern
        I2cwbyte Nr
        I2cwbyte Position
        I2cstop

        ' Fehler-Flag ausgeben, sollte immer 0 sein, dann war kein Fehler
        Print "Err " ; Err
    End If

Loop

End
Angepasst werden muss nur die Slaveadresse bei Servom8w.
Da vom Slave nichts gelesen werden kann braucht man die Lese-Adresse eigentlich nicht.
Evtl. kann man die Busgeschwindigkeit bei TWBR ändern, falls andere Quarz- oder Busfrequenzen gewünscht sind. Verwendet man Config TWI = .. rechnet das Bascom für einen aus, Anhand der Angabe bei $crystal.

Das Telegramm-Paket, dass der Master zum Slave sendet ist so aufgebaut:
1. Zeichen: ein "S" (grosses S) als Kennzeichen das ein Servo angesteuert werden soll, alle anderen werden verworfen,
2. Zeichen: die Servo-Nr
3. Zeichen: die Position des Servos, theoretisch von 0 bis 255, aber je nach Servo meistens im Bereich von 50 bis 200 !

Die Funktion des Slave nochmal als Text:
In der Do..Loop-Schleife wird immer das Flag TWINT geprüft, das anzeigt, dass Daten über TWI angekommen sind, anschließend wir der Status aus TWSR ausgelesen, und per Select..Case entsprechend verzweigt, da wir hier nur einen Slave-Receiver haben, braucht man nur die hier angegebenen Statuscodes verwenden.
Wird nach einer Start-Sequenz die eigene Slaveadresse angesprochen wird der Zähler für die Anzahl der empfangenen Zeichen auf 0 zurückgesetzt.
Es wird grundsätzlich jedes Byte mit ACK quittiert egal ob der Puffer schon voll ist oder nicht, ist der Puffer voll werden die nachfolgenden Bytes verworfen !
Wird ein STOP oder RESTART empfangen, wird ein weiteres Flag gesetzt (Neuemsg) falls die Paketgrösse passt, ansonsten ist das Pakte ungültig und wird verworfen. Will man unterschiedliche Paketgrössen empfangen, muss man diese Abfrage natürlich hier rausnehmen, und kann sich zB. nur an das 1. Zeichen im Paket halten was zu tun ist.
Ist das Flag Neuemsg auf 1, wird in der nächsten If-Abfrage die Auswertung des empfangenen Pakets gestartet, und das Flag wieder zurückgesetzt.
Beginnt das Paket mit einem "S" ist es für uns interessant, und wir stellen den entsprechenden Servo (aus Byte 2) auf den neuen Wert (aus Byte 3).
Jetzt ist die Schleife beendet, und es beginnt alles wieder von vorne, solange das Flag TWINT nicht gesetzt ist, muss sich der AVR nur um die PWM-Ausgabe für die Servos kümmern, das geschieht per ISR, und deshalb können wir hier die Do..Loop-Schleife endlos laufen lassen.