1

Montag, 20. September 2010, 21:57

I2C Multimaster

Hat hier jemand Erfahrungen mit I2C Multimastersystemen? Das treibt mich nämlich momentan ziemlich zur Verzweiflung...
Momentaner Aufbau: Zwei Mega8 und ein PCF8570 SRAM. Der eine Mega schreibt ins RAM, der andere holt die Daten dort wieder ab und stellt diese über RS232 dem PC zur Verfügung. Im Endausbau sollen es mehrere Megas sein die Daten schreiben derweil ein Mega die Daten ausliest und via USB einer PC-Anwendung zur Verfügung stellt. Soweit bin ich aber noch nicht mal im Ansatz, mit zwei Megas hakelts es schon dauernd und mit dreien geht dann nix mehr...

Der Testcode des schreibenden Megas:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
regfile = "m8def.dat"
$crystal = 8000000 

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

Config Twi = 100000                                         ' 100kHz, mehr schafft der 8570 nicht
Declare Sub Schreiben

Const Pcf_write = &B10100000                                'RAM write
Const Pcf_read = &B10100001                                 'RAM read

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

Dim Zahl As Byte

Zahl = 0
' Schleife um das Ram mit verschiedenen Werten zu füttern
Do
    Gosub Schreiben
    Incr Zahl
    If Zahl > 98 Then Zahl = 0
    Waitms 31                                                                   'Primzahl
Loop

Sub Schreiben:
    Twcr = &B00000100                                               'kann man sich eigentlich sparen
    I2cstart
    I2cwbyte Pcf_write
    Waitms 1
    I2cwbyte &B00000001                                              'Byte 1 schreiben
    waitms 1
    I2cwbyte Zahl
    Waitms 1
    I2cstop
    Twcr = &B00000000                                               's.o.
End Sub


Die eigentliche I2C-Kommunikation habe ich deshalb in eine Sub gepackt damit ich bei Fehlern (ERR=1) diese über ein simples RETURN wieder verlassen kann. Die Fehlerabfrage ist hier jetzt nicht drin, da habe ich aber schon verschiedenste Varianten ohne Erfolg durchexerziert.

Der zweite schreibende Mega hatte übrigens fast den gleichen Code, mit der Ausnahme...

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Zahl = 100
' Schleife um das Ram mit verschiedenen Werten zu füttern
Zahl = 100
Do
    Gosub Schreiben
    Incr Zahl
    If Zahl > 254 Then Zahl = 100
    Waitms 37                                                                   'Primzahl
Loop
...
Sub Schreiben:
...
    I2cwbyte Pcf_write
    waitms 1
    I2cwbyte &B00000010                                              'Byte 2 schreiben
...

Hier wird also statt von 0 - 99 von 100 - 255 gezählt, dient nur der besseren Unterscheidbarkeit im Terminalprogram. Geschrieben wird ins zweite Byte des RAMs, die Delayzeit ist eine andere um Überschneidungen am Bus gering zu halten.

Jetzt noch der Code des lesenden Megas:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
$regfile = "m8def.dat"
$crystal = 8000000 
$baud = 38400 

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

Config Twi = 100000                                         ' wie beim schreiben

Declare Sub Lesen                                           ' wie beim schreiben

Const Pcf_write = &B10100000                                'RAM write
Const Pcf_read = &B10100001                                 'RAM read

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

Dim Zahl As Byte
Dim Wert1 As Byte
Dim Wert2 As Byte

Zahl = 0
Do
    Gosub Lesen

    Print Zahl ; "  " ; Wert1 ; "  " ; Wert2
    Incr Zahl
    If Zahl > 254 Then Zahl = 0
    Wert1 = 0
    Wert2 = 0
    Waitms 43                                                 'Primzahl
Loop


Sub Lesen:
    I2cstart

    I2cwbyte Pcf_write
    waitms 1

    I2cwbyte &B00000001
    waitms 1

    I2cstart

    I2cwbyte Pcf_read
    waitms 1

    I2crbyte Wert1 , Ack
    Waitms 2
    I2crbyte Wert2 , Nack
    waitms 1

    I2cstop
End Sub

Auch hier hatte ich (erfolglos) verschiedene Fehlerprüfungen vorgenommen - es funktioniert einfach nicht.

Habe ich nur einen schreibenden Mega so läuft es ein Weile...können 30Sek sein, aber auch 10min, keine Logik erkennbar. Dann hängt sich das ganze System entweder auf oder es erscheint nur noch '2' als Ergebnis, also die letzte Byteadresse. Und die Werte erscheinen in deutlich langsamerer Abfolge, da herrscht Chaos auf dem Bus.

Bei zwei schreibenden Megas kommen vielleicht ein Dutzend Werte, dann hängt das Ganze wieder.
Mit verschiedenen Verzögerungszeiten zwischen den Zugriffen habe ich natürlich auch rumexperimentiert (auch komplett ohne), wobei der 8570 ein SRAM ist, also deutlich schneller als z.B. ein EEPROM - ändert alles nix.

Was läuft hier schief, selbst bei der simplen Version mit nur zwei Megas? Hardware-TWI (und dafür ist ja die i2c_twi.lbx) würde ja eigentlich bedeuten dass ein Mega selbstständig erkennt dass der Bus bereits belegt ist und Zugriffsversuche gleich wieder abbrechen. Das passiert hier aber irgendwie nicht, die kommen sich offensichtlich ständig in die Quere. Wobei lt. Hilfe bzw. LIB-Quelltext bei Hardware-TWI auch keine Pullups am Bus nötig sein sollen, funktioniert ohne aber gleich gar nicht...
Any idea?
Schöne Grüsse
Toenne

-Ralf-

RCLine Team

Wohnort: Remscheid

Beruf: Prediger

  • Nachricht senden

2

Dienstag, 21. September 2010, 19:20

RE: I2C Multimaster

Vielleicht ist deine Frage hier besser aufgehoben:

http://www.bascom-forum.de

;)
Gruß Ralf (das Grantele)

Funcopter mit Alu-TS
Raptor E550

Laß dir von keinem Fachmann imponieren, der dir erzählt:
Lieber Freund, das mache ich schon zwanzig Jahre so. - Man
kann eine Sache auch zwanzig Jahre falsch machen.
Tucholsky

3

Mittwoch, 22. September 2010, 23:16

Nun, ich dachte ich frage erstmal hier, immerhin gehts hier ja fast schon um eine elementare Funktionalität so dass ich zunächst einmal von einem Fehler meinerseits ausgehen ;).
Schöne Grüsse
Toenne