PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : I2C zwischen Atmegas 88



High Light
06.01.2010, 19:24
Hallo zusammen,

die die mich schon kenne, wissen dass ich hauptsächlich mit dem Bau
eines Hexapods beschäftigt bin. Dieser ist im Moment im mechanischen
Teil fertig und nun folgt die Programmierung. (Hexapod unter dem
Thema "Erster Hexapod").

So mein Problem im Moment liegt bei I2C.
Als erster Meilenstein soll der Master einen Status an 3 Slaves senden,
welche darauf hin eine LED einschalten.
Es handelt sich bei allen 4 Controllern um Atmega88. Für I2C nehme ich
die hardwareseitig vorhanden Pins.

Jetzt mal der Code für den Master. Wäre klasse wenn sich jemand den Code
durchsehen könnte und mir sagen könnte, was ich anderes schreiben muss.



$regfile = "m88def.dat"
$crystal = 16000000
$baud = 9600

$lib "I2c_twi.lbx"

Config Twi = 400000


Const Slave1 = &HC1 'I2C Adresse slave1
Const Slave2 = &HC2 'I2C Adresse slave2
Const Slave3 = &HC3 'I2C Adresse slave3


Dim Status As Byte

Wait 2 'Warte 2 Sekunden
I2cinit 'Bus initialisieren

Do

Status = 1

I2cstart
I2cwbyte Slave1 'Slave1 ansprechen
I2cwbyte Status 'Status
I2cstop

Waitms 1000

I2cstart
I2cwbyte Slave2 'Slave2 ansprechen
I2cwbyte Status 'Status
I2cstop

Waitms 1000

I2cstart
I2cwbyte Slave3 'Slave3 ansprechen
I2cwbyte Status 'Status
I2cstop

Waitms 1000


Loop

End





MfG High Light

linux_80
06.01.2010, 23:36
Hallo,

die Slaveadressen passen so nicht, weil das erst Bit für Read/Write benutzt wird.
Eine Adresse in dem Bereich würde dann eine dieser sein:
&HC0, &HC2 o. &HC4

High Light
07.01.2010, 19:59
Ich steh auf dem Schlauch!!!

Welches erste Bit steht für Read/Write?
un dwarum gehen alle Adressen bis auf &HC1???
Welche Adressen könnte ich den noch verwendenden?

Des weiteren unterscheidet man Read- und Write- Adressen?

Gruß High Light

021aet04
07.01.2010, 20:46
Wenn du dich über I2C informierst steht z.B. im Wissensbereich
http://www.rn-wissen.de/index.php/I2C

Die Adresse besteht aus 7bit + 1bit für R/W. Die ersten 7bit sind für die Adresse, das 8te Bit ist das R/W Bit.
Wenn du jetzt z.B. den PCF8583 verwendest ist die Adresse für schreiben
1010 00A0R/W => 1010 ist die Basisadresse, A0 ist die Adresse, die man Ändern kann (mittels Anschluss vom PCF8583) und das R/W Bit.
Wenn man A0 auf GND legt lautet die Adresse für lesen: 1010 0000 = hexA0
Für schreiben: 1010 0001 = hexA1

Am Besten ist es, wenn du in einem DB nachsiehst. Dort ist immer ein Diagramm mit der Datenübertragung.

Ich könnte dir einen Quellcode (in C) posten, den ich heute geschrieben habe um die I2C Adressen auszulesen.

MfG Hannes

High Light
08.01.2010, 08:04
Ok, danke jetzt wird das mal klarer.
Das Programm hilft mir nicht weiter,
da ich ja im Moment nur Atmegas88 verwende.
Da kann ich ja dann die Adressen selber festlegen oder?
Dass heißt ich gebe zum Beispiel dem Slave1 die Adresse:

Const Slave1 = &HC1

Mit der kann ich dann schreiben oder?
Möchte ich aber lesen heißte es dann:

Const Slave1 = &HC0

Habe ich dass so richtig verstanden?

Gruß High Light

021aet04
08.01.2010, 15:22
Nicht ganz. Im Link, den ich gepostet habe ( http://www.rn-wissen.de/index.php/I2C ) steht unter http://www.rn-wissen.de/index.php/I2C#Aufbau_einer_7-Bit-Adresse
Dieses letzte Bit wird als R/W Bit bezeichnet (0 steht für "schreiben", 1 für "lesen").

Das würde bedeuten die Schreibadresse wäre 0xC0 (&HC0) und die Leseadresse 0xC1 (&HC1).

MfG Hannes

High Light
08.01.2010, 20:13
Oh ich glaube da habe ich etwas verdreht^^.
So hatte ich es eich au gemeint.
Danke für die Hilfe.
Dann werde ich mich mal am Sonntag an den
Code für den Slave machen.
Wäre klasse, wenn ihr den dann auch mal durchsehen könntet.

Gruß High Light

High Light
13.01.2010, 19:49
Ok ich bin am ausprobieren und suchen und muss sagen,
Ich checks gar net, wie ich den Code für den Slave schreiben
muss.
Weil ich versteh gerad gar nix, und finde tue ich au nix fürs Slaves.
Kann mir jemand weiter helfen?

Das hier ist das einzige was ich gefunden hab:
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=51427&highlight=i2c
Kann ich dies überhaupt in meinem Fall verwenden???
Wenn nein? Wie dann?

Noch eine zweite Frage, muss ich beim Master auch angeben welche Pins verwendet werden sollen?

Gruß High Light

High Light
19.01.2010, 20:12
Kann mir den keiner weiterhelfen?

Gruß High Light

guenter1604
19.01.2010, 20:46
Hier habe ich mal einen TWI Slave Transmitter gebaut

http://www.gerold-online.de/cms/wheelie/mein-wheelie/gearsensoren.html

High Light
18.06.2010, 10:33
Hallo zusammen,

da bin ich mal wieder seit langer Zeit,
und jetzt soll es mal endlich weiter gehen!!!


Hier habe ich mal den Quellcode für den Master:



$regfile = "m88def.dat"
$crystal = 16000000
$baud = 9600

$lib "I2c_twi.lbx"

Config Twi = 400000


Const Slave1 = &HC0 'I2C Adresse slave1
Const Slave2 = &HC2 'I2C Adresse slave2
Const Slave3 = &HC4 'I2C Adresse slave3


Dim Status As Byte

Wait 2 'Warte 2 Sekunden
I2cinit 'Bus initialisieren

Do

Status = 1

I2cstart
I2cwbyte Slave1 'Slave1 ansprechen
I2cwbyte Status 'Status
I2cstop

Waitms 1000

I2cstart
I2cwbyte Slave2 'Slave2 ansprechen
I2cwbyte Status 'Status
I2cstop

Waitms 1000

I2cstart
I2cwbyte Slave3 'Slave3 ansprechen
I2cwbyte Status 'Status
I2cstop

Waitms 1000


Loop

End



Und hier den für einen Slave:



$regfile = "m88def.dat"
$crystal = 16000000
$baud = 9600

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

' 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, LEDs einschalten
If Neuesbyte <> 0 Then
Portd = 1 ' LEDs einschalten
End If

Loop

End


' Unterprogramme


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

End Sub


Würde dies nun so funktionieren, oder was muss ich noch ändern???
Muss ich die Pins auch konfigurieren?

Gruß High Light

Kampi
18.06.2010, 11:14
Du musst den einzelnen Controller per Config noch sagen welcher Pin SDA und welcher SCL ist.
Beispiel für nen Tiny2313
Config SCL = Portb.7
Config SDA = Portb.5

Das kopierst du einfach und passt die Ports auf deine jeweiligen Controller an. Du siehst ja im Datenblatt welcher Pin SCL und SDA ist.

High Light
18.06.2010, 16:11
Ok, danke schon mal.

Und der Rest passt dies schon soweit?
Da müssten doch noch Fehler drin sein oder?

Kampi
18.06.2010, 16:20
Ja der meckert beim compilieren rum aber ich finde im moment den Fehler noch nicht.

guenter1604
18.06.2010, 17:06
Hallo,

wenn du im Master mit:
$lib "I2c_twi.lbx"

die Hardware SPI benutzt, brauchst du doch keine Config SDA und Config SCL

im Slave fehlt das $lib "I2c_twi.lbx"

Günter

High Light
21.06.2010, 12:54
Danke schon mal, ich werde es mal so ausprobieren.
Hoffentlich funktioniert es.
Berichte euch sobald ich ein Ergebnis hab.

Gruß High Light

High Light
23.06.2010, 14:27
AAAAAAAAAAAAAllso, habe im Master Config SDA und SCL eingefügt,
dadurch bekomme ich keine Fehlermeldung mehr.
Ebenso habe ich die Libary im Slave eingefügt.

ABBERRR es geht nichts!!!

Weiß nicht warum, kann es auch damit zusammenhängen, dass ich mit der Demo-Version arbeite?????????
Oder sind andere Fehler im Programm???

Gruß High Light

guenter1604
23.06.2010, 14:46
AAAAAAAAAAAllllllssssoooo nochmal:

Config SDA und SCL == du willst Software I2C
$lib "I2c_twi.lbx" == du willst Hardware I2C
I2Cinit == du willst Software I2C

was denn nu??

Jada
23.06.2010, 21:05
Ich habe kurz ne frage,
damit ich es richtig verstehe, ich muss die beiden controler mittels scl und sda anschließen oder?

MfG Jada

High Light
25.06.2010, 13:06
Ich brauch Hardware I2C, weil ich die standartmäßigen Pins
vom Atmege 88 benutzen muss.

Pin 27 = SDA
Pin 28 = SCL

Könntest du mir bitte verraten was ich nun alles ändern muss?

Hat Hardware oder Software I2C Vor- oder Nachteile?

Gruß High Light

High Light
29.06.2010, 16:02
Was muss ich ändern???????? :-s :-s :-s :-s :-s

High Light

High Light
28.12.2010, 17:53
Hallo zusammen,

lang lang ist es her, dass ich mich um dieses Thema gekümmert hab,
aber jetzt will ich es endgültig abschließen!!!
und zwar hab ich hier den Slave- und den Master-Code,
wär klasse, wenn ihr mir sagen könntet, warum es nicht geht!!!

Zur Funktion, der Master soll im Sekundentakt, abwechselnd 100 und 10 an den Slave senden. Bei 10 soll die StatusLED am Slave aus- und bei 100 eingeschlalten werden.
Aber es geht nichts!!!

Mastercode:


$regfile = "m88def.dat"
$crystal = 16000000

Declare Sub Twi_send_byte(byval Slave As Byte , Zeichen As Byte)

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

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

Dim Wert As Byte 'Wertvariable

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


' Hauptschleife
Do
Wert = 100
Call Twi_send_byte(&Hc0 , Wert)
Waitms 1000

Wert = 10
Call Twi_send_byte(&Hc0 , Wert)
Waitms 1000

Loop

End

' Unterprogramme

' TWI send_byte
' sendet ein Byte und schliesst die Übertragung ab
Sub Twi_send_byte(byval Slave As Byte , Zeichen As Byte)
Error = 0 ' Fehler zurücksetzen

' 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 And &HFE ' slave adresse + Write
Twcr = &B10000100 ' TWINT löschen, Byte senden

' warten bis TWINT gesetzt ist
Gosub Twi_wait_int

' Slave hat sich gemeldet
If Twi_status = &H18 Or Twi_status = &H20 Then
Twdr = Zeichen ' Daten
Twcr = &B10000100 ' TWINT löschen, Byte senden

' warten bis TWINT gesetzt ist
Gosub Twi_wait_int

' Zeichen wurden gesendet
If Twi_status = &H28 Or Twi_status = &H30 Then
Error = 0 ' kein Fehler
Else
Error = Twi_status ' Fehler
End If

Else
' kein slave
Error = Twi_status ' Fehler
End If

' STOPbedingung kommt hier immer im Ablauf, egal welcher Status
Twcr = &B10010100 ' TWINT löschen, 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 löschen, Bus freigeben
Error = Twi_status ' Fehler
End If

End Sub

' 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


Slavecode:


$regfile = "m88def.dat"
$crystal = 16000000 !



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

Config Portd.7 = Output 'StatusLED
Statusled Alias Portd.7
Statusled = 1



' 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 Wert 100 gesendet, dann StatusLED anschalten
If Twi_data = 100 Then
Statusled = 0 ' StatusLED anschalten
End If

'wenn Wert 10 gesendet, dann StatusLED ausschalten
If Twi_data = 10 Then
Statusled = 1 ' StatusLED ausschalten
End If

Loop

End


' Unterprogramme


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

End Sub


Habt ihr eine Idee???

Grüße High Light

High Light
30.12.2010, 14:53
Also der Code ist richtig,
es lag an der Hardware, hab die Pullups getauscht
und jetzt geht es.

Gruß High Light

Basti1204
31.12.2010, 10:59
Hi, ich versuch momentan das gleich wie du nur dass ich einen Atmega32 mit Atmega88 verbinden will. Außerdem habe ich den Takt auf int 8Mhz laufen.
weiss zufällig jemand was ich dann beim Master TWBR eingebn muß??

Was für Pullups hast du drann bei mir sind es 10k??

High Light
31.12.2010, 11:27
Also beim TWBR kann ich dir leider nicht weiterhelfen,
hab dies nämlich nur kopiert und gehoft dass es geht :-D

Als Pullups hab ich jetzt 2,2 kOhm drin.

Grüße High Light

Basti1204
31.12.2010, 11:51
hm und was hattest du als es nicht ging??

Basti1204
31.12.2010, 13:56
ok hat sich erledigt ein defekter Pin war schuld, Danke.

Hab mal ein kleines Bild vom Oszi dran gehängt.
Achja Die Pullups waren bei mir egal lediglich die Flanken haben sich
ein wenig geändert.

!*sascha*!
08.01.2011, 14:13
Hi,


ich baue grad eine Servo-Steuerung über I2C! Also die Komunikation zwischen 2 IC´s gehtbei mir! hier mal der Code!

Slave:

$regfile = "m8def.dat" ' specify the used micro
$crystal = 12000000 ' used crystal frequency
$baud = 19200 ' use baud rate
$hwstack = 32 ' default use 32 for the hardware stack
$swstack = 32 ' default use 32for the SW stack
$framesize = 40 ' default use 40 for the frame space



'SCL is PORTD.4 (T0)
'SDA is PORTD.2 (INT0)
'Use 10K pull up resistors for both SCL and SDA

Config I2cslave = &B01000000 ' same as &H40


Dim Bfake As Byte



Do

Loop



I2c_master_needs_data:

Bfake = 60

_a1 = Bfake

Return


'When the master writes a byte, the following label is always called
'It is your task to retrieve variable _A1 and do something with it
'_A1 is register R16 that could be destroyed/altered by BASIC statements
'For that reason it is important that you first save this variable

I2c_master_has_data:

Bfake = _a1

Print "Data: " ; Bfake


Return

_slave_address = &H40 + Switches ' set the proper address

Master:



$regfile = "m16def.dat"
$framesize = 32
$swstack = 32
$hwstack = 32
$crystal = 4000000




'or use the TWI !
Config Scl = Porta.1
Config Sda = Porta.2



Do


I2cstart
I2cwbyte &H40
I2cwbyte &H91

I2cstop

Wait 3

I2cstart
I2cwbyte &H40
I2cwbyte &H3C
I2cstop

Wait 3


Loop