no way to compare when less than two revisions

Differences

This shows you the differences between two versions of the page.


en:examples:communication:i2c [2026/02/19 11:30] (current) – created - external edit 127.0.0.1
Line 1: Line 1:
 +<pagebreak>
 +====== Two wire interface TWI/I2C ======
 +//Required knowledge: 
 +[HW] [[et:hardware:homelab:controller]], [HW] [[et:hardware:homelab:combo]],
 +[AVR] [[et:avr:interrupts]], \\
 +[LIB] [[et:software:homelab:library:twi]], [LIB] [[et:software:homelab:library:module:lcd_graphic]]//
 +
 +===== Theory =====
 +
 +Two Wire Interface (TWI) is most often known by the abbreviation I<sup>2</sup>C, which is the patented name of the same protocol by its creator Philips. I<sup>2</sup>C 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.
 +
 +I<sup>2</sup>C 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 I<sup>2</sup>C bus without burning outputs.
 +
 +[{{ :examples:communication:i2c:twi.png?580 |I2C bus}}]
 +~~CL~~
 +
 +Each device on the I<sup>2</sup>C 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 I<sup>2</sup>C cable length is only a few meters.
 +
 +In the I<sup>2</sup>C 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.
 +
 +~~CL~~
 +
 +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 =====
 +
 +[{{ :examples:communication:i2c:mini-rtc-moodul.jpg?220|RTC module DS3231}}]
 +
 +In Atmel controllers, I<sup>2</sup>C 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.
 +~~CL~~
 +~~CL~~
 +~~CL~~
 +<code c>
 +// 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);
 +  }
 +}
 +</code>
  
en/examples/communication/i2c.txt · Last modified: 2026/02/19 11:30 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