Software I²C Library
The mikroC PRO for PIC32 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 :
  Important :
- This library implements time-based activities, so interrupts need to be disabled when using Software I²C.
- All I²C Library functions are blocking-call functions (they are waiting for I²C clock line to become logical one).
- The pins used for the Software I²C communication should be connected to the pull-up resistors. Turning off the LEDs connected to these pins may also be required.
- Every Software I²C library routine has its own counterpart in Hardware I²C library, except I2C_Repeated_Start.Soft_I2C_Startis used instead ofI2C_Repeated_Start.
- Working clock frequency of the Software I²C is 20kHz.
External dependencies of Software I²C Library
| The following variables must be defined in all projects using Software I²C Library: | Description : | Example : | 
|---|---|---|
| extern atomic sbit Soft_I2C_Scl; | Soft I²C Clock line. | sbit Soft_I2C_Scl at RB11_bit; | 
| extern atomic sbit Soft_I2C_Sda; | Soft I²C Data line. | sbit Soft_I2C_Sda at RB12_bit; | 
| extern atomic sbit Soft_I2C_Scl_Direction; | Direction of the Soft I²C Clock pin. | sbit Soft_I2C_Scl_Direction at TRISB11_bit; | 
| extern atomic sbit Soft_I2C_Sda_Direction; | Direction of the Soft I²C Data pin. | sbit Soft_I2C_Sda_Direction at TRISB12_bit; | 
Library Routines
Soft_I2C_Init
| Prototype | void Soft_I2C_Init(); | 
|---|---|
| Description | Configures the software I²C module. | 
| Parameters | None. | 
| Returns | Nothing. | 
| Requires | Global variables : 
 | 
| Example | // Software I2C connections sbit Soft_I2C_Scl at RB11_bit; sbit Soft_I2C_Sda at RB12_bit; sbit Soft_I2C_Scl_Direction at TRISB11_bit; sbit Soft_I2C_Sda_Direction at TRISB12_bit; // End Software I2C connections ... Soft_I2C_Init(); | 
| Notes | None. | 
Soft_I2C_Start
| Prototype | void 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 | unsigned short Soft_I2C_Read(unsigned int ack); | 
|---|---|
| Description | Reads one byte from the slave. | 
| Parameters | 
 | 
| 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 | unsigned short take; ... // Read data and send the not_acknowledge signal take = Soft_I2C_Read(0); | 
| Notes | None. | 
Soft_I2C_Write
| Prototype | unsigned short Soft_I2C_Write(unsigned short data_); | 
|---|---|
| Description | Sends data byte via the I²C bus. | 
| Parameters | 
 | 
| Returns | 
 | 
| 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); | 
| Notes | None. | 
Soft_I2C_Stop
| Prototype | void 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 | void 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 | // 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 Timer1Int() org IVT_ADDR_T1INTERRUPT {
  if (counter >= 20) {
    Soft_I2C_Break();
    counter = 0;                // reset counter
  }
  
  else
    counter++;                  // increment counter
  
  T1IF_bit = 0;                 // Clear Timer1 overflow interrupt flag
}
void main() {
  ...
  
  // try Soft_I2C_Init with blocking prevention mechanism
  IPC0   = IPC0 | 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
} | 
| 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 PIC32 MCU is connected (SCL, SDA pins) to PCF8583 RTC (real-time clock). Program sends date/time to RTC.
char seconds, minutes, hours, day, month, year;    // Global date/time variables
// Software I2C connections
sbit Soft_I2C_Scl           at RF3_bit;
sbit Soft_I2C_Sda           at RF4_bit;
sbit Soft_I2C_Scl_Direction at TRISF3_bit;
sbit Soft_I2C_Sda_Direction at TRISF4_bit;
// End Software I2C connections
// LCD module connections
sbit LCD_RS at LATB2_bit;
sbit LCD_EN at LATB3_bit;
sbit LCD_D4 at LATB4_bit;
sbit LCD_D5 at LATB5_bit;
sbit LCD_D6 at LATB6_bit;
sbit LCD_D7 at LATB7_bit;
sbit LCD_RS_Direction at TRISB2_bit;
sbit LCD_EN_Direction at TRISB3_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;
// End LCD module connections
//--------------------- 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        + 49);    // Print year vaiable + 1 (start from year 2011)
   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() {
  CHECON = 0x30;
  AD1PCFG = 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,"201");
}
//----------------- Main procedure
void main() {
  Delay_ms(100);
  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
    Delay_ms(1000);          // Wait 1 second
  }
}
What do you think about this topic ? Send us feedback!




