Software I²C Library

The mikroPascal PRO for dsPIC30/33 and PIC24 provides routines for implementing Software I²C communication. These routines are hardware independent and can be used with any MCU. The Software I²C library enables you to use MCU as Master in I²C communication. Multi-master mode is not supported.

  Important :

External dependencies of Software I²C Library

The following variables must be defined in all projects using Software I²C Library: Description : Example :
var Soft_I2C_Scl : sbit; sfr; external; Soft I²C Clock line. var Soft_I2C_Scl : sbit at RF3_bit;
var Soft_I2C_Sda : sbit; sfr; external; Soft I²C Data line. var Soft_I2C_Sda : sbit at RF2_bit;
var Soft_I2C_Scl_Direction : sbit; sfr; external; Direction of the Soft I²C Clock pin. var Soft_I2C_Scl_Direction : sbit at TRISF3_bit;
var Soft_I2C_Sda_Direction : sbit; sfr; external; Direction of the Soft I²C Data pin. var Soft_I2C_Sda_Direction : sbit at TRISF2_bit;

Library Routines

Soft_I2C_Init

Prototype

procedure Soft_I2C_Init();

Description

Configures the software I²C module.

Parameters

None.

Returns

Nothing.

Requires Global variables :
  • Soft_I2C_Scl: Soft I²C clock line
  • Soft_I2C_Sda: Soft I²C data line
  • Soft_I2C_Scl_Pin_Direction: Direction of the Soft I²C clock pin
  • Soft_I2C_Sda_Pin_Direction: Direction of the Soft I²C data pin
must be defined before using this function.
Example
// Software I2C connections
var Soft_I2C_Scl           : sbit at RF3_bit;
    Soft_I2C_Sda           : sbit at RF2_bit;
    Soft_I2C_Scl_Direction : sbit at TRISF3_bit;
    Soft_I2C_Sda_Direction : sbit at TRISF2_bit;
// End Software I2C connections
...
Soft_I2C_Init();
Notes

None.

Soft_I2C_Start

Prototype

procedure Soft_I2C_Start();

Description

Determines if the I²C bus is free and issues START signal.

Parameters

None.

Returns

Nothing.

Requires

Software I²C must be configured before using this function. See Soft_I2C_Init routine.

Example
// Issue START signal
Soft_I2C_Start();
Notes

None.

Soft_I2C_Read

Prototype

function Soft_I2C_Read(ack : word) : byte;

Description

Reads one byte from the slave.

Parameters
  • ack: acknowledge signal parameter. If the ack==0 not acknowledge signal will be sent after reading, otherwise the acknowledge signal will be sent.
Returns

One byte from the Slave.

Requires

Soft I²C must be configured before using this function. See Soft_I2C_Init routine.

Also, START signal needs to be issued in order to use this function. See Soft_I2C_Start routine.

Example
var take : byte;
...
// Read data and send the not_acknowledge signal
take := Soft_I2C_Read(0);
Notes

None.

Soft_I2C_Write

Prototype

function Soft_I2C_Write(data_ : byte) : byte;

Description

Sends data byte via the I²C bus.

Parameters
  • data_: data to be sent
Returns
  • 0 if there were no errors.
  • 1 if write collision was detected on the I²C bus.
Requires

Soft I²C must be configured before using this function. See Soft_I2C_Init routine.

Also, START signal needs to be issued in order to use this function. See Soft_I2C_Start routine.

Example
var data_, error : byte;
...
error := Soft_I2C_Write(data_);
error := Soft_I2C_Write($A3);
Notes

None.

Soft_I2C_Stop

Prototype

procedure Soft_I2C_Stop();

Description

Issues STOP signal.

Parameters

None.

Returns

Nothing.

Requires

Soft I²C must be configured before using this function. See Soft_I2C_Init routine.

Example
// Issue STOP signal
Soft_I2C_Stop();
Notes

None.

Soft_I2C_Break

Prototype

procedure Soft_I2C_Break();

Description

All Software I²C Library functions can block the program flow (see note at the top of this page). Calling this routine from interrupt will unblock the program execution. This mechanism is similar to WDT.

Parameters

None.

Returns

Nothing.

Requires Nothing.
Example
var data1, error, counter : byte;

procedure Timer1Int(); org IVT_ADDR_T1INTERRUPT;
begin
  counter := 0;
  if (counter >= 20)
    begin
      Soft_I2C_Break();
      counter := 0;                // reset counter
    end
  else
    Inc(counter);                  // increment counter
 
  T1IF_bit := 0;                 // Clear Timer1 overflow interrupt flag
end;

begin 

  ...

  // try Soft_I2C_Init with blocking prevention mechanism
  IPC0   := IPC0 or 0x1000;       // Interrupt priority level = 1 
  T1IE_bit := 1;                 // Enable Timer1 interrupts
  T1CON := 0x8030;               // Timer1 ON, internal clock FCY, prescaler 1:256
  Soft_I2C_Init();
  T1IE_bit := 0;                 // Disable Timer1 interrupts

end.
Notes

Interrupts should be disabled before using Software I²C routines again (see note at the top of this page).

Library Example

The example demonstrates use of the Software I²C Library. The dsPIC30/33 or PIC24 MCU is connected (SCL, SDA pins) to PCF8583 RTC (real-time clock). Program sends date/time to RTC.

Copy Code To ClipboardCopy Code To Clipboard
program RTC_Read;

var seconds, minutes, hours, day, month, year : byte;    // Global date/time variables

// Software I2C connections
var Soft_I2C_Scl           : sbit at RF3_bit;
    Soft_I2C_Sda           : sbit at RF2_bit;
    Soft_I2C_Scl_Direction : sbit at TRISF3_bit;
    Soft_I2C_Sda_Direction : sbit at TRISF2_bit;
// End Software I2C connections

// LCD module connections
var LCD_RS : sbit at LATD0_bit;
var LCD_EN : sbit at LATD1_bit;
var LCD_D4 : sbit at LATB0_bit;
var LCD_D5 : sbit at LATB1_bit;
var LCD_D6 : sbit at LATB2_bit;
var LCD_D7 : sbit at LATB3_bit;

var LCD_RS_Direction : sbit at TRISD0_bit;
var LCD_EN_Direction : sbit at TRISD1_bit;
var LCD_D4_Direction : sbit at TRISB0_bit;
var LCD_D5_Direction : sbit at TRISB1_bit;
var LCD_D6_Direction : sbit at TRISB2_bit;
var LCD_D7_Direction : sbit at TRISB3_bit;
// End LCD module connections

//--------------------- Reads time and date information from RTC (PCF8583)
procedure Read_Time();
  begin
    Soft_I2C_Start();               // Issue start signal
    Soft_I2C_Write(0xA0);           // Address PCF8583, see PCF8583 datasheet
    Soft_I2C_Write(2);              // Start from address 2
    Soft_I2C_Start();               // Issue repeated start signal
    Soft_I2C_Write(0xA1);           // Address PCF8583 for reading R/W=1
    seconds := Soft_I2C_Read(1);    // Read seconds byte
    minutes := Soft_I2C_Read(1);    // Read minutes byte
    hours := Soft_I2C_Read(1);      // Read hours byte
    day := Soft_I2C_Read(1);        // Read year/day byte
    month := Soft_I2C_Read(0);      // Read weekday/month byte}

    Soft_I2C_Stop();                // Issue stop signal}
  end;

//-------------------- Formats date and time
procedure Transform_Time();
  begin
    seconds :=  ((seconds and 0xF0) shr 4)*10 + (seconds and 0x0F);  // Transform seconds
    minutes :=  ((minutes and 0xF0) shr 4)*10 + (minutes and 0x0F);  // Transform months
    hours   :=  ((hours and 0xF0)  shr 4)*10  + (hours and 0x0F);    // Transform hours
    year    :=   (day and 0xC0) shr 6;                               // Transform year
    day     :=  ((day and 0x30) shr 4)*10    + (day and 0x0F);       // Transform day
    month   :=  ((month and 0x10)  shr 4)*10 + (month and 0x0F);     // Transform month
  end;

//-------------------- Output values to LCD
procedure Display_Time();
  begin
     Lcd_Chr(1, 6, (day / 10)   + 48);    // Print tens digit of day variable
     Lcd_Chr(1, 7, (day mod 10)   + 48);  // Print oness digit of day variable
     Lcd_Chr(1, 9, (month / 10) + 48);
     Lcd_Chr(1,10, (month mod 10) + 48);
     Lcd_Chr(1,15,  year        + 57);    // Print year vaiable + 9 (start from year 2009)

     Lcd_Chr(2, 6, (hours / 10)   + 48);
     Lcd_Chr(2, 7, (hours mod 10)   + 48);
     Lcd_Chr(2, 9, (minutes / 10) + 48);
     Lcd_Chr(2,10, (minutes mod 10) + 48);
     Lcd_Chr(2,12, (seconds / 10) + 48);
     Lcd_Chr(2,13, (seconds mod 10) + 48);
  end;

//------------------ Performs project-wide init
procedure Init_Main();
  begin
    ADPCFG := 0xFFFF;           // initialize AN pins as digital

    Soft_I2C_Init();           // Initialize Soft I2C communication
    Lcd_Init();                // Initialize LCD
    Lcd_Cmd(_LCD_CLEAR);       // Clear LCD display
    Lcd_Cmd(_LCD_CURSOR_OFF);  // Turn cursor off

    Lcd_Out(1,1,'Date:');      // Prepare and output static text on LCD
    Lcd_Chr(1,8,':');
    Lcd_Chr(1,11,':');
    Lcd_Out(2,1,'Time:');
    Lcd_Chr(2,8,':');
    Lcd_Chr(2,11,':');
    Lcd_Out(1,12,'200');
  end;

//----------------- Main procedure
  begin

   Delay_ms(1000);

   Init_Main();                 // Perform initialization

    while TRUE do               // Endless loop
      begin
        Read_Time();            // Read time from RTC(PCF8583)
        Transform_Time();       // Format date and time
        Display_Time();         // Prepare and display on LCD
      end;
  end.
Copyright (c) 2002-2012 mikroElektronika. All rights reserved.
What do you think about this topic ? Send us feedback!
Want more examples and libraries? 
Find them on LibStock - A place for the code