1.                 I2C Bus Protokoll

 

i2c_init

Ruhe: Keine Aktivität auf dem Bus
In Ruhe sind SDA und SCL auf +5 Volt "hochgespannt".
Durch "Kurzschliessen" auf Masse wird der Bus aktiviert.

i2c_start

Start-Bedingung: Data fällt, während Clock high ist
Das erste Byte nach einer Startbedinung ist immer eine Adresse
alle weiteren Bytes bis zu einer Stopbedingung sind Daten!

i2c_stop

Stop-Bedingung: Data steigt, während Clock high ist
Nach Stopbedinung müssen alle Bausteine wieder den Bus beobachten und nach einer Startbedingung Auschau halten.

i2c_w1

Eine Eins übertragen: Data ist High während eines Clock-Impulses.
Während eines Clock-Impuls darf sich die SDA-Leitung nicht ändern

i2c_w0

Eine Null übertragen: Data ist Low während eines Clock-Impulses.
Eine Änderung von SDA während SCL low ist, hat keine Funktion

i2c_w(4C)
if (i2c_ack) ..

 

d=i2c_rack

d=i2c_rnak

Acknowledge: Nach acht Datenbits folgt das ACK-Bit
Nach acht Datenbits wird SDA immer auf EINS gelegt. Ist ein Baustein unter der gesendeten Adresse vorhanden, so zieht der diese Eins auf Masse, daran erkennt der Master, das der Baustein arbeitsbereit ist.
Beim Senden eines Datenbyte-Byte an einen Baustein, bedeutet ACK dass der Baustein das Datenbyte akzeptiert hat.
Beim Empfangen eines Datenbyte wird die Datenleitung vom Slave entsprechend seinen Daten geesetzt. Das ACK muss dann der Master machen, als Empfangsquittung.

i2c_start
i2c_w(6E)
i2c_w(3C)
i2c_stop

Erfolgreiche Übertragung des Datenbytes 0011 1100 an den Baustein 0110 1110

2.                 Auf Betriebssystem-Ebene verfügbare I2C-Befehle

mit Quelltext für Linux in C (26.8 kB) bzw Windos/Delphi 4 (39.6 kB)

 

Befehl

Hinweise

Ergebniss

i2cdevls

Listet die verfügbaren I2C-Bausteine auf!

40 41 48 49 4A 4B 9E 9F

i2cadrda

Aufruf:

i2cadrda adr dat

Sendet an den Baustein mit der Adresse adr das Datenbyte dat

OK

i2cr8591

Initalisiert den Oszi-Baustein PCF 8591 und fragt die 4 AD-Wandler ab

i2cr8591 adr mod da
i2cr8591 9E 44 80

OK 13 5A B4 D3

3.                 Einfache Interface-Schaltung für die Serielle Schnittstelle

Die Bauteilkosten für die komplette Schaltung mit 8574 und 8591 liegen bei unter DM 20.-

4.                 I2C-Bus über Internet steuern

 

·  Digital OUT

Ansteuerung von Leuchtdioden

·  Digital IN

Abfrage von Kipp-Schaltern

 

·  Analog OUT

 

Funktionsgenerator fuer E-Funktion

·  Analog IN

4-Kanal-Ozsilloskop

 

5.                 Programmierung 8574

 

PCF 8574
Der Baustein ist eine 8 Bit Input/Output-Erweiterung des I2C-Busses, das heisst an die Datenpins P7..P0 kann ein beliebiger 8 Bit Wert als TTL-Pegel ausgegeben werden, bzw es kann der Zustand der 8 Bit abgefragt und ausgelesen werden!
Über die 3 Adressbits A2 A1 A0 kann die Bausteinadresse festgelegt werden

Fixadr

A2

A1

A0

write=0
read=1

Adr
(hex)

0100
0100

0
0

0
0

0
0

0 w
1 r

40
41

0100
0100

0
0

0
0

1
1

0 w
1 r

42
43

0100
0100

0
0

1
1

0
0

0 w
1 r

44
45

0100
0100

0
0

1
1

1
1

0 w
1 r

46
47

0100
0100

1
1

0
0

0
0

0 w
1 r

48
49

0100
0100

1
1

0
0

1
1

0 w
1 r

4A
4B

0100
0100

1
1

1
1

0
0

0 w
1 r

4C
4D

0100
0100

1
1

1
1

1
1

0 w
1 r

4E
4F


Damit lassen sich also 8 Bausteine mit zusammen 64 Bit Input/Output parallel am I2C Bus betreiben.

5.1                Programmierung des Bausteins PCF8574

Ausgabe eines Bytes

mit Pascal(DOS)/Delphi(Win)

mit Visual Basic(Win)

mit C bzw C++(Linux)

uses iic_tools;
..
iic_port:=iic_autocfg;
if iic_port=0
  then fehler('I2C Bus nicht da');
..
iic_start;
  iic_w($40);
  iic_w(data);
iic_stop;
..

Module iic_tools.bas geladen!

..
iic_Port=iic_autocfg
if iic_port=0 then 
  fehler 'I2C Bus nicht da'
..
iic_start
  iic_w(&H40)
  iic_w(data)
iic_stop
..

Kernel-Module i2c geladen

# include "i2c.h";
..
int I2C=fopen("/dev/i2c0","r+");
if (I2C=0)
  {fehler("I2C-Bus nicht da");}
..
ioctl(I2C,I2C_SLAVE,0x20);
write(I2C,data,1);
fclose(I2C);

Einlesen eines Bytes

Damit die Datenbytes richtig eingelesen werden können wird zunächst an alle Pins eine Eins ausgegeben!
Diese Eins(+5V) darf jedoch auf Masse gelegt werden. Dann wird eine Null eingelesen, wenn die ursprünglich angelegte Eins jedoch noch vorhanden ist , wird wieder eine Eins eingelesen!

mit Pascal(DOS)/Delphi(Win)

mit Visual Basic(Win)

mit C bzw C++(Linux)

uses iic_tools;
..
iic_port:=iic_autocfg;
if iic_port=0
  then fehler('I2C Bus nicht da!');
..
iic_start;
  iic_w($40);
  iic_w($FF);
iic_stop;
iic_start;
  iic_w($41);
  data:=iic_rack;
iic_stop;

Module iic_tools.bas geladen!

..
iic_Port=iic_autocfg
if iic_port=0 then 
  fehler 'I2C Bus nicht da'
..
iic_start
  iic_w(&H40)
  iic_w(&HFF)
iic_stop
iic_start
  iic_w(&H41)
  data=iic_rack(&HFF)
iic_stop
 

Kernel-Module i2c geladen

# include "i2c.h";
..
int I2C=fopen("/dev/i2c0","r+");
if (I2C=0)
  {fehler("I2C-Bus nicht da");}
..
ioctl(I2C,I2C_SLAVE,0x20); 
/*nur 7 Bit Adresse noetig!*/
write(I2C,0xFF,1);
read (I2C,data,1);
fclose(I2C);

 

6.                 Programmierung 8591

 

PCF 8591
Der Baustein ist ein

·  4 Kanal AD mit 8 Bit Auflösung

·  1 Kanal DA mit 8 Bit Auflösung
Über die 3 Adressbits A2 A1 A0 kann die Bausteinadresse festgelegt werden

Fixadr

A2

A1

A0

write=0
read=1

Adr
(hex)

1001
1001

0
0

0
0

0
0

0 w
1 r

90
91

1001
1001

0
0

0
0

1
1

0 w
1 r

92
93

1001
1001

0
0

1
1

0
0

0 w
1 r

94
95

1001
1001

0
0

1
1

1
1

0 w
1 r

96
97

1001
1001

1
1

0
0

0
0

0 w
1 r

98
99

1001
1001

1
1

0
0

1
1

0 w
1 r

9A
9B

1001
1001

1
1

1
1

0
0

0 w
1 r

9C
9D

1001
1001

1
1

1
1

1
1

0 w
1 r

9E
9F


Damit lassen sich also 8 Bausteine mit zusammen 32 Analog-Input-Kanälen 8 Analog-Out-Kanälen parallel am I2C Bus betreiben.

Configuration des PCF8591:

 

6.1                Programmierung des Bausteins PCF8591

Funktion als Digital-Analog-Wandler

mit Pascal(DOS)/Delphi(Win)

mit Visual Basic(Win)

mit C bzw C++(Linux)

uses iic_tools;
..
iic_port:=iic_autocfg;
if iic_port=0
  then fehler('I2C Bus nicht da');
..
iic_start;
  iic_w($90);
  iic_w(cfg);
  iic_w(dawert);
iic_stop;
..

Module iic_tools.bas geladen!

..
iic_Port=iic_autocfg
if iic_port=0 then 
  fehler 'I2C Bus nicht da'
..
iic_start
  iic_w(&H90)
  iic_w(cfg)
  iic_w(da-wert)
iic_stop
..

Kernel-Module i2c geladen

# include "i2c.h";
..
int I2C=fopen("/dev/i2c0","r+");
if (I2C=0)
  {fehler("I2C-Bus nicht da");}
..
ioctl(I2C,I2C_SLAVE,0x48);
write(I2C,cfg,1);
write(I2C,dawert,1);
fclose(I2C);

4-Kanal-Messung

Damit die Datenbytes richtig eingelesen werden können wird zunächst an alle Pins eine Eins ausgegeben!
Diese Eins(+5V) darf jedoch auf Masse gelegt werden. Dann wird eine Null eingelesen, wenn die ursprünglich angelegte Eins jedoch noch vorhanden ist , wird wieder eine Eins eingelesen!

mit Pascal(DOS)/Delphi(Win)

mit Visual Basic(Win)

mit C bzw C++(Linux)

uses iic_tools;
..
iic_port:=iic_autocfg;
if iic_port=0
  then fehler('I2C Bus nicht da!');
..
iic_start;
  iic_w($90);
  iic_w($44);iic_w($FF);
iic_stop;
iic_start;
  iic_w($91);
  dummy:=iic_rack;
  k1   :=iic_rack;
  k2   :=iic_rack;
  k3   :=iic_rack;
  k4   :=iic_rack;
  dummy:=iic_rnak;
iic_stop;

Module iic_tools.bas geladen!

..
iic_Port=iic_autocfg
if iic_port=0 then 
  fehler 'I2C Bus nicht da'
..
iic_start
  iic_w(&H40)
  iic_w(&H44)
  iic_w(&HFF)
iic_stop
iic_start
  iic_w(&H41)
  dummy=iic_rack
  k1=iic_rack
  k2=iic_rack
  k3=iic_rack
  k4=iic_rack
  dummy=iic_rnak
iic_stop

Kernel-Module i2c geladen

# include "i2c.h";
..
int I2C=fopen("/dev/i2c0","r+");
if (I2C=0)
  {fehler("I2C-Bus nicht da");}
..
ioctl(I2C,I2C_SLAVE,0x48); 
/*nur 7 Bit Adresse noetig!*/
write(I2C,0x44,1);
write(I2C,0xFF,1);
read (I2C,dummy,1);
read (I2C,k1,1);
read (I2C,k2,1);
read (I2C,k3,1);
read (I2C,k4,1);
fclose(I2C);

 

 

Dank an:

Robert-Bosch-Schule Ulm
Abt. Elektrotechnik, Datentechnik, Programmiersprachen