Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:
Lo primero que hay que hacer es empaparse del protocolo I2C. Como se observa una linea es bidireccional (SDA) y no hay ninguna en el puerto paralelo. Resolvemos el problema con el siguente circuito usando un 74HC244.
La selección del sentido se realiza con dos salidas. Se puede realizar un inversor con un transistor y un par de resistencias y dejar libre una de ellas. Para las salidas I2C se ha previsto un reset para, en caso de error en el PC, desconectarlas (Seg Salidas).
Comenzaremos con un PCF 8574 configurado como entradas. Para el manejo del puerto hay que bajarsse el archivo IO.DLL.
Una vez realizado el circuito se dispone de la señal de reloj (SCL), la línea de datos (SDA) y la masa que va a ser común. Por el otro lado hay que aplicar una tensión estabilizada de 5V.
El data sheet ( http://hubbard.engr.scu.edu/embedded/sp ... cf8574.pdf) del PCF 8574 se puede localizar fácilmente.
La configuración de entrada/salida se hace por software así que no reviste mayor importancia la configuración de sus patillas. Tan solo hay que anotar cuales van a ser entradas, salidas o mixtas.
Para poder gestionar el bus I2C en Delphi :
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Unit UI2C;
(* Delphi Protocolo para I2C.
Conexión al puerto paralelo a través del puerto paralelo
con un 74 HC 244 como adaptador
21-11-2006 Conexión de entradas con el PCF 8574
24-11-2006 Conexión de salidas con el PCF8574
*)
(* ======================== Interface ======================================= *)
Interface
Procedure Init (X : Byte);
Procedure I2C_WrData (X : Byte);
Function I2C_RdData : Byte;
Procedure I2C_WaitAck;
Procedure I2C_Stop;
(* ======================== Implementation ================================== *)
Implementation
Uses Windows, Forms, SysUtils;
Procedure PortOut (Port : Word; Data : Byte); stdcall; external 'io.dll';
Function PortIn (Port : Word) : Byte ; stdcall; external 'io.dll';
//-----------------------------------------------------------------------------
Procedure Dly5;
(* Temporización de 5 uSec *)
Var F : Int64;
T_Start, T_Stop, T_Now : Int64;
Begin
QueryPerformanceCounter (T_Start);
QueryPerformanceFrequency (F);
T_Stop := T_Start + F * 5 Div 1000000;
Repeat
Application.ProcessMessages;
QueryPerformanceCounter (T_Now)
Until T_Now >= T_Stop
End;
//------------------------------------------------------------------------------
Procedure I2C_Start;
(* Conexión del periférico *)
Begin
PortOut ($378, $21); // SCL := 1
PortOut ($37A, $00); // SDA := 1
Dly5; // Wait 5 uSec
PortOut ($37A, $01); // SDA := 0
Dly5;
PortOut ($378, $20); // SCL := 0
Dly5;
End;
//-----------------------------------------------------------------------------
Procedure I2C_Stop;
(* Desconexión del periférico *)
Begin
PortOut ($37A, $01); // SDA := 0
Dly5;
PortOut ($378, $81); // SCL := 1
Dly5;
PortOut ($37A, $00); // SDA := 1
Dly5;
End;
//-----------------------------------------------------------------------------
Procedure I2C_WrAck (NACK : Boolean);
(* *)
Begin
If NACK
Then PortOut ($37A, $00) // SDA := 1
Else PortOut ($37A, $01); // SDA := 0
Dly5;
PortOut ($378, $81); // SCL := 1
Dly5;
PortOut ($378, $80); // SCL := 0
Dly5;
PortOut ($37A, $00); // SDA := 1
Dly5;
End;
//-----------------------------------------------------------------------------
Procedure I2C_WaitAck;
(* Acepta el dato*)
Begin
PortOut ($37A, $00); // SDA := 1
PortOut ($378, $11); // SCL := 1
Dly5;
Repeat
Application.ProcessMessages;
Until PortIn ($379) and $40 = 0;
PortOut ($378, $10); // SCL := 0
Dly5;
End;
//-----------------------------------------------------------------------------
Procedure I2C_WrData (X : Byte);
(* Escritura en periférico *)
Var Counter : Integer;
Mask : Integer;
Begin
Mask := $80;
For Counter := 1 To 8 Do
Begin
If X And Mask = 0
Then PortOut ($37A, $01) // SDA := 0
Else PortOut ($37A, $00); // SDA := 1
Dly5;
PortOut ($378, $21); // SCL := 1
Dly5;
PortOut ($378, $20); // SCL := 0
Dly5;
Mask := Mask Shr 1
End;
Dly5;
End;
//-----------------------------------------------------------------------------
Function I2C_RdData : Byte;
(* Lectura de entradas *)
Var Counter : Integer;
X : Integer;
Begin
X := 0;
PortOut ($37A, $00); // SDA := 1 = input
PortOut ($378, $10); //Invierte Bus
Dly5;
For Counter := 1 To 8 Do // Ampliado de 8 a 9 para que no diese error
Begin
PortOut ($378, $11); // SCL := 1
Dly5;
X := X Shl 1;
If PortIn ($379) And $40 <> 0 Then Inc (X);
Dly5;
PortOut ($378, $10); // SCL := 0
Dly5;
End;
Result := X;
End;
(*=============================== PCF 8574 ==========*)
procedure Init (X : Byte);
(* Inicializa el periférico *)
begin
I2C_Start;
I2C_WrData (X); // Selecciona el periférico
I2C_WaitAck;
end;
(* ================================ End ===================================== *)
End.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Hay que realizar una ventana parecida para realizar las pruebas.
muchas gracias bactering por este manual que nos estas montando 🙂