I2C Testumgebung

Halloele

Ich hab schon gegoogelt, aber nix brauchbares gefunden (vllt. warens auch die falschen Suchbegriffe...)

Ich muss zur Zeit zwei Microcontrollern beibringen, sich ueber I2C zu unterhalten. Leider besitzt nur einer von beiden einen eigenen I2C Controller, so dass ich auf dem zweiten das Protokoll in Soft- ware nachbauen muss. Daher bin ich nun auf der Suche nach einer einfachen I2C Testumge- bung. Ich denke da z.B. an ein Programm, das I2C meinetwegen ueber den Parallelport realisiert und dann auf dem Monitor einfach empfangenen Daten als Hexcode oder aehnlich anzeigt.

Gibts sowas? Am Besten fuer Linux oder i386-Solaris, noch viel Besser natuerlich Open Source. Wonach sollte ich suchen?

Ciao,

Horst

--
                             Horst  Laschinsky
        Universitaet Erlangen-Nuernberg - Physikalisches Institut I
 Erwin-Rommel-Str. 1, Room: 209, 91058 Erlangen - Tel: ++49 9131 85-27062
       http://www.antares.physik.uni-erlangen.de/~htlaschi/index.html
Reply to
Horst Laschinsky
Loading thread data ...

Selber schreiben. i2c_parport für die Hardware, dann /dev/i2c-0 mit read()/write() beackern. Gibt schöne Dokumentation und Sourcen im i2c-Paket, das es auf der gleichen Seite wie lm_sensors gibt.

Gruß Henning

Reply to
Henning Paul

Ist zwar nicht die Antwort auf deine Frage, aber trotzdem ein Hinweis:

Du benötigst einen Master und einen Slave. Der Microontroller fungiert dabei in der Regel als Master und das jeweilige Peripheriegerät (z.B. EEProm) als Slave. Das Timing des Masters ist unkritisch, da dieser den Takt ja vorgibt. Der Slave muss aber in der vom Master vorgegebenene Zeit reagieren. Deshalb ist es wahrcheinlich sinnvoll, den Controller, der einen Hardware I2C-Bus Controller hat als Slave zu betreiben. Der andere, d.h. der auf dem deine Softwarelösung läuft ist dann der Master.

-> s.o. Das Timing des Slaves ist kritisch, deshalb ist eine PC-Parallelportlösung als Testumgebung ungeeignet

Mit nem PC-Parallelport läßt sich allerdings sehr einfach ein I2C Master realisieren, vieleicht hilft das ja auch weiter. Ich müsste mal nachsehen, ob ich noch irgendwo ein par Schnipsel Turbo-Pascal zu dem Thema finde....

Die Frage wäre noch, ob es unbedingt I2C sein muss, oder ob es andere bessere oder einfachere Lösungen gibt. Benötigst du ein System mit mehr als einem Master und einem Slave, oder müssen nur zwei Prozessoren miteinander kommunizieren? Wieviele Daten willst/must du denn transportieren?

Gruß

Stefan

Reply to
Stefan Bröring

Muss der Master nur senden, oder auch empfangen?

Ich habe I2C bisher nur für die Kommunikation mit EEProms, RTCs und so verwendet, nicht für die Kommunikation zwischen Prozessoren, deshalb meine Frage. Beim I2C Protokoll gebe ich ja neben der Slaveadresse noch eine Speicheradresse und so an. Das muss nicht unbedingt sinnvoll sein für die Kommunikation zwischen Prozessoren. bzw. das Protokoll läßt sich vermutlich recht einfach mit wenigen Logikbausteinen realisieren, ist aber nicht für den Austausch von Datentelegrammen geeignet.

Wenn der Master Antworten benötigt, muss er sich diese quasi Byte für Byte rauspulen.

Es gibt viele Möglichkeiten, wie man soetwas mit nur zwei, oder auch nur einer Leitung realisieren kann. Mit einer Leitung würde der Master einfach ein asynchrones serielles Signal per Software realisieren (falls nicht doch ein UART frei ist) und auf die Datenleitung legen. Der Slave antwortet dann auf der selben Leitung ebenfalls mit einem asynchronen seriellen Signal.

Vorteil: Zum Testen / Abhören nehme ich einfach die Com-Schnittstelle des PCs und ein Terminalprogramm

Wenn es eine Zweidrahtlösung sein soll, kann man eine synchrone Lösung wählen, bei der der Master den Takt sowohl zum Senden, als auch zum Empfangen vorgibt. Bei den Slaves hängt die Taktleitung dann z.B. an einem INT-Eingang. Damit sind dann sehr hohe Datentransferraten möglich.

Hier erstmal ein paar Fragmente aus einem 8031 Programm, mit einem I2C Uhrenchip PCF85?? Ich hoffe, der Code ist selbsterklärend...

Pascal-Sources muss ich noch suchen.

Gruß

Stefan

------------------------------------------------- snip -------------------------

INIT_I2C: SETB SDA SETB SCL RET

START_I2C: CLR SDA ;Startbedingung setzen LCALL _DELAY CLR SCL ;SCL auch auf LOW SJMP _DELAY ;nach kurzer Wartezeit return

BIT_I2C: MOV SDA,C ;Bit in Carry ausgeben LCALL _DELAY SETB SCL ;Taktbit setzen LCALL _DELAY MOV C,SDA ;Zustand des Datenbits lesen PUSH PSW CLR SCL ;Taktbit zurckseten LCALL _DELAY POP PSW RET

STOP_I2C: SETB SCL ;SCL auf High-Pegel LCALL _DELAY SETB SDA ;Steigende Flanke SJMP _DELAY ;warten und return

BYTE_I2C: MOV C,ACC.7 ;Daten im ACCU senden oder lesen LCALL BIT_I2C MOV ACC.7,C

MOV C,ACC.6 LCALL BIT_I2C MOV ACC.6,C

MOV C,ACC.5 LCALL BIT_I2C MOV ACC.5,C

MOV C,ACC.4 LCALL BIT_I2C MOV ACC.4,C

MOV C,ACC.3 LCALL BIT_I2C MOV ACC.3,C

MOV C,ACC.2 LCALL BIT_I2C MOV ACC.2,C

MOV C,ACC.1 LCALL BIT_I2C MOV ACC.1,C

MOV C,ACC.0 LCALL BIT_I2C ;letztes Bit senden MOV ACC.0,C RET

ACK_I2C: SETB C LJMP BIT_I2C

ACK_I2C_W: CLR C LJMP BIT_I2C

GET_I2C: .module GET_I2C MOV C,SCL MOV I2C_BIT,C LCALL STOP_I2C ;Stopbedingung sicherstellen LCALL START_I2C ;Startbedingung MOV A,ADR_I2C ;Slave-Adresse nach A CLR ACC.0 ;erst Adresse schreiben LCALL BYTE_I2C ;Slave-Adr. schreiben LCALL ACK_I2C MOV A,WRD_I2C ;Wordadresse in den AKKU LCALL BYTE_I2C ;Wordadresse senden LCALL ACK_I2C LCALL STOP_I2C LCALL START_I2C MOV A,ADR_I2C SETB ACC.0 LCALL BYTE_I2C ;Slaveadresse senden LCALL ACK_I2C ;ACK abwarten MOV A,#$FF ;alle Bits High, um zu lesen LCALL BYTE_I2C LCALL ACK_I2C ;Ack schreiben SDA auf low LCALL STOP_I2C MOV C,I2C_BIT MOV SCL,C RET

PUT_I2C: .module PUT_I2C MOV C,SCL MOV I2C_BIT,C LCALL STOP_I2C ;Stopbedingung sicherstellen LCALL START_I2C ;Startbedingung PUSH ACC MOV A,ADR_I2C ;Slave-Adresse nach A CLR ACC.0 ;erst Adresse schreiben LCALL BYTE_I2C ;Slave-Adr. schreiben LCALL ACK_I2C MOV A,WRD_I2C ;Wordadresse in den AKKU LCALL BYTE_I2C ;Wordadresse senden LCALL ACK_I2C POP ACC LCALL BYTE_I2C LCALL ACK_I2C LCALL STOP_I2C MOV C,I2C_BIT MOV SCL,C RET

GET_UHR: .module GET_UHR MOV ADR_I2C,#$A0 ;Slave-Adresse nach R1 MOV WRD_I2C,#04 ;Stunden adressieren LCALL GET_I2C ;Byte auslesen MOV STUNDE,A MOV WRD_I2C,#03 ;Minuten adressieren LCALL GET_I2C ;Byte auslesen MOV MINUTE,A MOV WRD_I2C,#02 ;Sekunden adressieren LCALL GET_I2C ;Byte auslesen MOV SEKUND,A RET

Reply to
Stefan Bröring

Hab da gerade was gefunden...

stammt aus PC-XT oder 286er Zeiten

-----------------------------------------------------------------------------------------

program i2C; uses crt,dos;

const lpt1 : word = $378; lpt2 : word = $278; lpt3 : word = $3BC;

var daten,status,steuer : word; ausgang : byte; tb : byte; sys_speed : word;

function speed : word; var h,m,s,ss,t,w : word; x : real; begin w := 0; x := 0; gettime(h,m,s,ss); t := ss; repeat gettime(h,m,s,ss) until ss t; t := ss; repeat gettime(h,m,s,ss); inc(w); x := 0; for h := 1 to 100 do x := x+1; until ss t; speed := w; end;

procedure zeit; var x : real; begin x := 0; repeat x := x+ 1; until x >= sys_speed; end;

procedure init; begin clrscr; sys_speed := speed div 40; daten := lpt1; status := daten+1; steuer := daten+2; port[daten]:=255; port[steuer]:=0; port[status] := 255; ausgang := 255; zeit; end;

procedure ruhe; begin port[daten] := 255; {alles auf High, auáer D1} zeit; ausgang := 255; end;

procedure sda(b : boolean); begin ausgang := ausgang and 251; {Bit 1 = SDA = low} if b then ausgang := ausgang or 4; port[daten] := ausgang; zeit; end;

procedure scl(b : boolean); begin ausgang := ausgang and 254; {Bit 0 = SCL = low} if b then ausgang := ausgang + 1; port[daten] := ausgang; zeit; end;

procedure start; begin ruhe; sda(true); scl(true); sda(false); scl(false); end;

procedure stop; begin sda(false); scl(true); sda(true); end;

function bit(a:boolean):boolean; begin sda(a); scl(true); tb := port[daten]; if (port[status] and 128) = 0 then bit := true else bit := false; scl(false); end;

function byte_s(b:byte):boolean; var i,j : integer; q : boolean; begin j := b; for i := 0 to 7 do begin j := j * 2; bit((j>255)); j := j and 255; end; byte_s := bit(true); {ack} end;

function byte_r : byte; var i,j : byte; begin j := 0; for i := 0 to 7 do begin j := j*2; if not bit(true) then inc(j); end; byte_r := j; bit(true); {wg. ack} end;

procedure speicher(adresse : word;daten:byte); var b : byte; begin start; byte_s((adresse div 256) * 2 + $A0); byte_s((adresse and 255)); byte_s(daten); stop; end;

function lese(adresse : word) : byte; var b : byte; begin start; b := adresse div 256; b := b*2; b := b and 14; b := b+$A0; byte_s(b); byte_s((adresse and 255)); start; byte_s(b+1); lese := byte_r; stop; end;

procedure test_r; var i : integer; b,bb : byte; begin i := 0; repeat b := lese(i); write(i:6,b:4); inc(i); if i > 2047 then i := 0; until keypressed; end;

begin init; test_r; end.

Reply to
Stefan Bröring

Beides. Wie gesagt, es werden ab und zu auch groessere Datenmengen uebertragen, wofuer ein Uebertragungsprotokoll designed wurde, und zwar eine Art "abgespecktes TCP". Es muessen also zumindest die ACKs und Fehlermeldungen zurueck zum Master gelangen.

Hu? Also das ist mir neu, dass man da eine Speicheradresse angeben muss und ich find dazu auch grad in der Spec. nix.

Jups. Die Sache ist halt die, dass die anderen drei uCs ja eigene I2C-Controller besitzen. Und wieso soll ich mir's schwerer ma- chen als es ist, wenn ich diese Controller einfach verwenden kann.

Ja, isser. :-) Vielen herzlichen Dank!

Ciao,

Horst

--
                             Horst  Laschinsky
        Universitaet Erlangen-Nuernberg - Physikalisches Institut I
 Erwin-Rommel-Str. 1, Room: 209, 91058 Erlangen - Tel: ++49 9131 85-27062
       http://www.antares.physik.uni-erlangen.de/~htlaschi/index.html
Reply to
Horst Laschinsky

Muß man auch nicht. Es ist nur bei Speicherbausteinen üblicherweise zufällig so, daß die Registeradresse erstes Datenargument ist. Also ein "Multiple Read/Write" mit 2 Bytes als Nutzlast, erstes Adresse, zweites Wert (bzw. 3 Bytes Nutzlast bei 16bit-organisierten Speichern).

Gruß Henning

Reply to
Henning Paul

Tja, und wie immer wurde auch hier übersehen, dass auch die SCL-Leitung Bi-Direktional ist.

Das kann gutgehen, muss es aber nicht. Der Master muss, nachdem er SCL auf High setzt erst abwarten, bis die Leitung wirklich High geworden ist. Langsame Busteilnehmer dürfen die Leitung absichtlich zum "Clock stretching" auf Low festhalten.

Das macht z.B. der gute alte MAS3507 so..

--
thomas.kindler@gmx.de
Reply to
Thomas Kindler

Beim i2c_parport.ko Kernelmodul ist das berücksichtigt worden, da wird eine Statusleitung zum Zurücklesen benutzt.

Und einige Maxim A/D-Wandler. Weshalb der AN2135 nicht mit denen umkann. Sehr ärgerlich das, hat ziemlichen Entwicklungsaufwand nach sich gezogen.

Gruß Henning

Reply to
Henning Paul

Wird wohl so sein. Meine Erfahrungen auf I2C beschränken sich wie bereits zuvor beschrieben auf die Ansteuerung von EEProms und RTCs.

Gruß

Stefan

Reply to
Stefan Bröring

Am 9 Feb 2006 13:02:21 GMT schrieb Horst Laschinsky:

Vielleicht hilft dir das hier weiter

formatting link
formatting link

Hat mir mal kurzfristig aus der Klemme geholfen :)

Alexander

Reply to
Alexander Peter

Ah! Das sieht nach GENAU nach dem aus, was ich suche!

Vielen Dank! Gleich mal probieren.

Ciao,

Horst

-- Horst Laschinsky Universitaet Erlangen-Nuernberg - Physikalisches Institut I Erwin-Rommel-Str. 1, Room: 209, 91058 Erlangen - Tel: ++49 9131 85-27062

formatting link

Reply to
Horst Laschinsky

HAllo,

das Nachbauen sollte eigentlich kein Problem sein. Es Gibt App-Notes und beispiele der Microcontroller und Compiler hersteller.

Welchen Microcontroller möchtest Du verwenden, welche Sprache (Assembler, C,...)?

Gruss Jochen

Reply to
Jochen Rapp

Jo, das Programmieren ist auch nicht das Problem, sondern das De- buggen. Prinzipiell koennte man das natuerlich auch mit nem Oszi und viel Geduld machen, aber ich glaub, die Software die Alexander er- waehnt hat ist da doch geeigneter. :-) Werd ich am Montag gleich mal testen.

Der uC ist ein Motorola MPC860. Der hat zwar prinzipiell einen I2C Controller on board, aber dummerweise ist der mir nicht zugaenglich, da die entsperchenden Leitungen nicht von der Platine herausgefuehrt sind. Darum muss ich das Protokoll ueber I/O Ports simulieren. Und um die Frage gleich mal vorwegzunehmen: Nein, das Design kann nicht geaendert werden. (Die Begruendung hierfuer wuerde etwas zu weit fuehren, belassen wirs bei einem "es geht nicht").

Die Software, die bisher darauf laeuft, ist in C++ geschrieben. Aus Konsistenzgruenden sollte es daher der I2C-Code auch sein (wo- bei mir persoenlich C wesentlich lieber waere...).

Ciao,

Horst

--
                             Horst  Laschinsky
        Universitaet Erlangen-Nuernberg - Physikalisches Institut I
 Erwin-Rommel-Str. 1, Room: 209, 91058 Erlangen - Tel: ++49 9131 85-27062
       http://www.antares.physik.uni-erlangen.de/~htlaschi/index.html
Reply to
Horst Laschinsky

Hallo,

mal doch mal nicht den Teufel an die Wand. Wenn Du auf vorgefertigte Programme zurückgreifst, dann ist die Chanche gross, dass alles zusammenspielt.

Ich habe schon einige I2C für Microcontroller programmiert, das ging bisher immer ohne Probleme.

Überleg dir, ob Du das I2C wirklich benötigst. Wenn Du nur zwei Microcontroller verbinden willst, dann kannst Du das auch vereinfachen. Adressen sind nicht notwendig. Wahrscheinlich kannste auch auf Start-Stop-Bit verzichten.

Gruss Jochen

Reply to
Jochen Rapp

Jo, das is schon klar. Dennoch waers mir lieber, wenn ich eine Moeg- lichkeit zum Debuggen haette. Ich sag ja net, dass es nicht funktio- niert, nur dass es ggf. nicht funktionieren _koennte_, und dann sind entsprechende Werkzeuge ueberaus sinnvoll.

Wie schonmal gesagt: es sind insgesamt vier Microcontroller. Davon haben drei einen I2C-Controller eingebaut (der vierte zwar auch, nur komm ich an den eben nicht ran). Also nehm ich I2C, denn dann muss ich mich nur um den einen kuemmern, net um alle vier.

Ciao,

Horst

--
                             Horst  Laschinsky
        Universitaet Erlangen-Nuernberg - Physikalisches Institut I
 Erwin-Rommel-Str. 1, Room: 209, 91058 Erlangen - Tel: ++49 9131 85-27062
       http://www.antares.physik.uni-erlangen.de/~htlaschi/index.html
Reply to
Horst Laschinsky

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.