Software I²C Library

The mikroC PRO for PIC 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 :
extern sbit Soft_I2C_Scl; Soft I²C Clock line. sbit Soft_I2C_Scl at RC3_bit;
extern sbit Soft_I2C_Sda; Soft I²C Data line. sbit Soft_I2C_Sda at RC4_bit;
extern sbit Soft_I2C_Scl_Direction; Direction of the Soft I²C Clock pin. sbit Soft_I2C_Scl_Direction at TRISC3_bit;
extern sbit Soft_I2C_Sda_Direction; Direction of the Soft I²C Data pin. sbit Soft_I2C_Sda_Direction at TRISC4_bit;

Library Routines

Soft_I2C_Init

Prototype

void Soft_I2C_Init();

Returns

Nothing.

Description

Configures the software I²C module.

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
sbit Soft_I2C_Scl           at RC3_bit;
sbit Soft_I2C_Sda           at RC4_bit;
sbit Soft_I2C_Scl_Direction at TRISC3_bit;
sbit Soft_I2C_Sda_Direction at TRISC4_bit;
// End Software I2C connections

...
Soft_I2C_Init();

Soft_I2C_Start

Prototype

void Soft_I2C_Start(void);

Returns

Nothing.

Description

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

Requires

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

Example
// Issue START signal
Soft_I2C_Start();

Soft_I2C_Read

Prototype

unsigned short Soft_I2C_Read(unsigned int ack);

Returns

One byte from the Slave.

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.

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
unsigned short take;
...
// Read data and send the not_acknowledge signal
take = Soft_I2C_Read(0);

Soft_I2C_Write

Prototype

unsigned short Soft_I2C_Write(unsigned short data_);

Returns

  • 0 if there were no errors.
  • 1 if write collision was detected on the I²C bus.

Description

Sends data byte via the I²C bus.

Parameters :

  • data_: data to be sent

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
unsigned short data_, error;
...
error = Soft_I2C_Write(data_);
error = Soft_I2C_Write(0xA3);

Soft_I2C_Stop

Prototype

void Soft_I2C_Stop(void);

Returns

Nothing.

Description

Issues STOP signal.

Requires

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

Example
// Issue STOP signal
Soft_I2C_Stop();

Soft_I2C_Break

Prototype

void Soft_I2C_Break(void);

Returns

Nothing.

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.

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

// Software I2C connections
sbit Soft_I2C_Scl           at RC0_bit;
sbit Soft_I2C_Sda           at RC1_bit;
sbit Soft_I2C_Scl_Direction at TRISC0_bit;
sbit Soft_I2C_Sda_Direction at TRISC1_bit;
// End Software I2C connections

char counter = 0;

void interrupt {

  if (INTCON.T0IF) {
    if (counter >= 20) {
      Soft_I2C_Break();
      counter = 0;              // reset counter
    }
    else
      counter++;                // increment counter
  
    INTCON.T0IF = 0;            // Clear Timer0 overflow interrupt flag

    }
}

void main() {

  OPTION_REG = 0x04;            // TMR0 prescaler set to 1:32

  ...

  // try Soft_I2C_Init with blocking prevention mechanism
  INTCON.GIE = 1;               // Global interrupt enable
  INTCON.T0IE = 1;              // Enable Timer0 overflow interrupt
  Soft_I2C_Init();
  INTCON.GIE = 0;               // Global interrupt disable

  ...
}

Library Example

The example demonstrates Software I²C Library routines usage. The PIC MCU is connected (SCL, SDA pins) to PCF8583 RTC (real-time clock). Program reads date and time are read from the RTC and prints it on Lcd.

Copy Code To ClipboardCopy Code To Clipboard
// Software I2C connections
sbit Soft_I2C_Scl           at RC3_bit;
sbit Soft_I2C_Sda           at RC4_bit;
sbit Soft_I2C_Scl_Direction at TRISC3_bit;
sbit Soft_I2C_Sda_Direction at TRISC4_bit;
// End Software I2C connections

// LCD module connections
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;

sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// End LCD module connections

char seconds, minutes, hours, day, month, year; // Global date/time variables

//--------------------- Reads time and date information from RTC (PCF8583)
void Read_Time() {

  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
  
}

//-------------------- Formats date and time
void Transform_Time() {
  seconds  =  ((seconds & 0xF0) >> 4)*10 + (seconds & 0x0F);  // Transform seconds
  minutes  =  ((minutes & 0xF0) >> 4)*10 + (minutes & 0x0F);  // Transform months
  hours    =  ((hours & 0xF0)  >> 4)*10  + (hours & 0x0F);    // Transform hours
  year     =   (day & 0xC0) >> 6;                             // Transform year
  day      =  ((day & 0x30) >> 4)*10    + (day & 0x0F);       // Transform day
  month    =  ((month & 0x10)  >> 4)*10 + (month & 0x0F);     // Transform month
}

//-------------------- Output values to LCD
void Display_Time() {

   Lcd_Chr(1, 6, (day / 10)   + 48);    // Print tens digit of day variable
   Lcd_Chr(1, 7, (day % 10)   + 48);    // Print oness digit of day variable
   Lcd_Chr(1, 9, (month / 10) + 48);
   Lcd_Chr(1,10, (month % 10) + 48);
   Lcd_Chr(1,15,  year        + 48);    // Print year variable  (start from year 2010)


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


//------------------ Performs project-wide init
void Init_Main() {

  TRISB = 0;
  PORTB = 0xFF;
  TRISB = 0xff;
  ANSEL  = 0;                // Configure AN pins as digital I/O
  ANSELH = 0;
  C1ON_bit = 0;              // Disable comparators
  C2ON_bit = 0;
  
  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_Chr(1,16,'.');
  Lcd_Out(2,1,"Time:");
  Lcd_Chr(2,8,':');
  Lcd_Chr(2,11,':');
  Lcd_Out(1,12,"201");       // start from year 2010
}

//----------------- Main procedure
void main() {
  Delay_ms(500);
   
  Init_Main();               // Perform initialization

  while (1) {                // Endless loop
    Read_Time();             // Read time from RTC(PCF8583)
    Transform_Time();        // Format date and time
    Display_Time();          // Prepare and display on LCD
  }
}
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