Software I²C Library
The mikroPascal PRO for AVR 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 :
- 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.
- 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 : |
|---|---|---|
var Soft_I2C_Scl_Output : sbit; sfr; external; |
Soft I²C Clock output line. | var Soft_I2C_Scl_Output : sbit at PORTC0_bit; |
var Soft_I2C_Sda_Output : sbit; sfr; external; |
Soft I²C Data output line. | var Soft_I2C_Sda_Output : sbit at PORTC1_bit; |
var Soft_I2C_Scl_Input : sbit; sfr; external; |
Soft I²C Clock input line. | var Soft_I2C_Scl_Input : sbit at PINC0_bit; |
var Soft_I2C_Sda_Input : sbit; sfr; external; |
Soft I²C Data input line. | var Soft_I2C_Sda_Input : sbit at PINC1_bit; |
var Soft_I2C_Scl_Pin_Direction : sbit; sfr; external; |
Direction of the Soft I²C Clock pin. | var Soft_I2C_Scl_Direction : sbit at DDC0_bit; |
var Soft_I2C_Sda_Pin_Direction : sbit; sfr; external; |
Direction of the Soft I²C Data pin. | var Soft_I2C_Sda_Direction : sbit at DDC1_bit; |
Library Routines
Soft_I2C_Init
| Prototype |
procedure Soft_I2C_Init(); |
|---|---|
| Returns |
Nothing. |
| Description |
Configures the software I²C module. |
| Requires |
Global variables :
|
| Example |
// Soft_I2C pinout definition var Soft_I2C_Scl_Output : sbit at PORTC0_bit; var Soft_I2C_Sda_Output : sbit at PORTC1_bit; var Soft_I2C_Scl_Input : sbit at PINC0_bit; var Soft_I2C_Sda_Input : sbit at PINC1_bit; var Soft_I2C_Scl_Direction : sbit at DDC0_bit; var Soft_I2C_Sda_Direction : sbit at DDC1_bit; // End of Soft_I2C pinout definition ... Soft_I2C_Init(); |
Soft_I2C_Start
| Prototype |
procedure Soft_I2C_Start(); |
|---|---|
| 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 |
function Soft_I2C_Read(ack: word): byte; |
|---|---|
| Returns |
One byte from the Slave. |
| Description |
Reads one byte from the slave. Parameters :
|
| 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 : word; ... // Read data and send the not_acknowledge signal take := Soft_I2C_Read(0); |
Soft_I2C_Write
| Prototype |
function Soft_I2C_Write(data_: byte): byte; |
|---|---|
| Returns |
|
| Description |
Sends data byte via the I²C bus. Parameters :
|
| 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(0xA3); |
Soft_I2C_Stop
| Prototype |
procedure Soft_I2C_Stop(); |
|---|---|
| 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 |
procedure Soft_I2C_Break(); |
|---|---|
| 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 |
// Soft_I2C pinout definition
var Soft_I2C_Scl_Output : sbit at PORTC0_bit;
var Soft_I2C_Sda_Output : sbit at PORTC1_bit;
var Soft_I2C_Scl_Input : sbit at PINC0_bit;
var Soft_I2C_Sda_Input : sbit at PINC1_bit;
var Soft_I2C_Scl_Direction : sbit at DDC0_bit;
var Soft_I2C_Sda_Direction : sbit at DDC1_bit;
// End of Soft_I2C pinout definition
var counter : byte;
procedure Timer0Overflow_ISR(); org 0x12;
begin
counter := 0;
if (counter >= 20)
begin
Soft_I2C_Break();
counter := 0; // reset counter
end
else
Inc(counter); // increment counter
end;
begin
TOIE0_bit := 1; // Timer0 overflow interrupt enable
TCCR0_bit := 5; // Start timer with 1024 prescaler
SREG_I_bit := 0; // Interrupt disable
...
// try Soft_I2C_Init with blocking prevention mechanism
SREG_I_bit := 1; // Interrupt enable
Soft_I2C_Init();
SREG_I_bit := 0; // Interrupt disable
...
end.
|
Library Example
The example demonstrates Software I²C Library routines usage. The AVR 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.
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 PORTC0_bit;
Soft_I2C_Sda_Output : sbit at PORTC1_bit;
Soft_I2C_Scl_Input : sbit at PINC0_bit;
Soft_I2C_Sda_Input : sbit at PINC1_bit;
Soft_I2C_Scl_Direction : sbit at DDC0_bit;
Soft_I2C_Sda_Direction : sbit at DDC1_bit;
// End Software I2C connections
// LCD module connections
var LCD_RS : sbit at PORTD2_bit;
LCD_EN : sbit at PORTD3_bit;
LCD_D4 : sbit at PORTD4_bit;
LCD_D5 : sbit at PORTD5_bit;
LCD_D6 : sbit at PORTD6_bit;
LCD_D7 : sbit at PORTD7_bit;
LCD_RS_Direction : sbit at DDD2_bit;
LCD_EN_Direction : sbit at DDD3_bit;
LCD_D4_Direction : sbit at DDD4_bit;
LCD_D5_Direction : sbit at DDD5_bit;
LCD_D6_Direction : sbit at DDD6_bit;
LCD_D7_Direction : sbit at DDD7_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 + 56); // Print year vaiable + 8 (start from year 2008)
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,'200');
end;
//----------------- Main procedure
begin
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!




