Software I²C Library
The mikroPascal PRO for ARM 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.

- This library implements time-based activities, so interrupts need to be disabled when using Software I²C.
- All Software 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_Start
is used instead ofI2C_Repeated_Start
. - Working clock frequency of the Software I²C is 20kHz.
External dependencies of Software I²C Library
Stellaris
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 GPIO_PORTD_DATA3_bit; |
var Soft_I2C_Sda : sbit; sfr; external; |
Soft I²C Data line. | var Soft_I2C_Sda : sbit at GPIO_PORTD_DATA4_bit; |
var Soft_I2C_Scl_Direction : sbit; sfr; external; |
Direction of the Soft I²C Clock pin. | var Soft_I2C_Scl_Direction : sbit at GPIO_PORTD_DIR3_bit; |
var Soft_I2C_Sda_Direction : sbit; sfr; external; |
Direction of the Soft I²C Data pin. | var Soft_I2C_Sda_Direction : sbit at GPIO_PORTD_DIR4_bit; |
STM32
The following variables must be defined in all projects using Software I²C Library: | Description : | Example : |
---|---|---|
var Soft_I2C_Scl_Output : sbit; sfr; external; |
Soft I²C Clock Output line. | var Soft_I2C_Scl_Output : sbit at GPIOD_ODR.B3; |
var Soft_I2C_Sda_Output : sbit; sfr; external; |
Soft I²C Data Output line. | var Soft_I2C_Sda_Output : sbit at GPIOD_ODR.B4; |
var Soft_I2C_Scl_Input : sbit; sfr; external; |
Soft I²C Clock Input pin. | var Soft_I2C_Scl_Input : sbit at GPIOD_IDR.B3; |
var Soft_I2C_Sda_Input : sbit; sfr; external; |
Soft I²C Data Input pin. | var Soft_I2C_Sda_Input : sbit at GPIOD_IDR.B4; |
Library Routines
Soft_I2C_Init
Prototype |
procedure Soft_I2C_Init(); |
---|---|
Description |
Configures the software I²C module. |
Parameters |
None. |
Returns |
Nothing. |
Requires |
External dependencies of the library from the top of the page must be defined before using this function. |
Example |
Stellaris// Software I2C connections var Soft_I2C_Scl : sbit at GPIO_PORTD_DATA3_bit; Soft_I2C_Sda : sbit at GPIO_PORTD_DATA4_bit; Soft_I2C_Scl_Direction : sbit at GPIO_PORTD_DIR3_bit; Soft_I2C_Sda_Direction : sbit at GPIO_PORTD_DIR4_bit; // End Software I2C connections ... Soft_I2C_Init(); STM32// Software I2C connections var Soft_I2C_Scl_Output : sbit at GPIOD_ODR.B3; Soft_I2C_Sda_Output : sbit at GPIOD_ODR.B4; Soft_I2C_Scl_Input : sbit at GPIOD_IDR.B3; Soft_I2C_Sda_Input : sbit at GPIOD_IDR.B4; // 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 |
|
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 |
|
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 |
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 |
|
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 ARM MCU is connected (SCL, SDA pins) to PCF8583 RTC (real-time clock). Program sends date/time to RTC.
Stellaris
program RTC_Read; var seconds, minutes, hours, day, month, year : byte; // Global date/time variables // Software I2C connections var Soft_I2C_Scl : sbit at GPIO_PORTD_DATA3_bit; Soft_I2C_Sda : sbit at GPIO_PORTD_DATA4_bit; Soft_I2C_Scl_Direction : sbit at GPIO_PORTD_DIR3_bit; Soft_I2C_Sda_Direction : sbit at GPIO_PORTD_DIR4_bit; // End Software I2C connections // LCD module connections var LCD_RS : sbit at GPIO_PORTA_DATA2_bit; var LCD_EN : sbit at GPIO_PORTA_DATA3_bit; var LCD_D4 : sbit at GPIO_PORTA_DATA4_bit; var LCD_D5 : sbit at GPIO_PORTA_DATA5_bit; var LCD_D6 : sbit at GPIO_PORTA_DATA6_bit; var LCD_D7 : sbit at GPIO_PORTA_DATA7_bit; var LCD_RS_Direction : sbit at GPIO_PORTA_DIR2_bit; var LCD_EN_Direction : sbit at GPIO_PORTA_DIR3_bit; var LCD_D4_Direction : sbit at GPIO_PORTA_DIR4_bit; var LCD_D5_Direction : sbit at GPIO_PORTA_DIR5_bit; var LCD_D6_Direction : sbit at GPIO_PORTA_DIR6_bit; var LCD_D7_Direction : sbit at GPIO_PORTA_DIR7_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 + 49); // Print year vaiable + 1 (start from year 2011) 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 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'); 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.
STM32
program RTC_Read; var seconds, minutes, hours, day, month, year : byte; // Global date/time variables // Software I2C connections var Soft_I2C_Scl_Output : sbit at GPIOD_ODR.B3; Soft_I2C_Sda_Output : sbit at GPIOD_ODR.B4; Soft_I2C_Scl_Input : sbit at GPIOD_IDR.B3; Soft_I2C_Sda_Input : sbit at GPIOD_IDR.B4; // End Software I2C connections // LCD module connections var LCD_RS : sbit at GPIOD_ODR.B10; var LCD_EN : sbit at GPIOD_ODR.B11; var LCD_D4 : sbit at GPIOD_ODR.B12; var LCD_D5 : sbit at GPIOD_ODR.B13; var LCD_D6 : sbit at GPIOD_ODR.B14; var LCD_D7 : sbit at GPIOD_ODR.B15; // 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 + 49); // Print year vaiable + 1 (start from year 2011) 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 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'); 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.
What do you think about this topic ? Send us feedback!