Two wire interface TWI/I2C

Required knowledge: [HW] Kontrollermoodul, [HW] Kombomoodul, [AVR] Katkestused,
[LIB] Kahejuhtmeliides TWI, [LIB] Graafiline LCD

Theory

Two Wire Interface (TWI) is most often known by the abbreviation I2C, which is the patented name of the same protocol by its creator Philips. I2C is an acronym for “Inter-Integrated Circuit”, meaning the interface is intended for on-board use. In everyday speech, simpler pronunciations like “i-square-c” or “i-two-c” are often used.

I2C uses two lines: a bidirectional data line (Serial Data line, SDA) and a clock line (Serial Clock line, SCL). All device outputs on the bus must be open-drain (open-collector), and both lines must have pull-up resistors (R1 and R2 in the schematic). This allows many devices to share one I2C bus without burning outputs.

I2C bus

Each device on the I2C bus has a unique address, which is 7 or 10 bits depending on the device. Common clock frequencies are 10 kHz (Low-speed mode), 100 kHz (Standard mode), and 400 kHz (Fast mode). Newer standards allow higher speeds, but they are less common. The clock frequency determines the data rate because one bit is transmitted per clock. The maximum number of devices on one bus is limited by the address space and the added electrical capacitance. The maximum bus capacitance is 400 pF, which means the maximum I2C cable length is only a few meters.

In the I2C protocol, devices are divided into masters and slaves. There is no fixed maximum number of masters or slaves, and devices can change roles. Four different bus operations are defined:

  • master sends
  • master receives
  • slave sends
  • slave receives

The master initially is usually in transmit mode, first sending a start bit, followed by the 7-bit slave address and a read/write bit. If the slave with that address exists, it responds with an ACK bit (pulls the line low). After that the master either continues sending or switches to receiving.

The start bit is defined as pulling SDA low while SCL is high. The stop bit is defined as releasing SDA high while SCL is high. All other level changes must occur when SCL is low.

Writing and reading are done byte by byte, and each successful byte exchange must be followed by an ACK signal from the receiving side. When the transfer is finished, the master sends either a stop bit or a new start bit with an address.

Practice

RTC module DS3231

In Atmel controllers, I2C is called the TWI module. Most of the TWI protocol work is done by the microcontroller hardware, but a software library is still required to simplify writing to and reading from the bus.

The example shows use of the real-time clock module (RTC) DS3231 with a HomeLab III generation controller. The real-time clock has its own Li battery as autonomous power, and after initial time setup there is no need to reinitialize, because the RTC keeps time on its own even without external power for years. Thus after initialization the module can be used only for accurate time reading without worrying about time drift or initial state.

// HomeLab RTC module DS3231 example program
// The module is connected to PORTE TWI bus: SDA - PE0, SCL - PE1
#include <homelab/pin.h>
#include <homelab/module/lcd_gfx.h>
#include <homelab/xmega/clksys_driver.h>
#include <homelab/xmega/twi_master_driver.h>
#include <avr/interrupt.h>
 
// DS1307 TWI address
#define DS3231 0b1101000
 
// Define TWI master
TWI_Master_t twiMaster;
 
// TWI interrupt vector,
// handles background writes and reads on the TWI bus
ISR(TWIE_TWIM_vect)
{
  TWI_MasterInterruptHandler(&twiMaster);
}
 
// Main program
int main(void)
{
  char buff[30];
  uint8_t time[8];
  uint8_t seconds = 0, minutes, hours;
  uint8_t date, month, year;
 
  // LCD initialization
  lcd_gfx_init();
  lcd_gfx_write_string("I2C RTC Module");
 
  // Start TWIE bus in master mode with low priority interrupt,
  // TWI speed 100 kHz with 32 MHz system clock
  TWI_MasterInit(&twiMaster, &TWIE,TWI_MASTER_INTLVL_LO_gc,
                                TWI_BAUD(32000000, 100000));
  // Enable low priority interrupts
  PMIC.CTRL |= PMIC_LOLVLEN_bm;
  sei();
 
  // Set initial time
  time[0] = 0;          // Address where time is written
  time[1] = 0;          // Seconds
  time[2] = (4<<4) | 4; // Minutes (44)
  time[3] = (1<<4) | 1; // Hours (11)
  time[4] = 3;          // Day of week (3)
  time[5] = (0<<4) | 5; // Date (5)
  time[6] = (0<<4) | 2; // Month (2)
  time[7] = (1<<4) | 4; // Year (14)
 
  // Start DS3231 clock (if not already running)
  TWI_MasterWrite(&twiMaster, DS3231, time, 8);
 
  // Infinite loop
  while (1)
  {
    // Read time again from DS3231 registers
    TWI_MasterWriteRead(&twiMaster,DS3231,(uint8_t *)0x00,1,7);
 
    // Wait for response
    while (twiMaster.status != TWIM_STATUS_READY);
 
    // Convert register values to time and date
    seconds = ((twiMaster.readData[0]>>4)*10) + (twiMaster.readData[0] & 0x0F);
    minutes = ((twiMaster.readData[1]>>4)*10) + (twiMaster.readData[1] & 0x0F);
    hours   = ((twiMaster.readData[2]>>4)*10) + (twiMaster.readData[2] & 0x0F);
    date    = ((twiMaster.readData[4]>>4)*10) + (twiMaster.readData[4] & 0x0F);
    month   = ((twiMaster.readData[5]>>4)*10) + (twiMaster.readData[5] & 0x0F);
    year    = ((twiMaster.readData[6]>>4)*10) + (twiMaster.readData[6] & 0x0F);
 
    // Display time on LCD
    sprintf(buff,"%02d:%02d:%02d  %02d.%02d.20%02d",
            hours,minutes,seconds,date,month,year);
    lcd_gfx_goto_char_xy(2,2);
    lcd_gfx_write_string(buff);
    _delay_ms(100);
  }
}
en/examples/communication/i2c.txt · Last modified: by 127.0.0.1
CC Attribution-Share Alike 4.0 International
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0