Software I2C Unit

This is a new library unit for carrying out I2C communication in the master mode. Since it is software based, any port pins may be used. Clock-stretching is included, along with a bit of error detection. Perhaps some energetic person will consider adding slave mode to it.


I2C_Start() and I2C_Stop() are the usual commands employed  to start and stop I2C communications. I2CPoll() is  used to sense whether the slave device is alive and ready  to respond. It's also useful for waiting until an eeprom  has completed its write cycle. It sets the global boolean  variable ACK_NAK_FLAG indicating whether the device  responded properly or timed out.

The two high-level commands are I2C_Receive() and  I2C_Send().  The commands are described, below.

This is an original library unit, but includes some parameter passing improvements suggested by Philippe Paternotte.

Compilation Constants

There are four compilation constants with no defaults which need to be set in the calling program. For example:

{$DEFINE SDA_PORT 'PortB'}  // I2C SDA port
{$DEFINE SDA_PIN 0}         // and its pin number 

{$DEFINE SCL_PORT 'PortB'}  // I2C SCL port 
{$DEFINE SCL_PIN 1}         // and its pin number

Global Constants and Variables

There are two global constants for your convenience:

    ACK = TRUE;
    NAK = FALSE;

And there is one global variable, as mentioned above:

   ACK_NAK_FLAG : boolean;      


The first two low-level commands require no parameters and are self-explanatory.

procedure I2CStart;

procedure I2CStop;

The next two commands are high-level and the ones you're apt to use most frequently. Again, their meanings should be clear.

procedure I2CSend(I2CByte : byte);

function I2CReceive(I2CAck : boolean) : byte;

Finally, the last command is typically used for error detection and may or may not be needed in your programs.

procedure I2CPoll(device : byte);

The argument contains the base device number to check on (R/W bit clear).  The procedure checks if the device is ready or gives up after 256 attempts. The global variable ACK_NAK_FLAG indicates success or not.

Add It to Your Library Collection

And here's the new library unit, "SoftI2C.pas" for you to download:

Be sure to read over the source code for additional details on how to use it.

Try It Out

If you'd like to see it in operation, then head over to the exercises. The barometer sensor project uses I2C. Click here to go to it.


  1. Hi,

    Thanks for your code exmple.
    I'try to learn about I2C comunication.
    Finaly, want to be able to control the
    PCA9685 chip in a "Servo controller shield".

    I don't understand the rol command. Is it a logic-shift (left or right)? I'm 'translating' the code to mikroPascal (from Things go fine, only the 'rol'...

    Kind regards! Marcel
    (next time, Illtry to login with the google acount)