I2C-Bus

4.1 I2C-Bus Software


4.1 Übersicht

Ein Interface für den Parallel Port hat zwei gravierende Nachteile:

  1. Meistens ist ein Drucker angeschlossen
  2. Unter Windows 2000, Windows NT und Windows XP kann die Schnittstelle nicht direkt programmiert werden und es steht in der Regel kein API zur Verfügung

Vorteil des seriellen Interface:

  1. Es stehen zwei programmierbare Ein- und Ausgänge zur Verfügung
  2. Es ist meistens mehr als eine Schnittstelle vorhanden
  3. Für die Programmierung stehen Standard API Aufrufe zur Verfügung

Spannung: 8 bis 12 Volt
Strom: 25mA
Übertragungsgeschwindigkeit: ca. 9,2ms/Byte

Eine Übersicht über die Funktionsweise des I2C-Bus wird hier nicht geliefert. Das Internet ist voll davon.

Alle Schaltungen werden in ein Standard Bopla Gehäuse untergebracht, sie sind klein und trittfest.

4.1.1 Software

Globale Variable und Constante
Const
  high = false;
  low = true;

Var
  CHandle: THandle;
  CEnabled: Boolean = false;

4.1.1.1 Level 1 Functions

Basisfunktionen der seriellen Schnittstelle

Öffnen der seriellen Schnittstelle
// Result = true = alles klar
// Result = false = Schnittstelle steht nicht zur Verfügung
Function ComOpen(ComStr:String):Boolean;
Begin
  Result := true;
  CHandle := CreateFile(PCHAR(ComStr),
             GENERIC_READ or GENERIC_WRITE,
             0,
             nil,
             OPEN_EXISTING,
             FILE_FLAG_OVERLAPPED,
             0);
  If CHandle = INVALID_HANDLE_VALUE Then Result := false;
  CEnabled := Result;
End;

Schliessen der seriellen Schnittstelle
Procedure ComClose;
Begin
  If CEnabled Then Begin
    CloseHandle(CHandle);
    CHandle := INVALID_HANDLE_VALUE;
  End;
End;

Setzt die DTR Leitung
// State = True = +5V..+12V
// State = False = -12V..-5V
Function DTR(State:Boolean):Boolean;
Const DTR: Array[Boolean] of Integer = (CLRDTR,SETDTR);
Begin
  Result := false;
  If CEnabled Then Begin
    Result := EscapeCommFunction(CHandle,DTR[State]);
  End;
End;

Setzt die RTS Leitung
// State = True = +5V..+12V
// state = False = -12V..-5V
Function RTS(State:Boolean):Boolean;
Const RTS: Array[Boolean] of Integer = (CLRRTS,SETRTS);
Begin
  Result := false;
  If CEnabled Then Begin
    Result := EscapeCommFunction(CHandle,RTS[State]);
  End;
End;

Holt den Status der DSR Leitung
// Result = True = +5V..12V
// Result = False = -12V..0V oder Offener Eingang
Function DSR:Boolean;
Var Flag:DWord;
Begin
  Result := false;
  If CEnabled Then Begin
    If GetCommModemStatus(CHandle,Flag) Then Begin
      Result := (Flag and MS_DSR_ON > 0);
    End;
  End;
End;

Holt den Status der CTS Leitung
// True = +5V..12V
// False = -12V..0V oder Offener Eingang
Function CTS:Boolean;
Var Flag:DWord;
Begin
  Result := false;
  If CEnabled Then Begin
    If GetCommModemStatus(CHandle,Flag) Then Begin
      Result := (Flag and MS_CTS_ON > 0);
    End;
  End;
End;

Holt den Status der Ring Leitung
// True = Versorgungsspannung ist vorhanden
// False = Versorgungsspannung fehlt
Function Ring:Boolean;
Var Flag:DWord;
Begin
  Result := false;
  If CEnabled Then Begin
    If GetCommModemStatus(CHandle,Flag) Then Begin
      Result := (Flag and MS_RING_ON > 0);
    End;
  End;
End;

4.1.1.2 Level 2 Functions

Basisfunktionen des I2C Bus

Setzen der SCL Leitung
// b1 = high = SCL Leitung liegt auf +5Volt
// b1 = low = SCL Leitung liegt auf 0 Volt
Procedure SCL(b1:Boolean);
Begin
  DTR(not b1);
End;

Setzen der SDA Leitung
// b1 = high = SDA Leitung liegt auf +5Volt
// b1 = low = SDA Leitung liegt auf 0 Volt
Procedure SDA(b1:Boolean);
Begin
  RTS(not b1);
End;

Lesen des Zustandes der SCL Leitung
// Result = high = SCL Leitung liegt auf +5Volt
// Result = low = SCL Leitung liegt auf 0 Volt
Function GetSCL:Boolean;
Begin
  If DSR Then Result := low Else Result := high;
End;

Lesen des Zustandes der SDA Leitung
// Result = high = SDA Leitung liegt auf +5Volt
// Result = low = SDA Leitung liegt auf 0 Volt
Function GetSDA:Boolean;
Begin
  If CTS Then Result := low Else Result := high;
End;

4.1.2.3 Level 3 Functions

Höhere Funktionen des I2C Bus

Startbit ausgeben
Procedure I2CStartBit;
Begin
  // Wenn CLK high ist, wechselt SDA von high nach low
  SDA(high);
  SCL(high);
  SDA(low);
  SCL(low);
End;

Stopbit ausgeben
Procedure I2CStopBit;
Begin
  // Wenn CLK high ist, wechselt SDA von low nach high
  SDA(low);
  SCL(high);
  SDA(high);
End;

Initialisierung
//Schnittstelle öffnen und Leitungen initialisieren
Function I2CInit(ComPort:String):Boolean;
Begin
  Result := false;
  If ComOpen(ComPort) Then Begin
    DTR(false);
    RTS(False);
  Result := true;
  End;
End;

Schliessen
// Schnittstelle freigeben
Procedure I2CRelease;
Begin
  ComClose;
End;

Byte ausgeben
Function I2CPutByte(b1:Byte):Boolean;
Var i:Integer; j:Byte;
Begin
  Result := false;
  j := $80;
  For i := 1 to 8 do Begin
    If (j and b1) = j Then Begin
      SDA(high);
    End Else Begin
      SDA(low);
    End;
    SCL(high);
    SCL(low);
    SDA(low);
    j := j div 2;
  End;
  // Acknowledge empfangen
  SDA(high);
  SCL(high);
  Result := GetSDA;
  SCL(low);
  SDA(high);
End;

Byte einlesen
Function GetByte(Ack:Byte):Byte;
Var i:Integer; b1:Byte;
Begin
  Result := 0;
  b1 := $00;
  SDA(high);
  For i := 1 to 8 do Begin
    b1 := b1 * 2;
    SCL(high);
    If GetSDA = high Then b1 := b1 or $01;
    SCL(low);
  End;
  // Acknowledge senden
  If Ack = 0 Then SDA(low) Else SDA(high);
  SCL(high);
  SCL(low);
  SDA(high);
  Result := b1;
End;

4.1.2 Download

Download

Bemerkung

I2CDemo.zip
12288 Bytes

Demo mit PCF8574 (Digital I/O) und PCF8583 (Counter) als Beispiel.

I2CUnit.pas
8192 Bytes

Unit mit allen Funktionen zur Bedienung des I2C-Bus Interfaces

Die Unit enthält eine Delay Funktion, die Verzögerungszeiten im Mikrosekundenbereich ermöglicht. Sollte der Typ TLargeInteger in der gewählten Hochsprache nicht verfügbar sein, kann die Funktion entfernt werden. Sie wurde nur bei der Entwicklung benötigt und wird von den anderen Funktionen jetzt nicht mehr benutzt.