PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : I2C Master Slave Probleme



Enterprise
03.03.2010, 21:12
Hallo zusammen,

ich möchte über I2C Daten auslesen und senden.
1. von einem Srf08 Ausgabe auf dem Uart RS232
2. von einem Slave Atmel8 ohne Quartz
3. Display LCD03

Mit dem Script vom Master kann ich den Srf08 auslesen.
Nun habe ich das Script von RN Wissen für Slave genommen.

Beim Slave soll eine LED Blinken, im selben Rhythmus wie die LED bei Master.
Das macht es nicht.
Beim Slave blinkt die LED schneller.
Wenn das dann funktioniert möchte ich noch Tasten und Schalter auslesen.
Diese sollte erst später besprochen werden.

Die Displayansteuerung ist nicht implementiert.

Das zweite Problem ist wenn der Slave angesteckt wird, dann misst der Srf08 nicht mehr.

Hier mein Master Script:




$crystal = 16000000
'$crystal = 3868000
$regfile = "m8def.dat"
$baud = 9600

Declare Function Srf08_entfernung(byval Srf08_slaveid As Byte) As Integer
Declare Sub Srf08_reichweite(byval Srf08_slaveid As Byte , Byval Reichweite As Word)
Declare Sub Srf08_verstaerkung(byval Srf08_slaveid As Byte , Byval Srf08_verstaerkung As Byte)
Declare Function Srf08_firmware(byval Srf08_slaveid As Byte) As Byte

Declare Sub Addieren
Declare Sub Subtrahieren

Config Portb = Output

Config Scl = Portc.5
Config Sda = Portc.4

Portc.1 = 1 'Taster Addieren
Portc.2 = 1 'Taster Subtrahieren

Const Adr_ta1_w = 6
Const Adr_modul_led_w = &H40 'Slave Adresse LED schreiben
Const Adr_modul_led_r = &H41 'Slave Adresse LED lesen
Const Displ_w = 198 'Display Adresse zum Schreiben
Const Displ_r = 199

Led Alias Portb.5

Dim Text As String * 20 'hier kommt der Anzeige-Text rein
Dim Stemp As String * 20

Dim B As Byte 'Variable zur Bestimmung der Textlänge
Dim C As Byte 'Hilfsvariable für FOR Schleife
Dim D As Byte 'D-Position auf dem Display
Dim E As Byte 'E-Position auf dem Display
Dim F As Byte 'Zählvariable für die Leuchtdauer des Displays
Dim G As Byte 'Zählvariable auf 1Sekunde für die Ausgabe Srf08
Dim Wert1 As Byte 'Wert1
Dim Wertled1 As Byte 'WertLed1

Dim Entfernung As Integer 'Srf08 Entfernung
Dim V As Byte 'Srf08 Verstärkung

Dim Tasblo(10) As Byte

Dim Ledgr As Byte 'LEDgr zum Slave Senden

Print
Print "I2C-Mastermodul von Enterprise V1.1"
Print


Wait 3 'Warte 3 Sekunden
I2cinit
Print " "
Print "SRF 08 Firmware Version: " ; Srf08_firmware(&He2)
Print " "

Srf08_reichweite &HE2 , 1000 'Reichweite in Zentimetern festlegen

' Verstärkungsfaktor ändern

' Srf08_verstaerkung &HE2 , 10 'Verstärkungsfaktor

V = 1
G = 1

Wert1 = 1
Wertled1 = 1


'************************************************* ******************************
'------------------- Hauptschleife ----------------------

Do
Waitms 100

Toggle Led ' LED Rot blinkt alle 100ms

Toggle Wertled1 ' Der Wert1 ändert alle 100ms von 1 auf 254
Gosub Slaveled1


' Srf08
If G = 10 Then
Entfernung = Srf08_entfernung(&He2)
Srf08_verstaerkung &HE2 , V 'Verstärkungsfaktor

Print "Verstaerkung: " ; V ; " " ; "Entfernung: " ; Entfernung ; " cm"
' V = V + 3
G = 1
Else
G = G + 1
End If

Loop

End

' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
'************************************************* ******************************
'------------------------ Slave LED senden 1 ---------------------
Slaveled1:

I2cstart
I2cwbyte Adr_modul_led_w
I2cwbyte 0
I2cwbyte Wertled1
I2cstop

Return

'-----------------------------------------------------------------
'-------------- SRF08 --------------------------------------------
'-----------------------------------------------------------------

Function Srf08_entfernung(byval Srf08_slaveid As Byte) As Integer
Local Lob As Byte
Local Hib As Byte
Local Firmware As Byte
Local Temp As Byte
Local Srf08_slaveid_read As Byte

Srf08_slaveid_read = Srf08_slaveid + 1

'Messvorgang in starten
I2cstart
I2cwbyte Srf08_slaveid
I2cwbyte 0
I2cwbyte 81 'In Zentimetern Messen
I2cstop

Warteaufmessung:
Waitms 1
Firmware = Srf08_firmware(&He2)
If Firmware = 255 Then Goto Warteaufmessung

I2cstart
I2cwbyte Srf08_slaveid
I2cwbyte 2 'Leseregister festlegen
I2cstop


I2cstart
I2cwbyte Srf08_slaveid_read
I2crbyte Hib , Ack
I2crbyte Lob , Nack
I2cstop


Srf08_entfernung = Makeint(lob , Hib)
End Function



'Messreichweite in cm festlegen
Sub Srf08_reichweite(byval Srf08_slaveid As Byte , Byval Reichweite As Word)
Local Wert As Word
Local Temp As Byte

Wert = Reichweite / 4 'Ungefähre Registerberechnung
Temp = Low(wert)

I2cstart
I2cwbyte Srf08_slaveid
I2cwbyte 2 'Register
I2cwbyte Temp
I2cstop

End Sub


'Verstärung festlegen
Sub Srf08_verstaerkung(byval Srf08_slaveid As Byte , Byval Srf08_verstaerkung As Byte)
I2cstart
I2cwbyte Srf08_slaveid
I2cwbyte 1 'Register
I2cwbyte Srf08_verstaerkung
I2cstop

End Sub



Function Srf08_firmware(byval Srf08_slaveid As Byte) As Byte
Local Firmware As Byte
Local Srf08_slaveid_read As Byte

Srf08_slaveid_read = Srf08_slaveid + 1

I2cstart
I2cwbyte Srf08_slaveid
I2cwbyte 0 'Leseregister festlegen
I2cstop

I2cstart
I2cwbyte Srf08_slaveid_read
I2crbyte Firmware , Nack
I2cstop

Srf08_firmware = Firmware
End Function




Und hier das Slave Script:



$regfile = "m8def.dat" ' the used chip
'$crystal = 7372800 ' frequency used
'$baud = 9600 ' keine baud rate angeben !

Config Portd = Output ' kompletter PortD als Ausgang

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

Dim Neuesbyte As Byte ' Bytemerker

Declare Sub Twi_init_slave

Twi_data = 0
Call Twi_init_slave ' TWI aktivieren

' alle LEDs ein
Portd = 0

' Hauptschleife
Do
' hier könnte ihr Code stehen


' Merker zurücksetzen
Neuesbyte = 0

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

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

' wurde ein Byte geschickt
If Twi_status = &H80 Or Twi_status = &H88 Then
Twi_data = Twdr ' neue Daten merken
Neuesbyte = 1 ' merken das ein neues Byte da ist
End If

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

' wenn ein neues Byte gekommen ist, dieses an PortD ausgeben
If Neuesbyte <> 0 Then
' Portd = Twi_data ' Daten auf PortD ausgeben
Print
If Twi_data = 254 Then
Portd.0 = 0
End If

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



Kann mir da jemand weiter helfen.


mfg
Enterprise

Enterprise
04.03.2010, 21:06
Hallo zusammen,

habe meinen Fehler gefunden.
Ich habe dann nochmals alles untersucht.
Es lag dann an meinem I2C Bus Kabelanbruch.

Durch das viele Testen habe ich jetzt zwei Slaves mit Atmel8.
Der eine mit dem internen Takt und der andere mit 16Mhz

Nun blinkt auf beide Slaves die Kontroll LED.


Jetzt habe ich mal eine Frage?

Die Hauptschleife wird alle 100ms durchlaufen.
Wie muss jetzt das Programm aussehen, wenn man zu
einem Slave LED's ein oder aus schalten möchte, vom Srf08 Daten holen,
auf LCD03 anzeigen und die12er Tastatur abfragen und einen weitern Slave mit Taster und Schaltern und GP12D abfragen und zwei
Motor Treiber ansteuern.
Und eventuell Ausgabe auf dem Uart.

Da bekomme ich ja Zeitprobleme mit dieser weiße?

Wie muss ich an dieses Thema dran gehen?


mfg
Enterprise